Merge "Fix immediate invalidations for moved movable content" into androidx-main
diff --git a/activity/activity-ktx/api/current.ignore b/activity/activity-ktx/api/current.ignore
deleted file mode 100644
index 1c56f4f..0000000
--- a/activity/activity-ktx/api/current.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.activity.PipHintTrackerKt:
-    Removed class androidx.activity.PipHintTrackerKt
diff --git a/activity/activity-ktx/api/current.txt b/activity/activity-ktx/api/current.txt
index 4023c72..d9a358f 100644
--- a/activity/activity-ktx/api/current.txt
+++ b/activity/activity-ktx/api/current.txt
@@ -6,6 +6,10 @@
     method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.activity.ComponentActivity, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
   }
 
+  public final class PipHintTrackerKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static suspend Object? trackPipAnimationHintView(android.app.Activity, android.view.View view, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
 }
 
 package androidx.activity.result {
diff --git a/activity/activity-ktx/api/public_plus_experimental_current.txt b/activity/activity-ktx/api/public_plus_experimental_current.txt
index 980229c..d9a358f 100644
--- a/activity/activity-ktx/api/public_plus_experimental_current.txt
+++ b/activity/activity-ktx/api/public_plus_experimental_current.txt
@@ -7,7 +7,7 @@
   }
 
   public final class PipHintTrackerKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) @kotlinx.coroutines.ExperimentalCoroutinesApi public static suspend Object? trackPipAnimationHintView(android.app.Activity, android.view.View view, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static suspend Object? trackPipAnimationHintView(android.app.Activity, android.view.View view, kotlin.coroutines.Continuation<? super kotlin.Unit>);
   }
 
 }
diff --git a/activity/activity-ktx/api/restricted_current.ignore b/activity/activity-ktx/api/restricted_current.ignore
deleted file mode 100644
index 1c56f4f..0000000
--- a/activity/activity-ktx/api/restricted_current.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.activity.PipHintTrackerKt:
-    Removed class androidx.activity.PipHintTrackerKt
diff --git a/activity/activity-ktx/api/restricted_current.txt b/activity/activity-ktx/api/restricted_current.txt
index 4023c72..d9a358f 100644
--- a/activity/activity-ktx/api/restricted_current.txt
+++ b/activity/activity-ktx/api/restricted_current.txt
@@ -6,6 +6,10 @@
     method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM> viewModels(androidx.activity.ComponentActivity, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras>? extrasProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
   }
 
+  public final class PipHintTrackerKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static suspend Object? trackPipAnimationHintView(android.app.Activity, android.view.View view, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+  }
+
 }
 
 package androidx.activity.result {
diff --git a/activity/activity-ktx/build.gradle b/activity/activity-ktx/build.gradle
index 9505501..2d5ca30 100644
--- a/activity/activity-ktx/build.gradle
+++ b/activity/activity-ktx/build.gradle
@@ -26,7 +26,7 @@
 dependencies {
 
     api(project(":activity:activity"))
-    api("androidx.core:core-ktx:1.1.0") {
+    api("androidx.core:core-ktx:1.9.0") {
         because "Mirror activity dependency graph for -ktx artifacts"
     }
     api("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") {
@@ -59,4 +59,4 @@
 
 android {
     namespace "androidx.activity.ktx"
-}
\ No newline at end of file
+}
diff --git a/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt b/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
index 0801c64..710602a 100644
--- a/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
+++ b/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
@@ -23,7 +23,6 @@
 import android.view.View
 import android.view.ViewTreeObserver
 import androidx.annotation.RequiresApi
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.callbackFlow
 
@@ -37,7 +36,6 @@
  *
  * @param view the view to use as the reference for the source rect hint
  */
-@ExperimentalCoroutinesApi
 @RequiresApi(Build.VERSION_CODES.O)
 public suspend fun Activity.trackPipAnimationHintView(view: View) {
     // Returns a rect of the window coordinates of a view.
diff --git a/activity/activity/api/current.txt b/activity/activity/api/current.txt
index ee25f24..045b57c 100644
--- a/activity/activity/api/current.txt
+++ b/activity/activity/api/current.txt
@@ -56,6 +56,12 @@
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
   }
 
+  public final class EdgeToEdge {
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle, optional androidx.activity.SystemBarStyle navigationBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity);
+  }
+
   public final class FullyDrawnReporter {
     ctor public FullyDrawnReporter(java.util.concurrent.Executor executor, kotlin.jvm.functions.Function0<kotlin.Unit> reportFullyDrawn);
     method public void addOnReportDrawnListener(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
@@ -103,6 +109,19 @@
     property public abstract androidx.activity.OnBackPressedDispatcher onBackPressedDispatcher;
   }
 
+  public final class SystemBarStyle {
+    method public static androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public static androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public static androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+    field public static final androidx.activity.SystemBarStyle.Companion Companion;
+  }
+
+  public static final class SystemBarStyle.Companion {
+    method public androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+  }
+
   public final class ViewTreeFullyDrawnReporterOwner {
     method public static androidx.activity.FullyDrawnReporterOwner? get(android.view.View);
     method public static void set(android.view.View, androidx.activity.FullyDrawnReporterOwner fullyDrawnReporterOwner);
diff --git a/activity/activity/api/public_plus_experimental_current.txt b/activity/activity/api/public_plus_experimental_current.txt
index ee25f24..045b57c 100644
--- a/activity/activity/api/public_plus_experimental_current.txt
+++ b/activity/activity/api/public_plus_experimental_current.txt
@@ -56,6 +56,12 @@
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
   }
 
+  public final class EdgeToEdge {
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle, optional androidx.activity.SystemBarStyle navigationBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity);
+  }
+
   public final class FullyDrawnReporter {
     ctor public FullyDrawnReporter(java.util.concurrent.Executor executor, kotlin.jvm.functions.Function0<kotlin.Unit> reportFullyDrawn);
     method public void addOnReportDrawnListener(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
@@ -103,6 +109,19 @@
     property public abstract androidx.activity.OnBackPressedDispatcher onBackPressedDispatcher;
   }
 
+  public final class SystemBarStyle {
+    method public static androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public static androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public static androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+    field public static final androidx.activity.SystemBarStyle.Companion Companion;
+  }
+
+  public static final class SystemBarStyle.Companion {
+    method public androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+  }
+
   public final class ViewTreeFullyDrawnReporterOwner {
     method public static androidx.activity.FullyDrawnReporterOwner? get(android.view.View);
     method public static void set(android.view.View, androidx.activity.FullyDrawnReporterOwner fullyDrawnReporterOwner);
diff --git a/activity/activity/api/restricted_current.txt b/activity/activity/api/restricted_current.txt
index 1210c28..e8670e7 100644
--- a/activity/activity/api/restricted_current.txt
+++ b/activity/activity/api/restricted_current.txt
@@ -55,6 +55,12 @@
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
   }
 
+  public final class EdgeToEdge {
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle, optional androidx.activity.SystemBarStyle navigationBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity, optional androidx.activity.SystemBarStyle statusBarStyle);
+    method public static void setUp(androidx.activity.ComponentActivity);
+  }
+
   public final class FullyDrawnReporter {
     ctor public FullyDrawnReporter(java.util.concurrent.Executor executor, kotlin.jvm.functions.Function0<kotlin.Unit> reportFullyDrawn);
     method public void addOnReportDrawnListener(kotlin.jvm.functions.Function0<kotlin.Unit> callback);
@@ -102,6 +108,19 @@
     property public abstract androidx.activity.OnBackPressedDispatcher onBackPressedDispatcher;
   }
 
+  public final class SystemBarStyle {
+    method public static androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public static androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public static androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+    field public static final androidx.activity.SystemBarStyle.Companion Companion;
+  }
+
+  public static final class SystemBarStyle.Companion {
+    method public androidx.activity.SystemBarStyle auto(@ColorInt int lightScrim, @ColorInt int darkScrim);
+    method public androidx.activity.SystemBarStyle dark(@ColorInt int scrim);
+    method public androidx.activity.SystemBarStyle light(@ColorInt int scrim, @ColorInt int darkScrim);
+  }
+
   public final class ViewTreeFullyDrawnReporterOwner {
     method public static androidx.activity.FullyDrawnReporterOwner? get(android.view.View);
     method public static void set(android.view.View, androidx.activity.FullyDrawnReporterOwner fullyDrawnReporterOwner);
diff --git a/activity/activity/build.gradle b/activity/activity/build.gradle
index f2b29f7..6bcedcb5 100644
--- a/activity/activity/build.gradle
+++ b/activity/activity/build.gradle
@@ -22,7 +22,7 @@
     api("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
     api("androidx.savedstate:savedstate:1.2.1")
     api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
     implementation("androidx.tracing:tracing:1.0.0")
     api(libs.kotlinStdlib)
 
diff --git a/activity/activity/src/androidTest/java/androidx/activity/EdgeToEdgeTest.kt b/activity/activity/src/androidTest/java/androidx/activity/EdgeToEdgeTest.kt
new file mode 100644
index 0000000..bd3a8a8
--- /dev/null
+++ b/activity/activity/src/androidTest/java/androidx/activity/EdgeToEdgeTest.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.activity
+
+import android.graphics.Color
+import android.os.Build
+import androidx.core.view.WindowInsetsControllerCompat
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.testutils.withActivity
+import androidx.testutils.withUse
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class EdgeToEdgeTest {
+
+    @Test
+    fun setUpAuto() {
+        withUse(ActivityScenario.launch(ComponentActivity::class.java)) {
+            withActivity {
+                setUpEdgeToEdge()
+                val view = window.decorView
+                if (Build.VERSION.SDK_INT >= 29) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.TRANSPARENT)
+                    assertThat(window.navigationBarColor).isEqualTo(Color.TRANSPARENT)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isTrue()
+                        assertThat(isAppearanceLightNavigationBars).isTrue()
+                    }
+                } else if (Build.VERSION.SDK_INT >= 26) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.TRANSPARENT)
+                    assertThat(window.navigationBarColor).isEqualTo(DefaultLightScrim)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isTrue()
+                        assertThat(isAppearanceLightNavigationBars).isTrue()
+                    }
+                } else if (Build.VERSION.SDK_INT >= 23) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.TRANSPARENT)
+                    assertThat(window.navigationBarColor).isEqualTo(DefaultDarkScrim)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isTrue()
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun setUpDark() {
+        withUse(ActivityScenario.launch(ComponentActivity::class.java)) {
+            withActivity {
+                setUpEdgeToEdge(
+                    statusBarStyle = SystemBarStyle.dark(Color.DKGRAY),
+                    navigationBarStyle = SystemBarStyle.dark(Color.DKGRAY)
+                )
+                val view = window.decorView
+                if (Build.VERSION.SDK_INT >= 26) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.DKGRAY)
+                    assertThat(window.navigationBarColor).isEqualTo(Color.DKGRAY)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isFalse()
+                        assertThat(isAppearanceLightNavigationBars).isFalse()
+                    }
+                } else if (Build.VERSION.SDK_INT >= 23) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.DKGRAY)
+                    assertThat(window.navigationBarColor).isEqualTo(Color.DKGRAY)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isFalse()
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun setUpLight() {
+        withUse(ActivityScenario.launch(ComponentActivity::class.java)) {
+            withActivity {
+                setUpEdgeToEdge(
+                    statusBarStyle = SystemBarStyle.light(Color.CYAN, Color.DKGRAY),
+                    navigationBarStyle = SystemBarStyle.light(Color.CYAN, Color.DKGRAY),
+                )
+                val view = window.decorView
+                if (Build.VERSION.SDK_INT >= 26) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.CYAN)
+                    assertThat(window.navigationBarColor).isEqualTo(Color.CYAN)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isTrue()
+                        assertThat(isAppearanceLightNavigationBars).isTrue()
+                    }
+                } else if (Build.VERSION.SDK_INT >= 23) {
+                    assertThat(window.statusBarColor).isEqualTo(Color.CYAN)
+                    assertThat(window.navigationBarColor).isEqualTo(Color.DKGRAY)
+                    WindowInsetsControllerCompat(window, view).run {
+                        assertThat(isAppearanceLightStatusBars).isTrue()
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt b/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt
new file mode 100644
index 0000000..837544a
--- /dev/null
+++ b/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt
@@ -0,0 +1,282 @@
+/*
+ * 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:JvmName("EdgeToEdge")
+
+package androidx.activity
+
+import android.app.UiModeManager
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.graphics.Color
+import android.os.Build
+import android.view.View
+import android.view.Window
+import android.view.WindowManager
+import androidx.annotation.ColorInt
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsControllerCompat
+
+// The light scrim color used in the platform API 29+
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/com/android/internal/policy/DecorView.java;drc=6ef0f022c333385dba2c294e35b8de544455bf19;l=142
+@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+internal val DefaultLightScrim = Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
+
+// The dark scrim color used in the platform.
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/color/system_bar_background_semi_transparent.xml
+// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/remote_color_resources_res/values/colors.xml;l=67
+@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+internal val DefaultDarkScrim = Color.argb(0x80, 0x1b, 0x1b, 0x1b)
+
+private var Impl: EdgeToEdgeImpl? = null
+
+/**
+ * Sets up edge-to-edge display for this [ComponentActivity].
+ *
+ * To set it up with the default style, call this method in your Activity's onCreate method:
+ * ```
+ *     override fun onCreate(savedInstanceState: Bundle?) {
+ *         setUpEdgeToEdge()
+ *         super.onCreate(savedInstanceState)
+ *         ...
+ *     }
+ * ```
+ *
+ * The default style configures the system bars with a transparent background when contrast can be
+ * enforced by the system (API 29 or above). On older platforms (which only have 3-button/2-button
+ * navigation modes), an equivalent scrim is applied to ensure contrast with the system bars.
+ *
+ * See [SystemBarStyle] for more customization options.
+ *
+ * @param statusBarStyle The [SystemBarStyle] for the status bar.
+ * @param navigationBarStyle The [SystemBarStyle] for the navigation bar.
+ */
+@JvmName("setUp")
+@JvmOverloads
+fun ComponentActivity.setUpEdgeToEdge(
+    statusBarStyle: SystemBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT),
+    navigationBarStyle: SystemBarStyle = SystemBarStyle.auto(DefaultLightScrim, DefaultDarkScrim)
+) {
+    val view = window.decorView
+    val statusBarIsDark = statusBarStyle.isDark(view.resources)
+    val navigationBarIsDark = navigationBarStyle.isDark(view.resources)
+    val impl = Impl ?: if (Build.VERSION.SDK_INT >= 29) {
+        EdgeToEdgeApi29()
+    } else if (Build.VERSION.SDK_INT >= 26) {
+        EdgeToEdgeApi26()
+    } else if (Build.VERSION.SDK_INT >= 23) {
+        EdgeToEdgeApi23()
+    } else if (Build.VERSION.SDK_INT >= 21) {
+        EdgeToEdgeApi21()
+    } else {
+        EdgeToEdgeBase()
+    }.also { Impl = it }
+    impl.setUp(
+        statusBarStyle, navigationBarStyle, window, view, statusBarIsDark, navigationBarIsDark
+    )
+}
+
+/**
+ * The style for the status bar or the navigation bar used in [setUpEdgeToEdge].
+ */
+class SystemBarStyle private constructor(
+    private val lightScrim: Int,
+    internal val darkScrim: Int,
+    internal val nightMode: Int
+) {
+
+    companion object {
+
+        /**
+         * Creates a new instance of [SystemBarStyle]. This style detects the dark mode
+         * automatically.
+         * - On API level 29 and above, the bar will be transparent in the gesture navigation mode.
+         *   If this is used for the navigation bar, it will have the scrim automatically applied
+         *   by the system in the 3-button navigation mode. _Note that neither of the specified
+         *   colors are used_. If you really want a custom color on these API levels, use [dark] or
+         *   [light].
+         * - On API level 28 and below, the bar will be one of the specified scrim colors depending
+         *   on the dark mode.
+         * @param lightScrim The scrim color to be used for the background when the app is in light
+         * mode.
+         * @param darkScrim The scrim color to be used for the background when the app is in dark
+         * mode. This is also used on devices where the system icon color is always light.
+         */
+        @JvmStatic
+        fun auto(@ColorInt lightScrim: Int, @ColorInt darkScrim: Int): SystemBarStyle {
+            return SystemBarStyle(lightScrim, darkScrim, UiModeManager.MODE_NIGHT_AUTO)
+        }
+
+        /**
+         * Creates a new instance of [SystemBarStyle]. This style consistently applies the specified
+         * scrim color regardless of the system navigation mode.
+         *
+         * @param scrim The scrim color to be used for the background. It is expected to be dark
+         * for the contrast against the light system icons.
+         */
+        @JvmStatic
+        fun dark(@ColorInt scrim: Int): SystemBarStyle {
+            return SystemBarStyle(scrim, scrim, UiModeManager.MODE_NIGHT_YES)
+        }
+
+        /**
+         * Creates a new instance of [SystemBarStyle]. This style consistently applies the specified
+         * scrim color regardless of the system navigation mode.
+         *
+         * @param scrim The scrim color to be used for the background. It is expected to be light
+         * for the contrast against the dark system icons.
+         * @param darkScrim The scrim color to be used for the background on devices where the
+         * system icon color is always light. It is expected to be dark.
+         */
+        @JvmStatic
+        fun light(@ColorInt scrim: Int, @ColorInt darkScrim: Int): SystemBarStyle {
+            return SystemBarStyle(scrim, darkScrim, UiModeManager.MODE_NIGHT_NO)
+        }
+    }
+
+    internal fun isDark(resources: Resources): Boolean {
+        return when (nightMode) {
+            UiModeManager.MODE_NIGHT_YES -> true
+            UiModeManager.MODE_NIGHT_NO -> false
+            else -> (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
+                Configuration.UI_MODE_NIGHT_YES
+        }
+    }
+
+    internal fun getScrim(isDark: Boolean) = if (isDark) darkScrim else lightScrim
+
+    internal fun getScrimWithEnforcedContrast(isDark: Boolean): Int {
+        return when {
+            nightMode == UiModeManager.MODE_NIGHT_AUTO -> Color.TRANSPARENT
+            isDark -> darkScrim
+            else -> lightScrim
+        }
+    }
+}
+
+private interface EdgeToEdgeImpl {
+
+    fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    )
+}
+
+private class EdgeToEdgeBase : EdgeToEdgeImpl {
+
+    override fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    ) {
+        // No edge-to-edge before SDK 21.
+    }
+}
+
+@RequiresApi(21)
+private class EdgeToEdgeApi21 : EdgeToEdgeImpl {
+
+    @Suppress("DEPRECATION")
+    @DoNotInline
+    override fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    ) {
+        WindowCompat.setDecorFitsSystemWindows(window, false)
+        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
+        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
+    }
+}
+
+@RequiresApi(23)
+private class EdgeToEdgeApi23 : EdgeToEdgeImpl {
+
+    @DoNotInline
+    override fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    ) {
+        WindowCompat.setDecorFitsSystemWindows(window, false)
+        window.statusBarColor = statusBarStyle.getScrim(statusBarIsDark)
+        window.navigationBarColor = navigationBarStyle.darkScrim
+        WindowInsetsControllerCompat(window, view).isAppearanceLightStatusBars = !statusBarIsDark
+    }
+}
+
+@RequiresApi(26)
+private class EdgeToEdgeApi26 : EdgeToEdgeImpl {
+
+    @DoNotInline
+    override fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    ) {
+        WindowCompat.setDecorFitsSystemWindows(window, false)
+        window.statusBarColor = statusBarStyle.getScrim(statusBarIsDark)
+        window.navigationBarColor = navigationBarStyle.getScrim(navigationBarIsDark)
+        WindowInsetsControllerCompat(window, view).run {
+            isAppearanceLightStatusBars = !statusBarIsDark
+            isAppearanceLightNavigationBars = !navigationBarIsDark
+        }
+    }
+}
+
+@RequiresApi(29)
+private class EdgeToEdgeApi29 : EdgeToEdgeImpl {
+
+    @DoNotInline
+    override fun setUp(
+        statusBarStyle: SystemBarStyle,
+        navigationBarStyle: SystemBarStyle,
+        window: Window,
+        view: View,
+        statusBarIsDark: Boolean,
+        navigationBarIsDark: Boolean
+    ) {
+        WindowCompat.setDecorFitsSystemWindows(window, false)
+        window.statusBarColor = statusBarStyle.getScrimWithEnforcedContrast(statusBarIsDark)
+        window.navigationBarColor =
+            navigationBarStyle.getScrimWithEnforcedContrast(navigationBarIsDark)
+        window.isStatusBarContrastEnforced = false
+        window.isNavigationBarContrastEnforced =
+            navigationBarStyle.nightMode == UiModeManager.MODE_NIGHT_AUTO
+        WindowInsetsControllerCompat(window, view).run {
+            isAppearanceLightStatusBars = !statusBarIsDark
+            isAppearanceLightNavigationBars = !navigationBarIsDark
+        }
+    }
+}
diff --git a/activity/integration-tests/testapp/build.gradle b/activity/integration-tests/testapp/build.gradle
index 364e39f..7799f8e 100644
--- a/activity/integration-tests/testapp/build.gradle
+++ b/activity/integration-tests/testapp/build.gradle
@@ -31,6 +31,8 @@
     implementation(project(":activity:activity-ktx"))
     implementation(projectOrArtifact(":lifecycle:lifecycle-runtime-ktx"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-common"))
+    implementation("androidx.appcompat:appcompat:1.6.0")
+    implementation("androidx.core:core-splashscreen:1.0.0")
     androidTestImplementation(libs.kotlinStdlib)
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
diff --git a/activity/integration-tests/testapp/src/main/AndroidManifest.xml b/activity/integration-tests/testapp/src/main/AndroidManifest.xml
index 8a6e622..5aacb12 100644
--- a/activity/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/activity/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -31,6 +31,17 @@
             android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
             android:exported="true"
             android:supportsPictureInPicture="true" />
+        <activity
+            android:name="androidx.activity.integration.testapp.EdgeToEdgeActivity"
+            android:exported="true"
+            android:label="EdgeToEdgeActivity"
+            android:theme="@style/Theme.EdgeToEdge.SplashScreen"
+            android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
 
         <provider
             android:name="androidx.core.content.FileProvider"
@@ -46,4 +57,6 @@
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 
+    <uses-sdk tools:overrideLibrary="androidx.core.splashscreen" />
+
 </manifest>
diff --git a/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/EdgeToEdgeActivity.kt b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/EdgeToEdgeActivity.kt
new file mode 100644
index 0000000..1f5d11a
--- /dev/null
+++ b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/EdgeToEdgeActivity.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.activity.integration.testapp
+
+import android.app.Dialog
+import android.graphics.Color
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import androidx.activity.SystemBarStyle
+import androidx.activity.setUpEdgeToEdge
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.fragment.app.DialogFragment
+
+class EdgeToEdgeActivity : AppCompatActivity(R.layout.edge_to_edge_activity) {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        if (Build.VERSION.SDK_INT >= 21) {
+            installSplashScreen()
+        }
+        setUpEdgeToEdge()
+        super.onCreate(savedInstanceState)
+        findViewById<View>(R.id.default_config).setOnClickListener {
+            // The default style.
+            // API 29+: Transparent on gesture nav, Auto scrim on 3-button nav (same as default).
+            // API 26-28: Transparent status. Light or dark scrim on nav.
+            // API 23-25: Transparent status. Dark scrim on nav.
+            // API 21,22: Dark scrim (system default).
+            setUpEdgeToEdge()
+        }
+        findViewById<View>(R.id.custom_config).setOnClickListener {
+            // API 29+: Transparent on gesture nav, Auto scrim on 3-button nav (same as default).
+            // API 23-28: Yellow bars.
+            // API 21,22: Dark scrim (system default).
+            val style = SystemBarStyle.auto(
+                lightScrim = Color.argb(0x64, 0xff, 0xeb, 0x3b),
+                darkScrim = Color.argb(0x64, 0x4a, 0x14, 0x8c)
+            )
+            setUpEdgeToEdge(statusBarStyle = style, navigationBarStyle = style)
+        }
+        findViewById<View>(R.id.transparent_config).setOnClickListener {
+            // API 23+: Transparent regardless of the nav mode.
+            // API 21,22: Dark scrim (system default).
+            val style = SystemBarStyle.dark(Color.TRANSPARENT)
+            setUpEdgeToEdge(statusBarStyle = style, navigationBarStyle = style)
+        }
+        findViewById<View>(R.id.purple_config).setOnClickListener {
+            // API 23+: Purple.
+            // API 21,22: Dark scrim (system default).
+            val style = SystemBarStyle.dark(
+                scrim = Color.argb(0x64, 0x4a, 0x14, 0x8c)
+            )
+            setUpEdgeToEdge(statusBarStyle = style, navigationBarStyle = style)
+        }
+        findViewById<View>(R.id.yellow_config).setOnClickListener {
+            // API 23+: Yellow.
+            // API 21,22: Dark scrim (system default).
+            val style = SystemBarStyle.light(
+                scrim = Color.argb(0x64, 0xff, 0xeb, 0x3b),
+                darkScrim = Color.rgb(0xf5, 0x7f, 0x17)
+            )
+            setUpEdgeToEdge(statusBarStyle = style, navigationBarStyle = style)
+        }
+        findViewById<View>(R.id.light_mode).setOnClickListener { setDarkMode(false) }
+        findViewById<View>(R.id.dark_mode).setOnClickListener { setDarkMode(true) }
+        findViewById<View>(R.id.show_dialog).setOnClickListener {
+            EdgeToEdgeDialogFragment().show(supportFragmentManager, null)
+        }
+    }
+
+    private fun setDarkMode(darkMode: Boolean) {
+        AppCompatDelegate.setDefaultNightMode(
+            if (darkMode) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO
+        )
+    }
+}
+
+class EdgeToEdgeDialogFragment : DialogFragment() {
+
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        return AlertDialog.Builder(requireContext())
+            .setTitle("Demo Dialog")
+            .setMessage("Hello, world!")
+            .setPositiveButton(android.R.string.ok, { dialog, _ ->
+                dialog.dismiss()
+            })
+            .create()
+    }
+}
diff --git a/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/PipActivity.kt b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/PipActivity.kt
index 056b797..d162c43 100644
--- a/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/PipActivity.kt
+++ b/activity/integration-tests/testapp/src/main/java/androidx/activity/integration/testapp/PipActivity.kt
@@ -30,10 +30,8 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 
-@ExperimentalCoroutinesApi
 class PipActivity : ComponentActivity() {
 
     private lateinit var moveButton: Button
@@ -60,7 +58,6 @@
         return true
     }
 
-    @ExperimentalCoroutinesApi
     private fun trackHintView() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             lifecycleScope.launch {
@@ -96,4 +93,4 @@
             activity.enterPictureInPictureMode(PictureInPictureParams.Builder().build())
         }
     }
-}
\ No newline at end of file
+}
diff --git a/activity/integration-tests/testapp/src/main/res/layout/edge_to_edge_activity.xml b/activity/integration-tests/testapp/src/main/res/layout/edge_to_edge_activity.xml
new file mode 100644
index 0000000..47e6cd6
--- /dev/null
+++ b/activity/integration-tests/testapp/src/main/res/layout/edge_to_edge_activity.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <View
+        android:id="@+id/red"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:background="#f00" />
+
+    <View
+        android:id="@+id/blue"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:layout_gravity="end|bottom"
+        android:background="#00f" />
+
+    <LinearLayout
+        android:id="@+id/content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="64dp"
+        android:orientation="vertical">
+
+        <Button
+            android:id="@+id/default_config"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="default" />
+
+        <Button
+            android:id="@+id/custom_config"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="custom" />
+
+        <Button
+            android:id="@+id/transparent_config"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="transparent" />
+
+        <Button
+            android:id="@+id/purple_config"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="purple" />
+
+        <Button
+            android:id="@+id/yellow_config"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="yellow" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="32dp"
+            android:orientation="horizontal">
+
+            <Button
+                android:id="@+id/light_mode"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="light mode" />
+
+            <Button
+                android:id="@+id/dark_mode"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="dark mode" />
+
+        </LinearLayout>
+
+        <Button
+            android:id="@+id/show_dialog"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="32dp"
+            android:text="show dialog" />
+
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/activity/integration-tests/testapp/src/main/res/values-v21/themes.xml b/activity/integration-tests/testapp/src/main/res/values-v21/themes.xml
new file mode 100644
index 0000000..d905b18
--- /dev/null
+++ b/activity/integration-tests/testapp/src/main/res/values-v21/themes.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+<resources>
+    <style name="Theme.EdgeToEdge.SplashScreen" parent="Theme.SplashScreen">
+        <item name="postSplashScreenTheme">@style/Theme.EdgeToEdge</item>
+    </style>
+    <style name="Theme.EdgeToEdge" parent="@style/Theme.AppCompat.DayNight.NoActionBar" />
+</resources>
diff --git a/activity/integration-tests/testapp/src/main/res/values/themes.xml b/activity/integration-tests/testapp/src/main/res/values/themes.xml
new file mode 100644
index 0000000..8f4a6a4
--- /dev/null
+++ b/activity/integration-tests/testapp/src/main/res/values/themes.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+-->
+<resources>
+    <style name="Theme.EdgeToEdge.SplashScreen" parent="@style/Theme.AppCompat.DayNight.NoActionBar" />
+</resources>
diff --git a/appactions/interaction/interaction-capabilities-core/build.gradle b/appactions/interaction/interaction-capabilities-core/build.gradle
index 258ef4f..1883f29 100644
--- a/appactions/interaction/interaction-capabilities-core/build.gradle
+++ b/appactions/interaction/interaction-capabilities-core/build.gradle
@@ -32,6 +32,7 @@
     implementation(libs.kotlinCoroutinesCore)
     implementation(libs.kotlinStdlib)
     implementation("androidx.concurrent:concurrent-futures:1.1.0")
+    implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
 
     testAnnotationProcessor(libs.autoValue)
     testImplementation(libs.junit)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionAlreadyInProgress.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionAlreadyInProgress.kt
new file mode 100644
index 0000000..88279c8
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionAlreadyInProgress.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.appactions.builtintypes.types
+
+import androidx.appactions.builtintypes.properties.Name
+
+interface ActionAlreadyInProgress : Thing {
+    override fun toBuilder(): Builder<*>
+
+    companion object {
+        @JvmStatic
+        fun Builder(): Builder<*> = ActionAlreadyInProgressBuilderImpl()
+    }
+
+    interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
+        override fun build(): ActionAlreadyInProgress
+    }
+}
+
+private class ActionAlreadyInProgressBuilderImpl :
+    ActionAlreadyInProgress.Builder<ActionAlreadyInProgressBuilderImpl> {
+
+    private var identifier: String? = null
+    private var name: Name? = null
+
+    override fun build() = ActionAlreadyInProgressImpl(identifier, name)
+
+    override fun setIdentifier(text: String?): ActionAlreadyInProgressBuilderImpl =
+        apply { identifier = text }
+
+    override fun setName(text: String): ActionAlreadyInProgressBuilderImpl =
+        apply { name = Name(text) }
+
+    override fun setName(name: Name?): ActionAlreadyInProgressBuilderImpl =
+        apply { this.name = name }
+
+    override fun clearName(): ActionAlreadyInProgressBuilderImpl = apply { name = null }
+}
+
+private class ActionAlreadyInProgressImpl(
+    override val identifier: String?,
+    override val name: Name?
+) :
+    ActionAlreadyInProgress {
+    override fun toBuilder(): ActionAlreadyInProgress.Builder<*> =
+        ActionAlreadyInProgressBuilderImpl().setIdentifier(identifier).setName(name)
+
+    override fun toString(): String = "ActionAlreadyInProgress"
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionNotInProgress.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionNotInProgress.kt
new file mode 100644
index 0000000..e5eee22d
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/ActionNotInProgress.kt
@@ -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.appactions.builtintypes.types
+
+import androidx.appactions.builtintypes.properties.Name
+
+interface ActionNotInProgress : Thing {
+    override fun toBuilder(): Builder<*>
+
+    companion object {
+        @JvmStatic
+        fun Builder(): Builder<*> = ActionNotInProgressBuilderImpl()
+    }
+
+    interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
+        override fun build(): ActionNotInProgress
+    }
+}
+
+private class ActionNotInProgressBuilderImpl :
+    ActionNotInProgress.Builder<ActionNotInProgressBuilderImpl> {
+
+    private var identifier: String? = null
+    private var name: Name? = null
+
+    override fun build() = ActionNotInProgressImpl(identifier, name)
+
+    override fun setIdentifier(text: String?): ActionNotInProgressBuilderImpl =
+        apply { identifier = text }
+
+    override fun setName(text: String): ActionNotInProgressBuilderImpl = apply { name = Name(text) }
+
+    override fun setName(name: Name?): ActionNotInProgressBuilderImpl = apply { this.name = name }
+
+    override fun clearName(): ActionNotInProgressBuilderImpl = apply { name = null }
+}
+
+private class ActionNotInProgressImpl(override val identifier: String?, override val name: Name?) :
+    ActionNotInProgress {
+    override fun toBuilder(): ActionNotInProgress.Builder<*> =
+        ActionNotInProgressBuilderImpl().setIdentifier(identifier).setName(name)
+
+    override fun toString(): String = "ActionNotInProgress"
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt
new file mode 100644
index 0000000..236cf9e
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt
@@ -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.appactions.builtintypes.types
+
+import androidx.appactions.builtintypes.properties.Name
+
+interface GenericErrorStatus : Thing {
+    override fun toBuilder(): Builder<*>
+
+    companion object {
+        @JvmStatic
+        fun Builder(): Builder<*> = GenericErrorStatusBuilderImpl()
+    }
+
+    interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
+        override fun build(): GenericErrorStatus
+    }
+}
+
+private class GenericErrorStatusBuilderImpl :
+    GenericErrorStatus.Builder<GenericErrorStatusBuilderImpl> {
+
+    private var identifier: String? = null
+    private var name: Name? = null
+
+    override fun build() = GenericErrorStatusImpl(identifier, name)
+
+    override fun setIdentifier(text: String?): GenericErrorStatusBuilderImpl =
+        apply { identifier = text }
+
+    override fun setName(text: String): GenericErrorStatusBuilderImpl = apply { name = Name(text) }
+
+    override fun setName(name: Name?): GenericErrorStatusBuilderImpl = apply { this.name = name }
+
+    override fun clearName(): GenericErrorStatusBuilderImpl = apply { name = null }
+}
+
+private class GenericErrorStatusImpl(override val identifier: String?, override val name: Name?) :
+    GenericErrorStatus {
+    override fun toBuilder(): GenericErrorStatus.Builder<*> =
+        GenericErrorStatusBuilderImpl().setIdentifier(identifier).setName(name)
+
+    override fun toString(): String = "GenericErrorStatus"
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/NoInternetConnection.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/NoInternetConnection.kt
new file mode 100644
index 0000000..bd890cc
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/NoInternetConnection.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.appactions.builtintypes.types
+
+import androidx.appactions.builtintypes.properties.Name
+
+interface NoInternetConnection : Thing {
+    override fun toBuilder(): Builder<*>
+
+    companion object {
+        @JvmStatic
+        fun Builder(): Builder<*> = NoInternetConnectionBuilderImpl()
+    }
+
+    interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
+        override fun build(): NoInternetConnection
+    }
+}
+
+private class NoInternetConnectionBuilderImpl :
+    NoInternetConnection.Builder<NoInternetConnectionBuilderImpl> {
+
+    private var identifier: String? = null
+    private var name: Name? = null
+
+    override fun build() = NoInternetConnectionImpl(identifier, name)
+
+    override fun setIdentifier(text: String?): NoInternetConnectionBuilderImpl =
+        apply { identifier = text }
+
+    override fun setName(text: String): NoInternetConnectionBuilderImpl =
+        apply { name = Name(text) }
+
+    override fun setName(name: Name?): NoInternetConnectionBuilderImpl = apply { this.name = name }
+
+    override fun clearName(): NoInternetConnectionBuilderImpl = apply { name = null }
+}
+
+private class NoInternetConnectionImpl(override val identifier: String?, override val name: Name?) :
+    NoInternetConnection {
+    override fun toBuilder(): NoInternetConnection.Builder<*> =
+        NoInternetConnectionBuilderImpl().setIdentifier(identifier).setName(name)
+
+    override fun toString(): String = "NoInternetConnection"
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt
new file mode 100644
index 0000000..834eba0
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt
@@ -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.appactions.builtintypes.types
+
+import androidx.appactions.builtintypes.properties.Name
+
+interface SuccessStatus : Thing {
+    override fun toBuilder(): Builder<*>
+
+    companion object {
+        @JvmStatic
+        fun Builder(): Builder<*> = SuccessStatusBuilderImpl()
+    }
+
+    interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
+        override fun build(): SuccessStatus
+    }
+}
+
+private class SuccessStatusBuilderImpl :
+    SuccessStatus.Builder<SuccessStatusBuilderImpl> {
+
+    private var identifier: String? = null
+    private var name: Name? = null
+
+    override fun build() = SuccessStatusImpl(identifier, name)
+
+    override fun setIdentifier(text: String?): SuccessStatusBuilderImpl =
+        apply { identifier = text }
+
+    override fun setName(text: String): SuccessStatusBuilderImpl = apply { name = Name(text) }
+
+    override fun setName(name: Name?): SuccessStatusBuilderImpl = apply { this.name = name }
+
+    override fun clearName(): SuccessStatusBuilderImpl = apply { name = null }
+}
+
+private class SuccessStatusImpl(override val identifier: String?, override val name: Name?) :
+    SuccessStatus {
+    override fun toBuilder(): SuccessStatus.Builder<*> =
+        SuccessStatusBuilderImpl().setIdentifier(identifier).setName(name)
+
+    override fun toString(): String = "SuccessStatus"
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
new file mode 100644
index 0000000..214a13e
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.appactions.interaction.capabilities.core.entity
+
+/** The candidate of the lookup results, including the entity object. */
+class EntityLookupCandidate<T> internal constructor(
+    val candidate: T
+) {
+
+    override fun toString(): String {
+        return "EntityLookupCandidate(cadidate=$candidate)"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as EntityLookupCandidate<*>
+
+        if (candidate != other.candidate) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        return candidate.hashCode()
+    }
+
+    /** Builder class for [EntityLookupCandidate]. */
+    class Builder<T>(private var candidate: T) {
+
+        fun setCandidate(candidate: T): Builder<T> = apply { this.candidate = candidate }
+        fun build(): EntityLookupCandidate<T> = EntityLookupCandidate(candidate)
+    }
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt
new file mode 100644
index 0000000..3e6f30d
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.appactions.interaction.capabilities.core.entity
+
+import androidx.appactions.interaction.capabilities.core.values.SearchAction
+import androidx.appactions.interaction.protobuf.ByteString
+
+/** The class for the request of the entity lookup. */
+class EntityLookupRequest<T> internal constructor(
+    val searchAction: SearchAction<T>,
+    val pageSize: Int,
+    val pageToken: ByteString,
+) {
+    override fun toString(): String {
+        return "EntityLookupRequest(" +
+            "searchAction=$searchAction, " +
+            "pageSize=$pageSize, " +
+            "pageToken=$pageToken)"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as EntityLookupRequest<*>
+
+        if (searchAction != other.searchAction) return false
+        if (pageSize != other.pageSize) return false
+        if (pageToken != other.pageToken) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = searchAction.hashCode()
+        result = 31 * result + pageSize.hashCode()
+        result = 31 * result + pageToken.hashCode()
+        return result
+    }
+
+    /** Builder class for EntityLookupRequest. */
+    class Builder<T>(
+        private var searchAction: SearchAction<T>,
+        private var pageSize: Int,
+        private var pageToken: ByteString
+    ) {
+        fun setSearchAction(searchAction: SearchAction<T>) =
+            apply { this.searchAction = searchAction }
+
+        fun setPageSize(pageSize: Int) = apply { this.pageSize = pageSize }
+
+        fun setPageToken(pageToken: ByteString) = apply { this.pageToken = pageToken }
+
+        fun build() = EntityLookupRequest(searchAction, pageSize, pageToken)
+    }
+}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
new file mode 100644
index 0000000..8864ffd
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appactions.interaction.capabilities.core.entity
+
+import androidx.annotation.IntDef
+import androidx.appactions.interaction.protobuf.ByteString
+
+/** The class for the response of the entity lookup. */
+class EntityLookupResponse<T> internal constructor(
+    val candidateList: List<EntityLookupCandidate<T>>,
+    @property:EntityLookupStatus val status: Int,
+    val nextPageToken: ByteString,
+) {
+    override fun toString(): String {
+        return "EntityLookupResponse(" +
+            "candidateList=$candidateList, " +
+            "status=$status, " +
+            "nextPageToken=$nextPageToken)"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as EntityLookupResponse<*>
+
+        if (candidateList != other.candidateList) return false
+        if (status != other.status) return false
+        if (nextPageToken != other.nextPageToken) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = candidateList.hashCode()
+        result = 31 * result + status.hashCode()
+        result = 31 * result + nextPageToken.hashCode()
+        return result
+    }
+
+    /** Builder class for [Entity]. */
+    class Builder<T>(
+        private var candidateList: List<EntityLookupCandidate<T>>,
+        @property:EntityLookupStatus private var status: Int,
+        private var nextPageToken: ByteString
+    ) {
+        fun setCandidateList(candidateList: List<EntityLookupCandidate<T>>): Builder<T> = apply {
+            this.candidateList = candidateList
+        }
+
+        fun setStatus(status: Int): Builder<T> =
+            apply {
+                this.status = status
+            }
+
+        fun setNextPageToken(nextPageToken: ByteString): Builder<T> = apply {
+            this.nextPageToken = nextPageToken
+        }
+
+        fun build() = EntityLookupResponse<T>(candidateList, status, nextPageToken)
+    }
+
+    companion object {
+        const val SUCCESS: Int = 0
+        const val CANCELED: Int = 1
+        const val INVALID_PAGE_TOKEN: Int = 2
+        const val TIMEOUT: Int = 3
+        const val UNKNOWN_ERROR: Int = 4
+    }
+
+    // IntDef enum for lookup status.
+    @Retention(AnnotationRetention.SOURCE)
+    @IntDef(
+        value = [
+            SUCCESS,
+            CANCELED,
+            INVALID_PAGE_TOKEN,
+            TIMEOUT,
+            UNKNOWN_ERROR,
+        ]
+    )
+    annotation class EntityLookupStatus
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt
new file mode 100644
index 0000000..05d3d37
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.appactions.interaction.capabilities.core.entity
+
+import androidx.appactions.interaction.capabilities.core.values.Thing
+
+/**
+ * EntityProvider could provide candidates for assistant's search actions.
+ *
+ * <p>Use abstract classes within the library to create instances of the {@link EntityProvider}.
+ */
+abstract class EntityProvider<T : Thing> {
+    /**
+     * Unique identifier for this EntityFilter. Must match the shortcuts.xml declaration, which allows
+     * different filters to be assigned to types on a per-BII basis.
+     */
+    abstract fun getId(): String
+
+    /**
+     * Executes the entity lookup.
+     *
+     * @param request The request includes e.g. entity, search metadata, etc.
+     */
+    abstract fun lookup(request: EntityLookupRequest<T>): EntityLookupResponse<T>
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java
index 8f2bd49..1d8cf70 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package androidx.appactions.interaction.capabilities.core.entity;
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
index 6888593..dff7e78 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
@@ -19,13 +19,14 @@
 import androidx.annotation.RestrictTo
 import androidx.appactions.interaction.capabilities.core.ActionExecutorAsync
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
 import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
 import androidx.appactions.interaction.proto.FulfillmentResponse
 import androidx.appactions.interaction.proto.ParamValue
+import androidx.concurrent.futures.await
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 /**
  * ActionCapabilitySession implementation for executing single-turn fulfillment requests.
@@ -36,9 +37,10 @@
 internal class SingleTurnCapabilitySession<
     ArgumentT,
     OutputT,
-    >(
-    val actionSpec: ActionSpec<*, ArgumentT, OutputT>,
-    val actionExecutorAsync: ActionExecutorAsync<ArgumentT, OutputT>,
+>(
+    private val actionSpec: ActionSpec<*, ArgumentT, OutputT>,
+    private val actionExecutorAsync: ActionExecutorAsync<ArgumentT, OutputT>,
+    private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
 ) : ActionCapabilitySession {
     override val state: AppDialogState
         get() {
@@ -63,38 +65,25 @@
         callback: CallbackInternal,
     ) {
         val paramValuesMap: Map<String, List<ParamValue>> =
-            argumentsWrapper.paramValues.entries.associate {
-                    entry: Map.Entry<String, List<FulfillmentValue>> ->
-                Pair(
-                    entry.key,
-                    entry.value.mapNotNull { fulfillmentValue: FulfillmentValue ->
-                        fulfillmentValue.getValue()
-                    },
-                )
-            }
+            argumentsWrapper.paramValues.mapValues { entry -> entry.value.mapNotNull { it.value } }
         val argument = actionSpec.buildArgument(paramValuesMap)
-        Futures.addCallback(
-            actionExecutorAsync.execute(argument),
-            object : FutureCallback<ExecutionResult<OutputT>> {
-                override fun onSuccess(executionResult: ExecutionResult<OutputT>) {
-                    callback.onSuccess(convertToFulfillmentResponse(executionResult))
-                }
-
-                override fun onFailure(t: Throwable) {
-                    callback.onError(ErrorStatusInternal.CANCELLED)
-                }
-            },
-            Runnable::run,
-        )
+        scope.launch {
+            try {
+                val output = actionExecutorAsync.execute(argument).await()
+                callback.onSuccess(convertToFulfillmentResponse(output))
+            } catch (t: Throwable) {
+                callback.onError(ErrorStatusInternal.CANCELLED)
+            }
+        }
     }
 
     /** Converts typed {@link ExecutionResult} to {@link FulfillmentResponse} proto. */
-    internal fun convertToFulfillmentResponse(
+    private fun convertToFulfillmentResponse(
         executionResult: ExecutionResult<OutputT>,
     ): FulfillmentResponse {
         val fulfillmentResponseBuilder =
             FulfillmentResponse.newBuilder().setStartDictation(executionResult.startDictation)
-        executionResult.output?.let { it ->
+        executionResult.output?.let {
             fulfillmentResponseBuilder.setExecutionOutput(
                 actionSpec.convertOutputToProto(it),
             )
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java
index 8f2bd49..ea6e4cc 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package androidx.appactions.interaction.capabilities.core.impl;
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+import androidx.annotation.RestrictTo;
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/package-info.java
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/package-info.java
index 8f2bd49..2229543 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/package-info.java
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package androidx.appactions.interaction.capabilities.core.properties;
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/AssistantUpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/AssistantUpdateRequest.kt
index 4799845..b4af6e8 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/AssistantUpdateRequest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/AssistantUpdateRequest.kt
@@ -15,7 +15,6 @@
  */
 package androidx.appactions.interaction.capabilities.core.task.impl
 
-import androidx.annotation.RestrictTo
 import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
 import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
 
@@ -24,10 +23,8 @@
  *
  * @param argumentsWrapper The fulfillment request data.
  * @param callbackInternal The callback to report results from handling this request.
- * @hide
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-data class AssistantUpdateRequest(
+internal data class AssistantUpdateRequest(
     val argumentsWrapper: ArgumentsWrapper,
     val callbackInternal: CallbackInternal,
 )
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/SlotProcessingResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/SlotProcessingResult.kt
index 93f8e5d..67cca58 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/SlotProcessingResult.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/SlotProcessingResult.kt
@@ -15,7 +15,6 @@
  */
 package androidx.appactions.interaction.capabilities.core.task.impl
 
-import androidx.annotation.RestrictTo
 import androidx.appactions.interaction.proto.CurrentValue
 
 /**
@@ -25,8 +24,8 @@
  * * listener#onReceived returned ACCEPTED for all grounded values (which could be empty list)
  *
  * @param processedValues Processed CurrentValue objects.
- * @hide
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-data class SlotProcessingResult
-constructor(val isSuccessful: Boolean, val processedValues: List<CurrentValue>)
+internal data class SlotProcessingResult(
+    val isSuccessful: Boolean,
+    val processedValues: List<CurrentValue>,
+)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilitySession.kt
index 4033f4d..6f044e9 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilitySession.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilitySession.kt
@@ -16,35 +16,38 @@
 
 package androidx.appactions.interaction.capabilities.core.task.impl
 
+import androidx.annotation.GuardedBy
 import androidx.appactions.interaction.capabilities.core.BaseSession
 import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession
 import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
 import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
 import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
 import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
 import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
 import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.ParamValue
 import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
+import androidx.appactions.interaction.proto.ParamValue
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 
 internal class TaskCapabilitySession<
     ArgumentT,
     OutputT,
     ConfirmationT,
 >(
-    val actionSpec: ActionSpec<*, ArgumentT, OutputT>,
-    val appAction: AppAction,
-    val taskHandler: TaskHandler<ConfirmationT>,
-    val externalSession: BaseSession<ArgumentT, OutputT>,
+    actionSpec: ActionSpec<*, ArgumentT, OutputT>,
+    appAction: AppAction,
+    taskHandler: TaskHandler<ConfirmationT>,
+    externalSession: BaseSession<ArgumentT, OutputT>,
+    private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
 ) : ActionCapabilitySession, TaskUpdateHandler {
     override val state: AppDialogState
-        get() = sessionOrchestrator.getAppDialogState()
+        get() = sessionOrchestrator.appDialogState
 
     // single-turn capability does not have status
     override val status: ActionCapabilitySession.Status
-        get() = sessionOrchestrator.getStatus()
+        get() = sessionOrchestrator.status
 
     override fun destroy() {
         // TODO(b/270751989): cancel current processing request immediately
@@ -68,10 +71,10 @@
             appAction,
             taskHandler,
             externalSession,
-            Runnable::run,
         )
-    private var pendingAssistantRequest: AssistantUpdateRequest? = null
-    private var pendingTouchEventRequest: TouchEventUpdateRequest? = null
+
+    @GuardedBy("requestLock") private var pendingAssistantRequest: AssistantUpdateRequest? = null
+    @GuardedBy("requestLock") private var pendingTouchEventRequest: TouchEventUpdateRequest? = null
 
     override fun execute(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {
         enqueueAssistantRequest(AssistantUpdateRequest(argumentsWrapper, callback))
@@ -102,12 +105,9 @@
 
     private fun enqueueTouchEventRequest(request: TouchEventUpdateRequest) {
         synchronized(requestLock) {
-            if (pendingTouchEventRequest == null) {
-                pendingTouchEventRequest = request
-            } else {
-                pendingTouchEventRequest =
-                    TouchEventUpdateRequest.merge(pendingTouchEventRequest!!, request)
-            }
+            pendingTouchEventRequest =
+                if (pendingTouchEventRequest == null) request
+                else pendingTouchEventRequest!!.mergeWith(request)
             dispatchPendingRequestIfIdle()
         }
     }
@@ -119,7 +119,7 @@
      * <p>If sessionOrchestrator is not idle, do nothing, since this method will automatically be
      * called when sessionOrchestrator becomes idle.
      */
-    internal fun dispatchPendingRequestIfIdle() {
+    private fun dispatchPendingRequestIfIdle() {
         synchronized(requestLock) {
             if (!sessionOrchestrator.isIdle()) {
                 return
@@ -133,32 +133,10 @@
                 pendingTouchEventRequest = null
             }
             if (nextRequest != null) {
-                Futures.addCallback(
-                    sessionOrchestrator.processUpdateRequest(nextRequest),
-                    object : FutureCallback<Void?> {
-                        override fun onSuccess(unused: Void?) {
-                            dispatchPendingRequestIfIdle()
-                        }
-
-                        /**
-                         * A fatal exception has occurred, cause by one of the following:
-                         * <ul>
-                         * <li>1. The developer listener threw some runtime exception
-                         * <li>2. The SDK encountered some uncaught internal exception
-                         * </ul>
-                         *
-                         * <p>In both cases, this exception will be rethrown which will crash the
-                         * app.
-                         */
-                        override fun onFailure(t: Throwable) {
-                            throw IllegalStateException(
-                                "unhandled exception in request processing",
-                                t,
-                            )
-                        }
-                    },
-                    Runnable::run,
-                )
+                scope.launch {
+                    sessionOrchestrator.processUpdateRequest(nextRequest)
+                    dispatchPendingRequestIfIdle()
+                }
             }
         }
     }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.java
deleted file mode 100644
index 1fca454..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.java
+++ /dev/null
@@ -1,251 +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.appactions.interaction.capabilities.core.task.impl;
-
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableList;
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableMap;
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableSet;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingRequiredArgException;
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter;
-import androidx.appactions.interaction.proto.CurrentValue;
-import androidx.appactions.interaction.proto.CurrentValue.Status;
-import androidx.appactions.interaction.proto.DisambiguationData;
-import androidx.appactions.interaction.proto.Entity;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.appactions.interaction.protobuf.Struct;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.IntStream;
-
-/** Utility methods used for implementing Task Capabilities. */
-public final class TaskCapabilityUtils {
-    private TaskCapabilityUtils() {
-    }
-
-    /** Uses Property to detect if all required arguments are present. */
-    static boolean isSlotFillingComplete(
-            Map<String, List<ParamValue>> finalArguments, List<IntentParameter> paramsList) {
-        Set<String> requiredParams =
-                paramsList.stream()
-                        .filter(IntentParameter::getIsRequired)
-                        .map(IntentParameter::getName)
-                        .collect(toImmutableSet());
-        for (String paramName : requiredParams) {
-            if (!finalArguments.containsKey(paramName)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    static List<CurrentValue> paramValuesToCurrentValue(
-            List<ParamValue> paramValueList, Status status) {
-        return paramValueList.stream()
-                .map(paramValue -> toCurrentValue(paramValue, status))
-                .collect(toImmutableList());
-    }
-
-    static List<FulfillmentValue> paramValuesToFulfillmentValues(List<ParamValue> paramValueList) {
-        return paramValueList.stream()
-                .map(paramValue -> FulfillmentValue.newBuilder().setValue(paramValue).build())
-                .collect(toImmutableList());
-    }
-
-    static Map<String, List<FulfillmentValue>> paramValuesMapToFulfillmentValuesMap(
-            Map<String, List<ParamValue>> paramValueMap) {
-        return paramValueMap.entrySet().stream()
-                .collect(
-                        toImmutableMap(
-                                Map.Entry::getKey,
-                                (entry) -> paramValuesToFulfillmentValues(entry.getValue())));
-    }
-
-    static List<CurrentValue> fulfillmentValuesToCurrentValues(
-            List<FulfillmentValue> fulfillmentValueList, Status status) {
-        return fulfillmentValueList.stream()
-                .map(fulfillmentValue -> toCurrentValue(fulfillmentValue, status))
-                .collect(toImmutableList());
-    }
-
-    static CurrentValue toCurrentValue(ParamValue paramValue, Status status) {
-        return CurrentValue.newBuilder().setValue(paramValue).setStatus(status).build();
-    }
-
-    static CurrentValue toCurrentValue(FulfillmentValue fulfillmentValue, Status status) {
-        CurrentValue.Builder result = CurrentValue.newBuilder();
-        if (fulfillmentValue.hasValue()) {
-            result.setValue(fulfillmentValue.getValue());
-        }
-        if (fulfillmentValue.hasDisambigData()) {
-            result.setDisambiguationData(fulfillmentValue.getDisambigData());
-        }
-        return result.setStatus(status).build();
-    }
-
-    static ParamValue groundedValueToParamValue(Entity groundedEntity) {
-        if (groundedEntity.hasValue()) {
-            return ParamValue.newBuilder()
-                    .setIdentifier(groundedEntity.getIdentifier())
-                    .setStructValue(groundedEntity.getValue())
-                    .build();
-        } else {
-            return ParamValue.newBuilder()
-                    .setIdentifier(groundedEntity.getIdentifier())
-                    .setStringValue(groundedEntity.getName())
-                    .build();
-        }
-    }
-
-    /** Create a CurrentValue based on Disambugation result for a ParamValue. */
-    static CurrentValue getCurrentValueForDisambiguation(
-            ParamValue paramValue, List<Entity> disambiguationEntities) {
-        return CurrentValue.newBuilder()
-                .setValue(paramValue)
-                .setStatus(Status.DISAMBIG)
-                .setDisambiguationData(
-                        DisambiguationData.newBuilder().addAllEntities(disambiguationEntities))
-                .build();
-    }
-
-    /** Convenience method to be used in onFinishListeners. */
-    @NonNull
-    public static List<ParamValue> checkRequiredArg(
-            @NonNull Map<String, List<ParamValue>> args, @NonNull String argName)
-            throws MissingRequiredArgException {
-        List<ParamValue> result = args.get(argName);
-        if (result == null) {
-            throw new MissingRequiredArgException(
-                    String.format(
-                            "'%s' is a required argument but is missing from the final arguments "
-                                    + "map.",
-                            argName));
-        }
-        return result;
-    }
-
-    /** Compares two ParamValue, returns false if they are equivalent, true otherwise. */
-    private static boolean hasParamValueDiff(ParamValue oldArg, ParamValue newArg) {
-        if (oldArg.getValueCase().getNumber() != newArg.getValueCase().getNumber()) {
-            return true;
-        }
-        if (!oldArg.getIdentifier().equals(newArg.getIdentifier())) {
-            return true;
-        }
-        switch (oldArg.getValueCase()) {
-            case VALUE_NOT_SET:
-                return false;
-            case STRING_VALUE:
-                return !oldArg.getStringValue().equals(newArg.getStringValue());
-            case BOOL_VALUE:
-                return oldArg.getBoolValue() != newArg.getBoolValue();
-            case NUMBER_VALUE:
-                return oldArg.getNumberValue() != newArg.getNumberValue();
-            case STRUCT_VALUE:
-                return !Arrays.equals(
-                        oldArg.getStructValue().toByteArray(),
-                        newArg.getStructValue().toByteArray());
-        }
-        return true;
-    }
-
-    /**
-     * Returns true if we can skip processing of new FulfillmentValues for a slot.
-     *
-     * <p>There are two required conditions for skipping processing:
-     *
-     * <ul>
-     *   <li>1. currentValues are all ACCEPTED.
-     *   <li>2. there are no differences between the ParamValues in currentValues and
-     *       fulfillmentValues.
-     * </ul>
-     */
-    static boolean canSkipSlotProcessing(
-            List<CurrentValue> currentValues, List<FulfillmentValue> fulfillmentValues) {
-        if (currentValues.stream()
-                .allMatch(currentValue -> currentValue.getStatus().equals(Status.ACCEPTED))) {
-            if (currentValues.size() == fulfillmentValues.size()) {
-                return IntStream.range(0, fulfillmentValues.size())
-                        .allMatch(
-                                i ->
-                                        !TaskCapabilityUtils.hasParamValueDiff(
-                                                currentValues.get(i).getValue(),
-                                                fulfillmentValues.get(i).getValue()));
-            }
-        }
-        return false;
-    }
-
-    /** Given a {@code List<CurrentValue>} find all the Struct in them as a Map. */
-    private static Map<String, Struct> getStructsFromCurrentValues(
-            List<CurrentValue> currentValues) {
-        Map<String, Struct> candidates = new HashMap<>();
-        for (CurrentValue currentValue : currentValues) {
-            if (currentValue.getStatus() == CurrentValue.Status.ACCEPTED
-                    && currentValue.getValue().hasStructValue()) {
-                candidates.put(
-                        currentValue.getValue().getIdentifier(),
-                        currentValue.getValue().getStructValue());
-            } else if (currentValue.getStatus() == CurrentValue.Status.DISAMBIG) {
-                for (Entity entity : currentValue.getDisambiguationData().getEntitiesList()) {
-                    if (entity.hasValue()) {
-                        candidates.put(entity.getIdentifier(), entity.getValue());
-                    }
-                }
-            }
-        }
-        return Collections.unmodifiableMap(candidates);
-    }
-
-    /**
-     * Grounded values for donated inventory slots are sent as identifier only, so find matching
-     * Struct from previous turn and add them to the fulfillment values.
-     */
-    static List<FulfillmentValue> getMaybeModifiedSlotValues(
-            List<CurrentValue> currentValues, List<FulfillmentValue> newSlotValues) {
-        Map<String, Struct> candidates = getStructsFromCurrentValues(currentValues);
-        if (candidates.isEmpty()) {
-            return newSlotValues;
-        }
-        return newSlotValues.stream()
-                .map(
-                        fulfillmentValue -> {
-                            ParamValue paramValue = fulfillmentValue.getValue();
-                            if (paramValue.hasIdentifier()
-                                    && !paramValue.hasStructValue()
-                                    && candidates.containsKey(paramValue.getIdentifier())) {
-                                // TODO(b/243944366) throw error if struct filling fails for an
-                                //  inventory slot.
-                                return fulfillmentValue.toBuilder()
-                                        .setValue(
-                                                paramValue.toBuilder()
-                                                        .setStructValue(candidates.get(
-                                                                paramValue.getIdentifier())))
-                                        .build();
-                            }
-                            return fulfillmentValue;
-                        })
-                .collect(toImmutableList());
-    }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.kt
new file mode 100644
index 0000000..dbe2113
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtils.kt
@@ -0,0 +1,193 @@
+/*
+ * 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.appactions.interaction.capabilities.core.task.impl
+
+import androidx.appactions.interaction.proto.AppActionsContext
+import androidx.appactions.interaction.proto.CurrentValue
+import androidx.appactions.interaction.proto.DisambiguationData
+import androidx.appactions.interaction.proto.Entity
+import androidx.appactions.interaction.proto.FulfillmentRequest
+import androidx.appactions.interaction.proto.ParamValue
+import androidx.appactions.interaction.protobuf.Struct
+import java.util.Arrays
+
+/** Utility methods used for implementing Task Capabilities. */
+internal object TaskCapabilityUtils {
+    /** Uses Property to detect if all required arguments are present. */
+    fun isSlotFillingComplete(
+        finalArguments: Map<String, List<ParamValue>>,
+        paramsList: List<AppActionsContext.IntentParameter>
+    ) = paramsList.filter { it.isRequired }.map { it.name }.all { finalArguments.containsKey(it) }
+
+    fun paramValuesToCurrentValue(
+        paramValueList: List<ParamValue>,
+        status: CurrentValue.Status
+    ): List<CurrentValue> = paramValueList.map { toCurrentValue(it, status) }
+
+    private fun paramValuesToFulfillmentValues(
+        paramValueList: List<ParamValue>
+    ): List<FulfillmentRequest.Fulfillment.FulfillmentValue> =
+        paramValueList.map {
+            FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder().setValue(it).build()
+        }
+
+    fun paramValuesMapToFulfillmentValuesMap(
+        paramValueMap: Map<String, List<ParamValue>>
+    ): Map<String, List<FulfillmentRequest.Fulfillment.FulfillmentValue>> =
+        paramValueMap.entries.associate { entry ->
+            entry.key to paramValuesToFulfillmentValues(entry.value)
+        }
+
+    fun fulfillmentValuesToCurrentValues(
+        fulfillmentValueList: List<FulfillmentRequest.Fulfillment.FulfillmentValue>,
+        status: CurrentValue.Status
+    ): List<CurrentValue> = fulfillmentValueList.map { toCurrentValue(it, status) }
+
+    fun toCurrentValue(paramValue: ParamValue, status: CurrentValue.Status): CurrentValue =
+        CurrentValue.newBuilder().setValue(paramValue).setStatus(status).build()
+
+    private fun toCurrentValue(
+        fulfillmentValue: FulfillmentRequest.Fulfillment.FulfillmentValue,
+        status: CurrentValue.Status
+    ): CurrentValue {
+        val result = CurrentValue.newBuilder()
+        if (fulfillmentValue.hasValue()) {
+            result.value = fulfillmentValue.value
+        }
+        if (fulfillmentValue.hasDisambigData()) {
+            result.disambiguationData = fulfillmentValue.disambigData
+        }
+        return result.setStatus(status).build()
+    }
+
+    fun groundedValueToParamValue(groundedEntity: Entity): ParamValue =
+        if (groundedEntity.hasValue())
+            ParamValue.newBuilder()
+                .setIdentifier(groundedEntity.identifier)
+                .setStructValue(groundedEntity.value)
+                .build()
+        else
+            ParamValue.newBuilder()
+                .setIdentifier(groundedEntity.identifier)
+                .setStringValue(groundedEntity.name)
+                .build()
+
+    /** Create a [CurrentValue] based on Disambiguation result for a ParamValue. */
+    fun getCurrentValueForDisambiguation(
+        paramValue: ParamValue,
+        disambiguationEntities: List<Entity>
+    ): CurrentValue =
+        CurrentValue.newBuilder()
+            .setValue(paramValue)
+            .setStatus(CurrentValue.Status.DISAMBIG)
+            .setDisambiguationData(
+                DisambiguationData.newBuilder().addAllEntities(disambiguationEntities)
+            )
+            .build()
+
+    /** Compares two [ParamValue], returns false if they are equivalent, true otherwise. */
+    private fun hasParamValueDiff(oldArg: ParamValue, newArg: ParamValue): Boolean {
+        if (oldArg.valueCase.number != newArg.valueCase.number) {
+            return true
+        }
+        return if (oldArg.identifier != newArg.identifier) {
+            true
+        } else
+            when (oldArg.valueCase) {
+                ParamValue.ValueCase.VALUE_NOT_SET -> false
+                ParamValue.ValueCase.STRING_VALUE -> oldArg.stringValue != newArg.stringValue
+                ParamValue.ValueCase.BOOL_VALUE -> oldArg.boolValue != newArg.boolValue
+                ParamValue.ValueCase.NUMBER_VALUE -> oldArg.numberValue != newArg.numberValue
+                ParamValue.ValueCase.STRUCT_VALUE ->
+                    !Arrays.equals(
+                        oldArg.structValue.toByteArray(),
+                        newArg.structValue.toByteArray()
+                    )
+                else -> true
+            }
+    }
+
+    /**
+     * Returns true if we can skip processing of new [fulfillmentValues] for a slot.
+     *
+     * There are two required conditions for skipping processing:
+     * * 1. [currentValues] are all ACCEPTED.
+     * * 2. there are no differences between the [ParamValue]s in [currentValues] and
+     *   [fulfillmentValues].
+     */
+    fun canSkipSlotProcessing(
+        currentValues: List<CurrentValue>,
+        fulfillmentValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>
+    ): Boolean =
+        currentValues.all { it.status == CurrentValue.Status.ACCEPTED } &&
+            currentValues.size == fulfillmentValues.size &&
+            fulfillmentValues.indices.all {
+                !hasParamValueDiff(currentValues[it].value, fulfillmentValues[it].value)
+            }
+
+    /** Given a [List<CurrentValue>], find all the Struct in them as a Map. */
+    private fun getStructsFromCurrentValues(
+        currentValues: List<CurrentValue>
+    ): Map<String, Struct> {
+        val candidates = mutableMapOf<String, Struct>()
+        for (currentValue in currentValues) {
+            if (
+                currentValue.status == CurrentValue.Status.ACCEPTED &&
+                    currentValue.value.hasStructValue()
+            ) {
+                candidates[currentValue.value.identifier] = currentValue.value.structValue
+            } else if (currentValue.status == CurrentValue.Status.DISAMBIG) {
+                for (entity in currentValue.disambiguationData.entitiesList) {
+                    if (entity.hasValue()) {
+                        candidates[entity.identifier] = entity.value
+                    }
+                }
+            }
+        }
+        return candidates.toMap()
+    }
+
+    /**
+     * Grounded values for donated inventory slots are sent as identifier only, so find matching
+     * Struct from previous turn and add them to the fulfillment values.
+     */
+    fun getMaybeModifiedSlotValues(
+        currentValues: List<CurrentValue>,
+        newSlotValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>
+    ): List<FulfillmentRequest.Fulfillment.FulfillmentValue> {
+        val candidates = getStructsFromCurrentValues(currentValues)
+        return if (candidates.isEmpty()) {
+            newSlotValues
+        } else
+            newSlotValues.map {
+                val paramValue = it.value
+                if (
+                    paramValue.hasIdentifier() &&
+                        !paramValue.hasStructValue() &&
+                        candidates.containsKey(paramValue.identifier)
+                ) {
+                    // TODO(b/243944366) throw error if struct filling fails for an
+                    //  inventory slot.
+                    return@map it.toBuilder()
+                        .setValue(
+                            paramValue.toBuilder().setStructValue(candidates[paramValue.identifier])
+                        )
+                        .build()
+                }
+                it
+            }
+    }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.java
deleted file mode 100644
index 5a65e01..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.java
+++ /dev/null
@@ -1,663 +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.appactions.interaction.capabilities.core.task.impl;
-
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableList;
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableMap;
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableSet;
-
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appactions.interaction.capabilities.core.BaseSession;
-import androidx.appactions.interaction.capabilities.core.ConfirmationOutput;
-import androidx.appactions.interaction.capabilities.core.ExecutionResult;
-import androidx.appactions.interaction.capabilities.core.InitArg;
-import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession;
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper;
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal;
-import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec;
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger;
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal;
-import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingRequiredArgException;
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction;
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState;
-import androidx.appactions.interaction.proto.AppActionsContext.DialogParameter;
-import androidx.appactions.interaction.proto.CurrentValue;
-import androidx.appactions.interaction.proto.CurrentValue.Status;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.appactions.interaction.proto.TouchEventMetadata;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.function.Function;
-
-/**
- * TaskOrchestrator is responsible for holding session state, and processing assistant / manual
- * input updates to update session state.
- *
- * <p>TaskOrchestrator is also responsible to communicating state updates to developer provided
- * listeners.
- *
- * <p>Only one request can be processed at a time.
- */
-final class TaskOrchestrator<ArgumentT, OutputT, ConfirmationT> {
-
-    private static final String LOG_TAG = "TaskOrchestrator";
-    private final ActionSpec<?, ArgumentT, OutputT> mActionSpec;
-    private final AppAction mAppAction;
-    private final TaskHandler<ConfirmationT> mTaskHandler;
-    private final Executor mExecutor;
-    private final BaseSession<ArgumentT, OutputT> mExternalSession;
-
-    /**
-     * Map of argument name to the {@link CurrentValue} which wraps the argument name and status .
-     */
-    private final Map<String, List<CurrentValue>> mCurrentValuesMap;
-    /**
-     * Internal lock to enable synchronization while processing update requests. Also used for
-     * synchronization of Task orchestrator state. ie indicate whether it is idle or not
-     */
-    private final Object mTaskOrchestratorLock = new Object();
-    /**
-     * The callback that should be invoked when manual input processing finishes. This sends the
-     * processing results to the AppInteraction SDKs. Note, this field is not provided on
-     * construction because the callback is not available at the time when the developer creates the
-     * capability.
-     */
-    @Nullable TouchEventCallback mTouchEventCallback;
-    /** Current status of the overall task (i.e. status of the task). */
-    private ActionCapabilitySession.Status mTaskStatus;
-
-    /** True if an UpdateRequest is currently being processed, false otherwise. */
-    @GuardedBy("mTaskOrchestratorLock")
-    private boolean mIsIdle = true;
-
-    TaskOrchestrator(
-            ActionSpec<?, ArgumentT, OutputT> actionSpec,
-            AppAction appAction,
-            TaskHandler<ConfirmationT> taskHandler,
-            BaseSession<ArgumentT, OutputT> externalSession,
-            Executor executor) {
-        this.mActionSpec = actionSpec;
-        this.mAppAction = appAction;
-        this.mTaskHandler = taskHandler;
-        this.mExternalSession = externalSession;
-        this.mExecutor = executor;
-
-        this.mCurrentValuesMap = Collections.synchronizedMap(new HashMap<>());
-        this.mTaskStatus = ActionCapabilitySession.Status.UNINITIATED;
-    }
-    // Set a TouchEventCallback instance. This callback is invoked when state changes from manual
-    // input.
-    void setTouchEventCallback(@Nullable TouchEventCallback touchEventCallback) {
-        this.mTouchEventCallback = touchEventCallback;
-    }
-
-    /** Returns whether or not a request is currently being processed */
-    boolean isIdle() {
-        synchronized (mTaskOrchestratorLock) {
-            return mIsIdle;
-        }
-    }
-
-    ActionCapabilitySession.Status getStatus() {
-        return mTaskStatus;
-    }
-
-    /**
-     * processes the provided UpdateRequest asynchronously.
-     *
-     * <p>Returns a {@code ListenableFuture<Void>} that is completed when the request handling is
-     * completed.
-     *
-     * <p>An unhandled exception when handling an UpdateRequest will cause all future update
-     * requests to fail.
-     *
-     * <p>This method should never be called when isIdle() returns false.
-     */
-    ListenableFuture<Void> processUpdateRequest(UpdateRequest updateRequest) {
-        synchronized (mTaskOrchestratorLock) {
-            if (!mIsIdle) {
-                throw new IllegalStateException(
-                        "processUpdateRequest should never be called when isIdle is false.");
-            }
-            mIsIdle = false;
-            ListenableFuture<Void> requestProcessingFuture;
-            if (updateRequest.getAssistantRequest() != null) {
-                requestProcessingFuture =
-                        processAssistantUpdateRequest(updateRequest.getAssistantRequest());
-            } else if (updateRequest.getTouchEventRequest() != null) {
-                requestProcessingFuture =
-                        processTouchEventUpdateRequest(updateRequest.getTouchEventRequest());
-            }  else {
-                throw new IllegalArgumentException("unknown UpdateRequest type");
-            }
-            return Futures.transform(
-                    requestProcessingFuture,
-                    unused -> {
-                        synchronized (mTaskOrchestratorLock) {
-                            mIsIdle = true;
-                            return null;
-                        }
-                    },
-                    mExecutor,
-                    "set isIdle");
-        }
-    }
-
-    /** Processes an assistant update request. */
-    private ListenableFuture<Void> processAssistantUpdateRequest(
-            AssistantUpdateRequest assistantUpdateRequest) {
-        ArgumentsWrapper argumentsWrapper = assistantUpdateRequest.getArgumentsWrapper();
-        CallbackInternal callback = assistantUpdateRequest.getCallbackInternal();
-
-        if (argumentsWrapper.getRequestMetadata() == null) {
-            callback.onError(ErrorStatusInternal.INVALID_REQUEST_TYPE);
-            return Futures.immediateVoidFuture();
-        }
-        Fulfillment.Type requestType = argumentsWrapper.getRequestMetadata().requestType();
-        switch (requestType) {
-            case UNRECOGNIZED:
-            case UNKNOWN_TYPE:
-                callback.onError(ErrorStatusInternal.INVALID_REQUEST_TYPE);
-                break;
-            case SYNC:
-                return handleSync(argumentsWrapper, callback);
-            case CONFIRM:
-                return handleConfirm(callback);
-            case CANCEL:
-            case TERMINATE:
-                terminate();
-                callback.onSuccess(FulfillmentResponse.getDefaultInstance());
-                break;
-        }
-        return Futures.immediateVoidFuture();
-    }
-
-    public ListenableFuture<Void> processTouchEventUpdateRequest(
-            TouchEventUpdateRequest touchEventUpdateRequest) {
-        Map<String, List<ParamValue>> paramValuesMap = touchEventUpdateRequest.getParamValuesMap();
-        if (mTouchEventCallback == null
-                || paramValuesMap.isEmpty()
-                || mTaskStatus != ActionCapabilitySession.Status.IN_PROGRESS) {
-            return Futures.immediateVoidFuture();
-        }
-        for (Map.Entry<String, List<ParamValue>> entry : paramValuesMap.entrySet()) {
-            String argName = entry.getKey();
-            mCurrentValuesMap.put(
-                    argName,
-                    entry.getValue().stream()
-                            .map(
-                                    paramValue ->
-                                            TaskCapabilityUtils.toCurrentValue(
-                                                    paramValue, Status.ACCEPTED))
-                            .collect(toImmutableList()));
-        }
-        ListenableFuture<Void> argumentsProcessingFuture;
-        if (anyParamsOfStatus(Status.DISAMBIG)) {
-            argumentsProcessingFuture = Futures.immediateVoidFuture();
-        } else {
-            Map<String, List<FulfillmentValue>> fulfillmentValuesMap =
-                    TaskCapabilityUtils.paramValuesMapToFulfillmentValuesMap(
-                            getCurrentPendingArguments());
-            argumentsProcessingFuture = processFulfillmentValues(fulfillmentValuesMap);
-        }
-
-        ListenableFuture<FulfillmentResponse> fulfillmentResponseFuture =
-                Futures.transformAsync(
-                        argumentsProcessingFuture,
-                        (unused) -> maybeConfirmOrFinish(),
-                        mExecutor,
-                        "maybeConfirmOrFinish");
-
-        return invokeTouchEventCallback(fulfillmentResponseFuture);
-    }
-
-    private ListenableFuture<Void> invokeTouchEventCallback(
-            ListenableFuture<FulfillmentResponse> fulfillmentResponseFuture) {
-        return CallbackToFutureAdapter.getFuture(
-                completer -> {
-                    Futures.addCallback(
-                            fulfillmentResponseFuture,
-                            new FutureCallback<FulfillmentResponse>() {
-                                @Override
-                                public void onSuccess(FulfillmentResponse fulfillmentResponse) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.INFO,
-                                            LOG_TAG,
-                                            "Manual input success");
-                                    if (mTouchEventCallback != null) {
-                                        mTouchEventCallback.onSuccess(
-                                                fulfillmentResponse,
-                                                TouchEventMetadata.getDefaultInstance());
-                                    } else {
-                                        LoggerInternal.log(
-                                                CapabilityLogger.LogLevel.ERROR,
-                                                LOG_TAG,
-                                                "Manual input null callback");
-                                    }
-                                    completer.set(null);
-                                }
-
-                                @Override
-                                public void onFailure(@NonNull Throwable t) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.ERROR,
-                                            LOG_TAG,
-                                            "Manual input fail");
-                                    if (mTouchEventCallback != null) {
-                                        mTouchEventCallback.onError(
-                                                ErrorStatusInternal.TOUCH_EVENT_REQUEST_FAILURE);
-                                    } else {
-                                        LoggerInternal.log(
-                                                CapabilityLogger.LogLevel.ERROR,
-                                                LOG_TAG,
-                                                "Manual input null callback");
-                                    }
-                                    completer.set(null);
-                                }
-                            },
-                            mExecutor);
-                    return "handle fulfillmentResponseFuture for manual input";
-                });
-    }
-
-    // TODO: add cleanup logic if any
-    void terminate() {
-        this.mExternalSession.onDestroy();
-        this.mTaskStatus = ActionCapabilitySession.Status.DESTROYED;
-    }
-
-    /**
-     * If slot filling is incomplete, the future contains default FulfillmentResponse.
-     *
-     * <p>Otherwise, the future contains a FulfillmentResponse containing BIC or BIO data.
-     */
-    private ListenableFuture<FulfillmentResponse> maybeConfirmOrFinish() {
-        Map<String, List<ParamValue>> finalArguments = getCurrentAcceptedArguments();
-        if (anyParamsOfStatus(Status.REJECTED)
-                || !TaskCapabilityUtils.isSlotFillingComplete(
-                        finalArguments, mAppAction.getParamsList())) {
-            return Futures.immediateFuture(FulfillmentResponse.getDefaultInstance());
-        }
-        if (mTaskHandler.getOnReadyToConfirmListener() != null) {
-            return getFulfillmentResponseForConfirmation(finalArguments);
-        }
-        return getFulfillmentResponseForExecution(finalArguments);
-    }
-
-    private ListenableFuture<Void> maybeInitializeTask() {
-        if (this.mTaskStatus == ActionCapabilitySession.Status.UNINITIATED) {
-            mExternalSession.onInit(new InitArg());
-        }
-        this.mTaskStatus = ActionCapabilitySession.Status.IN_PROGRESS;
-        return Futures.immediateVoidFuture();
-    }
-
-    /**
-     * Handles a SYNC request from assistant.
-     *
-     * <p>Control-flow logic for a single task turn. Note, a task may start and finish in the same
-     * turn, so the logic should include onEnter, arg validation, and onExit.
-     */
-    private ListenableFuture<Void> handleSync(
-            ArgumentsWrapper argumentsWrapper, CallbackInternal callback) {
-        ListenableFuture<Void> onInitFuture = maybeInitializeTask();
-
-        clearMissingArgs(argumentsWrapper);
-        ListenableFuture<Void> argResolutionFuture =
-                Futures.transformAsync(
-                        onInitFuture,
-                        unused -> processFulfillmentValues(argumentsWrapper.getParamValues()),
-                        mExecutor,
-                        "processFulfillmentValues");
-
-        ListenableFuture<FulfillmentResponse> fulfillmentResponseFuture =
-                Futures.transformAsync(
-                        argResolutionFuture,
-                        unused -> maybeConfirmOrFinish(),
-                        mExecutor,
-                        "maybeConfirmOrFinish");
-        return CallbackToFutureAdapter.getFuture(
-                completer -> {
-                    Futures.addCallback(
-                            fulfillmentResponseFuture,
-                            new FutureCallback<FulfillmentResponse>() {
-                                @Override
-                                public void onSuccess(FulfillmentResponse fulfillmentResponse) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.INFO,
-                                            LOG_TAG,
-                                            "Task sync success");
-                                    callback.onSuccess(fulfillmentResponse);
-                                    completer.set(null);
-                                }
-
-                                @Override
-                                public void onFailure(@NonNull Throwable t) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.ERROR,
-                                            LOG_TAG,
-                                            "Task sync fail",
-                                            t);
-                                    callback.onError(ErrorStatusInternal.SYNC_REQUEST_FAILURE);
-                                    completer.set(null);
-                                }
-                            },
-                            mExecutor);
-                    return "handle fulfillmentResponseFuture for SYNC";
-                });
-    }
-
-    /**
-     * Control-flow logic for a single task turn in which the user has confirmed in the previous
-     * turn.
-     */
-    private ListenableFuture<Void> handleConfirm(CallbackInternal callback) {
-        Map<String, List<ParamValue>> finalArguments = getCurrentAcceptedArguments();
-        return CallbackToFutureAdapter.getFuture(
-                completer -> {
-                    Futures.addCallback(
-                            getFulfillmentResponseForExecution(finalArguments),
-                            new FutureCallback<FulfillmentResponse>() {
-                                @Override
-                                public void onSuccess(FulfillmentResponse fulfillmentResponse) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.INFO,
-                                            LOG_TAG,
-                                            "Task confirm success");
-                                    callback.onSuccess(fulfillmentResponse);
-                                    completer.set(null);
-                                }
-
-                                @Override
-                                public void onFailure(@NonNull Throwable t) {
-                                    LoggerInternal.log(
-                                            CapabilityLogger.LogLevel.ERROR,
-                                            LOG_TAG,
-                                            "Task confirm fail");
-                                    callback.onError(
-                                            ErrorStatusInternal.CONFIRMATION_REQUEST_FAILURE);
-                                    completer.set(null);
-                                }
-                            },
-                            mExecutor);
-                    return "handle fulfillmentResponseFuture for CONFIRM";
-                });
-    }
-
-    private void clearMissingArgs(ArgumentsWrapper assistantArgs) {
-        Set<String> argsCleared =
-                mCurrentValuesMap.keySet().stream()
-                        .filter(argName -> !assistantArgs.getParamValues().containsKey(argName))
-                        .collect(toImmutableSet());
-        for (String arg : argsCleared) {
-            mCurrentValuesMap.remove(arg);
-            // TODO(b/234170829): notify listener#onReceived of the cleared arguments
-        }
-    }
-
-    /**
-     * Main processing chain for both assistant requests and manual input requests. All pending
-     * parameters contained in fulfillmentValuesMap are chained together in a serial fassion. We use
-     * Futures here to make sure long running app processing (such as argument grounding or argument
-     * validation) are executed asynchronously.
-     */
-    private ListenableFuture<Void> processFulfillmentValues(
-            Map<String, List<FulfillmentValue>> fulfillmentValuesMap) {
-        ListenableFuture<SlotProcessingResult> currentFuture =
-                Futures.immediateFuture(new SlotProcessingResult(true, Collections.emptyList()));
-        for (Map.Entry<String, List<FulfillmentValue>> entry : fulfillmentValuesMap.entrySet()) {
-            String name = entry.getKey();
-            List<FulfillmentValue> fulfillmentValues = entry.getValue();
-            currentFuture =
-                    Futures.transformAsync(
-                            currentFuture,
-                            (previousResult) ->
-                                    maybeProcessSlotAndUpdateCurrentValues(
-                                            previousResult, name, fulfillmentValues),
-                            mExecutor,
-                            "maybeProcessSlotAndUpdateCurrentValues");
-        }
-        // Transform the final Boolean future to a void one.
-        return Futures.transform(currentFuture, (unused) -> null, mExecutor, "return null");
-    }
-
-    private ListenableFuture<SlotProcessingResult> maybeProcessSlotAndUpdateCurrentValues(
-            SlotProcessingResult previousResult,
-            String slotKey,
-            List<FulfillmentValue> newSlotValues) {
-        List<CurrentValue> currentSlotValues =
-                mCurrentValuesMap.getOrDefault(slotKey, Collections.emptyList());
-        List<FulfillmentValue> modifiedSlotValues =
-                TaskCapabilityUtils.getMaybeModifiedSlotValues(currentSlotValues, newSlotValues);
-        if (TaskCapabilityUtils.canSkipSlotProcessing(currentSlotValues, modifiedSlotValues)) {
-            return Futures.immediateFuture(previousResult);
-        }
-        List<CurrentValue> pendingArgs =
-                TaskCapabilityUtils.fulfillmentValuesToCurrentValues(
-                        modifiedSlotValues, Status.PENDING);
-        return Futures.transform(
-                processSlot(slotKey, previousResult, pendingArgs),
-                currentResult -> {
-                    mCurrentValuesMap.put(slotKey, currentResult.getProcessedValues());
-                    return currentResult;
-                },
-                mExecutor,
-                "update currentValuesMap");
-    }
-
-    /**
-     * Process pending param values for a slot.
-     *
-     * <p>If the previous slot was accepted, go through grounding/validation with TaskSlotProcessor,
-     * otherwise just return the pending values as is.
-     */
-    private ListenableFuture<SlotProcessingResult> processSlot(
-            String name, SlotProcessingResult previousResult, List<CurrentValue> pendingArgs) {
-        if (!previousResult.isSuccessful()) {
-            return Futures.immediateFuture(new SlotProcessingResult(false, pendingArgs));
-        }
-        return TaskSlotProcessor.processSlot(
-                name, pendingArgs, mTaskHandler.getTaskParamMap(), mExecutor);
-    }
-
-    /**
-     * Retrieve all ParamValue from accepted slots in currentValuesMap.
-     *
-     * <p>A slot is considered accepted if all CurrentValues in the slot has ACCEPTED status.
-     */
-    private Map<String, List<ParamValue>> getCurrentAcceptedArguments() {
-        return mCurrentValuesMap.entrySet().stream()
-                .filter(
-                        entry ->
-                                entry.getValue().stream()
-                                        .allMatch(
-                                                currentValue ->
-                                                        currentValue.getStatus()
-                                                                == Status.ACCEPTED))
-                .collect(
-                        toImmutableMap(
-                                Map.Entry::getKey,
-                                entry ->
-                                        entry.getValue().stream()
-                                                .map(CurrentValue::getValue)
-                                                .collect(toImmutableList())));
-    }
-
-    /**
-     * Retrieve all ParamValue from pending slots in currentValuesMap.
-     *
-     * <p>A slot is considered pending if any CurrentValues in the slot has PENDING status.
-     */
-    private Map<String, List<ParamValue>> getCurrentPendingArguments() {
-        return mCurrentValuesMap.entrySet().stream()
-                .filter(
-                        entry ->
-                                entry.getValue().stream()
-                                        .anyMatch(
-                                                currentValue ->
-                                                        currentValue.getStatus() == Status.PENDING))
-                .collect(
-                        toImmutableMap(
-                                Map.Entry::getKey,
-                                entry ->
-                                        entry.getValue().stream()
-                                                .map(CurrentValue::getValue)
-                                                .collect(toImmutableList())));
-    }
-
-    /** Returns true if any CurrentValue in currentValuesMap has the given Status. */
-    private boolean anyParamsOfStatus(Status status) {
-        return mCurrentValuesMap.entrySet().stream()
-                .anyMatch(
-                        entry ->
-                                entry.getValue().stream()
-                                        .anyMatch(
-                                                currentValue ->
-                                                        currentValue.getStatus() == status));
-    }
-
-    private ListenableFuture<ConfirmationOutput<ConfirmationT>> executeOnTaskReadyToConfirm(
-            Map<String, List<ParamValue>> finalArguments) {
-        try {
-            return Objects.requireNonNull(mTaskHandler.getOnReadyToConfirmListener())
-                    .onReadyToConfirm(finalArguments);
-        } catch (StructConversionException | MissingRequiredArgException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-    }
-
-    private ListenableFuture<ExecutionResult<OutputT>> executeOnTaskFinish(
-            Map<String, List<ParamValue>> finalArguments) {
-        ListenableFuture<ExecutionResult<OutputT>> executionResultFuture;
-        try {
-            executionResultFuture =
-                    mExternalSession.onFinishAsync(mActionSpec.buildArgument(finalArguments));
-        } catch (StructConversionException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-        return Futures.transform(
-                executionResultFuture,
-                executionResult -> {
-                    this.mTaskStatus = ActionCapabilitySession.Status.COMPLETED;
-                    return executionResult;
-                },
-                mExecutor,
-                "set taskStatus to COMPLETED");
-    }
-
-    private ListenableFuture<FulfillmentResponse> getFulfillmentResponseForConfirmation(
-            Map<String, List<ParamValue>> finalArguments) {
-        return Futures.transform(
-                executeOnTaskReadyToConfirm(finalArguments),
-                result -> {
-                    FulfillmentResponse.Builder fulfillmentResponse =
-                            FulfillmentResponse.newBuilder();
-                    convertToConfirmationOutput(result)
-                            .ifPresent(fulfillmentResponse::setConfirmationData);
-                    return fulfillmentResponse.build();
-                },
-                mExecutor,
-                "create FulfillmentResponse from ConfirmationOutput");
-    }
-
-    private ListenableFuture<FulfillmentResponse> getFulfillmentResponseForExecution(
-            Map<String, List<ParamValue>> finalArguments) {
-        return Futures.transform(
-                executeOnTaskFinish(finalArguments),
-                result -> {
-                    FulfillmentResponse.Builder fulfillmentResponse =
-                            FulfillmentResponse.newBuilder();
-                    if (mTaskStatus == ActionCapabilitySession.Status.COMPLETED) {
-                        convertToExecutionOutput(result)
-                                .ifPresent(fulfillmentResponse::setExecutionOutput);
-                    }
-                    return fulfillmentResponse.build();
-                },
-                mExecutor,
-                "create FulfillmentResponse from ExecutionResult");
-    }
-
-    AppDialogState getAppDialogState() {
-        AppDialogState.Builder appDialogStateBuilder = AppDialogState.newBuilder();
-        mAppAction.getParamsList().stream()
-                .forEach(
-                        intentParam -> {
-                            List<CurrentValue> vals = mCurrentValuesMap.get(intentParam.getName());
-                            DialogParameter.Builder dialogParameterBuilder =
-                                    DialogParameter.newBuilder().setName(intentParam.getName());
-                            if (vals != null) {
-                                dialogParameterBuilder.addAllCurrentValue(vals);
-                            }
-                            appDialogStateBuilder.addParams(dialogParameterBuilder);
-                        });
-        return appDialogStateBuilder.setFulfillmentIdentifier(mAppAction.getIdentifier()).build();
-    }
-
-    /** Convert from java capabilities {@link ExecutionResult} to {@link StructuredOutput} proto. */
-    private Optional<StructuredOutput> convertToExecutionOutput(
-            ExecutionResult<OutputT> executionResult) {
-        OutputT output = executionResult.getOutput();
-        if (output == null) {
-            return Optional.empty();
-        }
-
-        return Optional.of(mActionSpec.convertOutputToProto(output));
-    }
-
-    /**
-     * Convert from java capabilities {@link ConfirmationOutput} to {@link StructuredOutput} proto.
-     */
-    private Optional<StructuredOutput> convertToConfirmationOutput(
-            ConfirmationOutput<ConfirmationT> confirmationOutput) {
-        ConfirmationT confirmation = confirmationOutput.getConfirmation();
-        if (confirmation == null || confirmation instanceof Void) {
-            return Optional.empty();
-        }
-
-        StructuredOutput.Builder confirmationOutputBuilder = StructuredOutput.newBuilder();
-        for (Map.Entry<String, Function<ConfirmationT, List<ParamValue>>> entry :
-                mTaskHandler.getConfirmationDataBindings().entrySet()) {
-            confirmationOutputBuilder.addOutputValues(
-                    StructuredOutput.OutputValue.newBuilder()
-                            .setName(entry.getKey())
-                            .addAllValues(entry.getValue().apply(confirmation))
-                            .build());
-        }
-        return Optional.of(confirmationOutputBuilder.build());
-    }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.kt
new file mode 100644
index 0000000..90b48d2
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskOrchestrator.kt
@@ -0,0 +1,470 @@
+/*
+ * 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.appactions.interaction.capabilities.core.task.impl
+
+import androidx.annotation.GuardedBy
+import androidx.appactions.interaction.capabilities.core.BaseSession
+import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
+import androidx.appactions.interaction.capabilities.core.ExecutionResult
+import androidx.appactions.interaction.capabilities.core.InitArg
+import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession
+import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
+import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
+import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
+import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
+import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
+import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
+import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
+import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.InvalidResolverException
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingEntityConverterException
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingRequiredArgException
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingSearchActionConverterException
+import androidx.appactions.interaction.proto.AppActionsContext
+import androidx.appactions.interaction.proto.CurrentValue
+import androidx.appactions.interaction.proto.FulfillmentRequest
+import androidx.appactions.interaction.proto.FulfillmentResponse
+import androidx.appactions.interaction.proto.ParamValue
+import androidx.appactions.interaction.proto.TouchEventMetadata
+import androidx.concurrent.futures.await
+import java.util.concurrent.locks.ReentrantReadWriteLock
+import kotlin.concurrent.read
+import kotlin.concurrent.write
+import kotlin.jvm.Throws
+
+/**
+ * TaskOrchestrator is responsible for holding session state, and processing assistant / manual
+ * input updates to update session state.
+ *
+ * TaskOrchestrator is also responsible to communicating state updates to developer provided
+ * listeners.
+ *
+ * Only one request can be processed at a time.
+ */
+internal class TaskOrchestrator<ArgumentT, OutputT, ConfirmationT>(
+    private val actionSpec: ActionSpec<*, ArgumentT, OutputT>,
+    private val appAction: AppActionsContext.AppAction,
+    private val taskHandler: TaskHandler<ConfirmationT>,
+    private val externalSession: BaseSession<ArgumentT, OutputT>
+) {
+    /**
+     * A [reader-writer lock](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock) to protect
+     * the synchronizing operation on [currentValuesMap]
+     */
+    private val valuesMapLock = ReentrantReadWriteLock()
+
+    /** Map of argument name to the [CurrentValue] which wraps the argument name and status . */
+    @GuardedBy("valuesMapLock")
+    private val currentValuesMap = mutableMapOf<String, List<CurrentValue>>()
+
+    /**
+     * The callback that should be invoked when manual input processing finishes. This sends the
+     * processing results to the AppInteraction SDKs. Note, this field is not provided on
+     * construction because the callback is not available at the time when the developer creates the
+     * capability.
+     */
+    private var mTouchEventCallback: TouchEventCallback? = null
+
+    /** Current status of the overall task (i.e. status of the task). */
+    internal var status: ActionCapabilitySession.Status = ActionCapabilitySession.Status.UNINITIATED
+        private set
+
+    // Set a TouchEventCallback instance. This callback is invoked when state changes from manual
+    // input.
+    internal fun setTouchEventCallback(touchEventCallback: TouchEventCallback?) {
+        mTouchEventCallback = touchEventCallback
+    }
+
+    private val inProgressLock = Any()
+
+    @GuardedBy("inProgressLock") private var inProgress = false
+
+    /** Returns whether or not a request is currently being processed */
+    internal fun isIdle(): Boolean = synchronized(inProgressLock) { !inProgress }
+
+    internal val appDialogState: AppActionsContext.AppDialogState
+        get() =
+            AppActionsContext.AppDialogState.newBuilder()
+                .addAllParams(
+                    valuesMapLock.read {
+                        appAction.paramsList.map { intentParam ->
+                            val dialogParameterBuilder =
+                                AppActionsContext.DialogParameter.newBuilder()
+                                    .setName(intentParam.name)
+                            currentValuesMap[intentParam.name]?.let {
+                                dialogParameterBuilder.addAllCurrentValue(it)
+                            }
+                            dialogParameterBuilder.build()
+                        }
+                    }
+                )
+                .setFulfillmentIdentifier(appAction.identifier)
+                .build()
+
+    /**
+     * processes the provided UpdateRequest asynchronously.
+     *
+     * Returns when the request handling is completed.
+     *
+     * An unhandled exception when handling an UpdateRequest will cause all future update requests
+     * to fail.
+     *
+     * This method should never be called when isIdle() returns false.
+     */
+    internal suspend fun processUpdateRequest(updateRequest: UpdateRequest) {
+        synchronized(inProgressLock) {
+            if (inProgress) {
+                throw IllegalStateException(
+                    "processUpdateRequest should never be called when the task orchestrator" +
+                        " isn't idle."
+                )
+            }
+            inProgress = true
+        }
+        try {
+            if (updateRequest.assistantRequest != null) {
+                processAssistantUpdateRequest(updateRequest.assistantRequest)
+            } else if (updateRequest.touchEventRequest != null) {
+                processTouchEventUpdateRequest(updateRequest.touchEventRequest)
+            } else {
+                throw IllegalArgumentException("unknown UpdateRequest type")
+            }
+        } finally {
+            synchronized(inProgressLock) { inProgress = false }
+        }
+    }
+
+    /** Processes an assistant update request. */
+    @Suppress("DEPRECATION")
+    private suspend fun processAssistantUpdateRequest(
+        assistantUpdateRequest: AssistantUpdateRequest
+    ) {
+        val argumentsWrapper = assistantUpdateRequest.argumentsWrapper
+        val callback = assistantUpdateRequest.callbackInternal
+        if (argumentsWrapper.requestMetadata == null) {
+            callback.onError(ErrorStatusInternal.INVALID_REQUEST_TYPE)
+            return
+        }
+        when (argumentsWrapper.requestMetadata.requestType()) {
+            FulfillmentRequest.Fulfillment.Type.UNRECOGNIZED,
+            FulfillmentRequest.Fulfillment.Type.UNKNOWN_TYPE ->
+                callback.onError(ErrorStatusInternal.INVALID_REQUEST_TYPE)
+            FulfillmentRequest.Fulfillment.Type.SYNC -> handleSync(argumentsWrapper, callback)
+            FulfillmentRequest.Fulfillment.Type.CONFIRM -> handleConfirm(callback)
+            FulfillmentRequest.Fulfillment.Type.CANCEL,
+            FulfillmentRequest.Fulfillment.Type.TERMINATE -> {
+                terminate()
+                callback.onSuccess(FulfillmentResponse.getDefaultInstance())
+            }
+        }
+    }
+
+    private suspend fun processTouchEventUpdateRequest(
+        touchEventUpdateRequest: TouchEventUpdateRequest
+    ) {
+        val paramValuesMap = touchEventUpdateRequest.paramValuesMap
+        if (
+            mTouchEventCallback == null ||
+                paramValuesMap.isEmpty() ||
+                status !== ActionCapabilitySession.Status.IN_PROGRESS
+        ) {
+            return
+        }
+        valuesMapLock.write {
+            for ((argName, value) in paramValuesMap) {
+                currentValuesMap[argName] =
+                    value.map {
+                        TaskCapabilityUtils.toCurrentValue(it, CurrentValue.Status.ACCEPTED)
+                    }
+            }
+        }
+
+        try {
+            if (!anyParamsOfStatus(CurrentValue.Status.DISAMBIG)) {
+                val fulfillmentValuesMap =
+                    TaskCapabilityUtils.paramValuesMapToFulfillmentValuesMap(
+                        getCurrentPendingArguments()
+                    )
+                processFulfillmentValues(fulfillmentValuesMap)
+            }
+            val fulfillmentResponse = maybeConfirmOrFinish()
+            LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Manual input success")
+            if (mTouchEventCallback != null) {
+                mTouchEventCallback!!.onSuccess(
+                    fulfillmentResponse,
+                    TouchEventMetadata.getDefaultInstance()
+                )
+            } else {
+                LoggerInternal.log(
+                    CapabilityLogger.LogLevel.ERROR,
+                    LOG_TAG,
+                    "Manual input null callback"
+                )
+            }
+        } catch (t: Throwable) {
+            LoggerInternal.log(CapabilityLogger.LogLevel.ERROR, LOG_TAG, "Manual input fail")
+            if (mTouchEventCallback != null) {
+                mTouchEventCallback!!.onError(ErrorStatusInternal.TOUCH_EVENT_REQUEST_FAILURE)
+            } else {
+                LoggerInternal.log(
+                    CapabilityLogger.LogLevel.ERROR,
+                    LOG_TAG,
+                    "Manual input null callback"
+                )
+            }
+        }
+    }
+
+    // TODO: add cleanup logic if any
+    internal fun terminate() {
+        externalSession.onDestroy()
+        status = ActionCapabilitySession.Status.DESTROYED
+    }
+
+    /**
+     * If slot filling is incomplete, the future contains default FulfillmentResponse.
+     *
+     * Otherwise, the future contains a FulfillmentResponse containing BIC or BIO data.
+     */
+    @Throws(StructConversionException::class, MissingRequiredArgException::class)
+    private suspend fun maybeConfirmOrFinish(): FulfillmentResponse {
+        val finalArguments = getCurrentAcceptedArguments()
+        if (
+            anyParamsOfStatus(CurrentValue.Status.REJECTED) ||
+                !TaskCapabilityUtils.isSlotFillingComplete(finalArguments, appAction.paramsList)
+        ) {
+            return FulfillmentResponse.getDefaultInstance()
+        }
+        return if (taskHandler.onReadyToConfirmListener != null)
+            getFulfillmentResponseForConfirmation(finalArguments)
+        else getFulfillmentResponseForExecution(finalArguments)
+    }
+
+    private fun maybeInitializeTask() {
+        if (status === ActionCapabilitySession.Status.UNINITIATED) {
+            externalSession.onInit(InitArg())
+        }
+        status = ActionCapabilitySession.Status.IN_PROGRESS
+    }
+
+    /**
+     * Handles a SYNC request from assistant.
+     *
+     * Control-flow logic for a single task turn. Note, a task may start and finish in the same
+     * turn, so the logic should include onEnter, arg validation, and onExit.
+     */
+    private suspend fun handleSync(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {
+        maybeInitializeTask()
+        clearMissingArgs(argumentsWrapper)
+        try {
+            processFulfillmentValues(argumentsWrapper.paramValues)
+            val fulfillmentResponse = maybeConfirmOrFinish()
+            LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Task sync success")
+            callback.onSuccess(fulfillmentResponse)
+        } catch (t: Throwable) {
+            LoggerInternal.log(CapabilityLogger.LogLevel.ERROR, LOG_TAG, "Task sync fail", t)
+            callback.onError(ErrorStatusInternal.SYNC_REQUEST_FAILURE)
+        }
+    }
+
+    /**
+     * Control-flow logic for a single task turn in which the user has confirmed in the previous
+     * turn.
+     */
+    private suspend fun handleConfirm(callback: CallbackInternal) {
+        val finalArguments = getCurrentAcceptedArguments()
+        try {
+            val fulfillmentResponse = getFulfillmentResponseForExecution(finalArguments)
+            LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Task confirm success")
+            callback.onSuccess(fulfillmentResponse)
+        } catch (t: Throwable) {
+            LoggerInternal.log(CapabilityLogger.LogLevel.ERROR, LOG_TAG, "Task confirm fail")
+            callback.onError(ErrorStatusInternal.CONFIRMATION_REQUEST_FAILURE)
+        }
+    }
+
+    private fun clearMissingArgs(assistantArgs: ArgumentsWrapper) {
+        valuesMapLock.write {
+            val argsCleared =
+                currentValuesMap.keys.filter { !assistantArgs.paramValues.containsKey(it) }
+            for (arg in argsCleared) {
+                currentValuesMap.remove(arg)
+                // TODO(b/234170829): notify listener#onReceived of the cleared arguments
+            }
+        }
+    }
+
+    /**
+     * Main processing chain for both assistant requests and manual input requests. All pending
+     * parameters contained in fulfillmentValuesMap are chained together in a serial fashion. We use
+     * Futures here to make sure long running app processing (such as argument grounding or argument
+     * validation) are executed asynchronously.
+     */
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    private suspend fun processFulfillmentValues(
+        fulfillmentValuesMap: Map<String, List<FulfillmentRequest.Fulfillment.FulfillmentValue>>
+    ) {
+        var currentResult = SlotProcessingResult(true, emptyList())
+        for ((name, fulfillmentValues) in fulfillmentValuesMap) {
+            currentResult =
+                maybeProcessSlotAndUpdateCurrentValues(currentResult, name, fulfillmentValues)
+        }
+    }
+
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    private suspend fun maybeProcessSlotAndUpdateCurrentValues(
+        previousResult: SlotProcessingResult,
+        slotKey: String,
+        newSlotValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>
+    ): SlotProcessingResult {
+        val currentSlotValues =
+            valuesMapLock.read { currentValuesMap.getOrDefault(slotKey, emptyList()) }
+        val modifiedSlotValues =
+            TaskCapabilityUtils.getMaybeModifiedSlotValues(currentSlotValues, newSlotValues)
+        if (TaskCapabilityUtils.canSkipSlotProcessing(currentSlotValues, modifiedSlotValues)) {
+            return previousResult
+        }
+        val pendingArgs =
+            TaskCapabilityUtils.fulfillmentValuesToCurrentValues(
+                modifiedSlotValues,
+                CurrentValue.Status.PENDING
+            )
+        val currentResult = processSlot(slotKey, previousResult, pendingArgs)
+        valuesMapLock.write { currentValuesMap[slotKey] = currentResult.processedValues }
+        return currentResult
+    }
+
+    /**
+     * Process pending param values for a slot.
+     *
+     * If the previous slot was accepted, go through grounding/validation with TaskSlotProcessor,
+     * otherwise just return the pending values as is.
+     */
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    private suspend fun processSlot(
+        name: String,
+        previousResult: SlotProcessingResult,
+        pendingArgs: List<CurrentValue>
+    ): SlotProcessingResult {
+        return if (!previousResult.isSuccessful) SlotProcessingResult(false, pendingArgs)
+        else TaskSlotProcessor.processSlot(name, pendingArgs, taskHandler.taskParamMap)
+    }
+
+    /**
+     * Retrieve all ParamValue from accepted slots in currentValuesMap.
+     *
+     * A slot is considered accepted if all CurrentValues in the slot has ACCEPTED status.
+     */
+    private fun getCurrentAcceptedArguments(): Map<String, List<ParamValue>> =
+        valuesMapLock
+            .read {
+                currentValuesMap.filterValues { currentValues ->
+                    currentValues.all { it.status == CurrentValue.Status.ACCEPTED }
+                }
+            }
+            .mapValues { currentValue -> currentValue.value.map { it.value } }
+
+    /**
+     * Retrieve all ParamValue from pending slots in currentValuesMap.
+     *
+     * A slot is considered pending if any CurrentValues in the slot has PENDING status.
+     */
+    private fun getCurrentPendingArguments(): Map<String, List<ParamValue>> =
+        valuesMapLock
+            .read {
+                currentValuesMap.filterValues { currentValues ->
+                    currentValues.any { it.status == CurrentValue.Status.PENDING }
+                }
+            }
+            .mapValues { currentValues -> currentValues.value.map { it.value } }
+
+    /** Returns true if any CurrentValue in currentValuesMap has the given Status. */
+    private fun anyParamsOfStatus(status: CurrentValue.Status) =
+        valuesMapLock.read {
+            currentValuesMap.values.any { currentValues ->
+                currentValues.any { it.status == status }
+            }
+        }
+
+    @Throws(StructConversionException::class, MissingRequiredArgException::class)
+    private suspend fun getFulfillmentResponseForConfirmation(
+        finalArguments: Map<String, List<ParamValue>>
+    ): FulfillmentResponse {
+        val result = taskHandler.onReadyToConfirmListener!!.onReadyToConfirm(finalArguments).await()
+        val fulfillmentResponse = FulfillmentResponse.newBuilder()
+        convertToConfirmationOutput(result)?.let { fulfillmentResponse.confirmationData = it }
+        return fulfillmentResponse.build()
+    }
+
+    @Throws(StructConversionException::class)
+    private suspend fun getFulfillmentResponseForExecution(
+        finalArguments: Map<String, List<ParamValue>>
+    ): FulfillmentResponse {
+        val result = externalSession.onFinishAsync(actionSpec.buildArgument(finalArguments)).await()
+        status = ActionCapabilitySession.Status.COMPLETED
+        val fulfillmentResponse = FulfillmentResponse.newBuilder()
+        convertToExecutionOutput(result)?.let { fulfillmentResponse.executionOutput = it }
+        return fulfillmentResponse.build()
+    }
+
+    /**
+     * Convert from java capabilities [ExecutionResult] to [FulfillmentResponse.StructuredOutput]
+     * proto.
+     */
+    private fun convertToExecutionOutput(
+        executionResult: ExecutionResult<OutputT>
+    ): FulfillmentResponse.StructuredOutput? =
+        executionResult.output?.let { actionSpec.convertOutputToProto(it) }
+
+    /**
+     * Convert from java capabilities [ConfirmationOutput] to [FulfillmentResponse.StructuredOutput]
+     * proto.
+     */
+    private fun convertToConfirmationOutput(
+        confirmationOutput: ConfirmationOutput<ConfirmationT>
+    ): FulfillmentResponse.StructuredOutput? {
+        val confirmation = confirmationOutput.confirmation ?: return null
+        return FulfillmentResponse.StructuredOutput.newBuilder()
+            .addAllOutputValues(
+                taskHandler.confirmationDataBindings.entries.map {
+                    FulfillmentResponse.StructuredOutput.OutputValue.newBuilder()
+                        .setName(it.key)
+                        .addAllValues(it.value.apply(confirmation))
+                        .build()
+                }
+            )
+            .build()
+    }
+
+    companion object {
+        private const val LOG_TAG = "TaskOrchestrator"
+    }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.java
deleted file mode 100644
index a20e3c8..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.java
+++ /dev/null
@@ -1,349 +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.appactions.interaction.capabilities.core.task.impl;
-
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableList;
-
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures;
-import androidx.appactions.interaction.capabilities.core.impl.converters.DisambigEntityConverter;
-import androidx.appactions.interaction.capabilities.core.impl.converters.SearchActionConverter;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.capabilities.core.task.EntitySearchResult;
-import androidx.appactions.interaction.capabilities.core.task.ValidationResult;
-import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.InvalidResolverException;
-import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingEntityConverterException;
-import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingSearchActionConverterException;
-import androidx.appactions.interaction.capabilities.core.values.SearchAction;
-import androidx.appactions.interaction.proto.CurrentValue;
-import androidx.appactions.interaction.proto.CurrentValue.Status;
-import androidx.appactions.interaction.proto.DisambiguationData;
-import androidx.appactions.interaction.proto.Entity;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Contains static utility methods that handles processing argument slots for TaskCapabilityImpl.
- */
-final class TaskSlotProcessor {
-
-    private TaskSlotProcessor() {}
-
-    /** perform an in-app search for an ungrounded ParamValue */
-    private static <T> ListenableFuture<AppGroundingResult> ground(
-            ParamValue ungroundedParamValue, TaskParamBinding<T> binding, Executor executor) {
-        GenericResolverInternal<T> fieldResolver = binding.getResolver();
-        if (binding.getEntityConverter() == null) {
-            return Futures.immediateFailedFuture(
-                    new MissingEntityConverterException(
-                            "No entity converter found in the binding."));
-        }
-        if (binding.getSearchActionConverter() == null) {
-            return Futures.immediateFailedFuture(
-                    new MissingSearchActionConverterException(
-                            "No search action converter found in the binding."));
-        }
-        DisambigEntityConverter<T> entityConverter = binding.getEntityConverter();
-        SearchActionConverter<T> searchActionConverter = binding.getSearchActionConverter();
-        try {
-            SearchAction<T> searchAction =
-                    searchActionConverter.toSearchAction(ungroundedParamValue);
-            // Note, transformAsync is needed to catch checked exceptions. See
-            // https://yaqs.corp.google.com/eng/q/2565415714299052032.
-            return Futures.transformAsync(
-                    fieldResolver.invokeLookup(searchAction),
-                    (entitySearchResult) -> {
-                        try {
-                            return Futures.immediateFuture(
-                                    processEntitySearchResult(
-                                            entitySearchResult,
-                                            entityConverter,
-                                            ungroundedParamValue));
-                        } catch (StructConversionException e) {
-                            return Futures.immediateFailedFuture(e);
-                        }
-                    },
-                    executor,
-                    "processEntitySearchResult");
-        } catch (InvalidResolverException | StructConversionException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-    }
-
-    /**
-     * Applies "wildcard capture" technique. For more details see
-     * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
-     */
-    private static <T> ListenableFuture<ValidationResult> invokeValueChange(
-            List<ParamValue> updatedValue, TaskParamBinding<T> binding) {
-        try {
-            return binding.getResolver().notifyValueChange(updatedValue, binding.getConverter());
-        } catch (StructConversionException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-    }
-
-    /**
-     * Processes all ParamValue for a single slot.
-     *
-     * @return a {@code ListenableFuture<SlotProcessingResult>} object.
-     */
-    static ListenableFuture<SlotProcessingResult> processSlot(
-            String name,
-            List<CurrentValue> pendingArgs,
-            Map<String, TaskParamBinding<?>> taskParamMap,
-            Executor executor) {
-        TaskParamBinding<?> taskParamBinding = taskParamMap.get(name);
-        if (taskParamBinding == null) {
-            // TODO(b/234655571) use slot metadata to ensure that we never auto accept values for
-            // reference slots.
-            return Futures.immediateFuture(
-                    new SlotProcessingResult(
-                            Boolean.TRUE,
-                            pendingArgs.stream()
-                                    .map(
-                                            pendingArg ->
-                                                    TaskCapabilityUtils.toCurrentValue(
-                                                            pendingArg.getValue(), Status.ACCEPTED))
-                                    .collect(toImmutableList())));
-        }
-        List<ParamValue> groundedValues = Collections.synchronizedList(new ArrayList<>());
-        List<CurrentValue> ungroundedValues = Collections.synchronizedList(new ArrayList<>());
-
-        ListenableFuture<AppGroundingResult> groundingFuture =
-                Futures.immediateFuture(
-                        AppGroundingResult.ofSuccess(ParamValue.getDefaultInstance()));
-
-        for (CurrentValue pendingValue : pendingArgs) {
-            if (pendingValue.hasDisambiguationData()) {
-                // assistant-driven disambiguation
-                groundingFuture =
-                        consumeGroundingResult(
-                                chainAssistantGrounding(
-                                        groundingFuture, pendingValue, taskParamBinding, executor),
-                                groundedValues,
-                                ungroundedValues,
-                                executor);
-            } else if (taskParamBinding.getGroundingPredicate().invoke(pendingValue.getValue())) {
-                // app-driven disambiguation
-                groundingFuture =
-                        consumeGroundingResult(
-                                chainAppGrounding(
-                                        groundingFuture, pendingValue, taskParamBinding, executor),
-                                groundedValues,
-                                ungroundedValues,
-                                executor);
-            } else {
-                groundedValues.add(pendingValue.getValue());
-            }
-        }
-        return Futures.transformAsync(
-                groundingFuture,
-                (unused) -> {
-                    if (groundedValues.isEmpty()) {
-                        return Futures.immediateFuture(
-                                new SlotProcessingResult(
-                                        /* isSuccessful= */
-                                        false, Collections.unmodifiableList(ungroundedValues)));
-                    }
-                    return Futures.transform(
-                            invokeValueChange(groundedValues, taskParamBinding),
-                            validationResult ->
-                                    processValidationResult(
-                                            validationResult, groundedValues, ungroundedValues),
-                            executor,
-                            "validation");
-                },
-                executor,
-                "slot processing result");
-    }
-
-    /**
-     * Consumes the result of grounding.
-     *
-     * <p>If grounding was successful (app-driven with 1 returned result) the grounded ParamValue is
-     * added to groundedValues.
-     *
-     * <p>otherwise the ungrounded CurrentValue is added to ungroundedValues.
-     */
-    static ListenableFuture<AppGroundingResult> consumeGroundingResult(
-            ListenableFuture<AppGroundingResult> resultFuture,
-            List<ParamValue> groundedValues,
-            List<CurrentValue> ungroundedValues,
-            Executor executor) {
-        return Futures.transform(
-                resultFuture,
-                appGroundingResult -> {
-                    switch (appGroundingResult.getKind()) {
-                        case SUCCESS:
-                            groundedValues.add(appGroundingResult.success());
-                            break;
-                        case FAILURE:
-                            ungroundedValues.add(appGroundingResult.failure());
-                    }
-                    return appGroundingResult;
-                },
-                executor,
-                "consume grounding result");
-    }
-
-    /** enqueues processing of a pending value that requires assistant-driven grounding. */
-    static ListenableFuture<AppGroundingResult> chainAssistantGrounding(
-            ListenableFuture<AppGroundingResult> groundingFuture,
-            CurrentValue pendingValue,
-            TaskParamBinding<?> taskParamBinding,
-            Executor executor) {
-        return Futures.transformAsync(
-                groundingFuture,
-                previousResult -> {
-                    switch (previousResult.getKind()) {
-                        case SUCCESS:
-                            return Futures.transform(
-                                    renderAssistantDisambigData(
-                                            pendingValue.getDisambiguationData(), taskParamBinding),
-                                    unused ->
-                                            AppGroundingResult.ofFailure(
-                                                    CurrentValue.newBuilder(pendingValue)
-                                                            .setStatus(Status.DISAMBIG)
-                                                            .build()),
-                                    executor,
-                                    "renderAssistantDisambigData");
-                        case FAILURE:
-                            return Futures.immediateFuture(
-                                    AppGroundingResult.ofFailure(pendingValue));
-                    }
-                    throw new IllegalStateException("unreachable");
-                },
-                executor,
-                "assistant grounding");
-    }
-
-    /** enqueues processing of a pending value that requires app-driven grounding. */
-    static ListenableFuture<AppGroundingResult> chainAppGrounding(
-            ListenableFuture<AppGroundingResult> groundingFuture,
-            CurrentValue pendingValue,
-            TaskParamBinding<?> taskParamBinding,
-            Executor executor) {
-        return Futures.transformAsync(
-                groundingFuture,
-                previousResult -> {
-                    switch (previousResult.getKind()) {
-                        case SUCCESS:
-                            return ground(pendingValue.getValue(), taskParamBinding, executor);
-                        case FAILURE:
-                            return Futures.immediateFuture(
-                                    AppGroundingResult.ofFailure(pendingValue));
-                    }
-                    throw new IllegalStateException("unreachable");
-                },
-                executor,
-                "app grounding");
-    }
-
-    /**
-     * Processes the EntitySearchResult from performing an entity search.
-     *
-     * @param entitySearchResult the EntitySearchResult returned from the app resolver.
-     * @param ungroundedValue the original ungrounded ParamValue.
-     */
-    private static <T> AppGroundingResult processEntitySearchResult(
-            EntitySearchResult<T> entitySearchResult,
-            DisambigEntityConverter<T> entityConverter,
-            ParamValue ungroundedValue)
-            throws StructConversionException {
-        switch (entitySearchResult.getPossibleValues().size()) {
-            case 0:
-                return AppGroundingResult.ofFailure(
-                        TaskCapabilityUtils.toCurrentValue(ungroundedValue, Status.REJECTED));
-            case 1:
-                Entity groundedEntity =
-                        entityConverter.convert(
-                                Objects.requireNonNull(
-                                        entitySearchResult.getPossibleValues().get(0)));
-                return AppGroundingResult.ofSuccess(
-                        TaskCapabilityUtils.groundedValueToParamValue(groundedEntity));
-            default:
-                List<Entity> disambigEntities =
-                        getDisambigEntities(
-                                entitySearchResult.getPossibleValues(), entityConverter);
-                return AppGroundingResult.ofFailure(
-                        TaskCapabilityUtils.getCurrentValueForDisambiguation(
-                                ungroundedValue, disambigEntities));
-        }
-    }
-
-    private static <T> List<Entity> getDisambigEntities(
-            List<T> possibleValues, DisambigEntityConverter<T> entityConverter)
-            throws StructConversionException {
-        List<Entity> disambigEntities = new ArrayList<>();
-        for (T entity : possibleValues) {
-            disambigEntities.add(entityConverter.convert(Objects.requireNonNull(entity)));
-        }
-        return Collections.unmodifiableList(disambigEntities);
-    }
-
-    /**
-     * Processes the ValidationResult from sending argument updates to onReceived.
-     *
-     * @param validationResult the ValidationResult returned from value listener.
-     * @param groundedValues a List of all grounded ParamValue.
-     * @param ungroundedValues a List of all ungrounded CurrentValue.
-     */
-    private static SlotProcessingResult processValidationResult(
-            ValidationResult validationResult,
-            List<ParamValue> groundedValues,
-            List<CurrentValue> ungroundedValues) {
-        List<CurrentValue> combinedValues = new ArrayList<>();
-        switch (validationResult.getKind()) {
-            case ACCEPTED:
-                combinedValues.addAll(
-                        TaskCapabilityUtils.paramValuesToCurrentValue(
-                                groundedValues, Status.ACCEPTED));
-                break;
-            case REJECTED:
-                combinedValues.addAll(
-                        TaskCapabilityUtils.paramValuesToCurrentValue(
-                                groundedValues, Status.REJECTED));
-                break;
-        }
-        combinedValues.addAll(ungroundedValues);
-        return new SlotProcessingResult(
-                /* isSuccessful= */ ungroundedValues.isEmpty()
-                        && (validationResult.getKind() == ValidationResult.Kind.ACCEPTED),
-                Collections.unmodifiableList(combinedValues));
-    }
-
-    private static ListenableFuture<Void> renderAssistantDisambigData(
-            DisambiguationData disambiguationData, TaskParamBinding<?> binding) {
-        List<String> entityIds =
-                disambiguationData.getEntitiesList().stream()
-                        .map(Entity::getIdentifier)
-                        .collect(toImmutableList());
-        try {
-            return binding.getResolver().invokeEntityRender(entityIds);
-        } catch (InvalidResolverException e) {
-            return Futures.immediateFailedFuture(e);
-        }
-    }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.kt
new file mode 100644
index 0000000..fc41c53
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessor.kt
@@ -0,0 +1,286 @@
+/*
+ * 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.appactions.interaction.capabilities.core.task.impl
+
+import androidx.appactions.interaction.capabilities.core.impl.converters.DisambigEntityConverter
+import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
+import androidx.appactions.interaction.capabilities.core.task.EntitySearchResult
+import androidx.appactions.interaction.capabilities.core.task.ValidationResult
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.InvalidResolverException
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingEntityConverterException
+import androidx.appactions.interaction.capabilities.core.task.impl.exceptions.MissingSearchActionConverterException
+import androidx.appactions.interaction.proto.CurrentValue
+import androidx.appactions.interaction.proto.DisambiguationData
+import androidx.appactions.interaction.proto.ParamValue
+import androidx.concurrent.futures.await
+import kotlin.IllegalStateException
+import kotlin.String
+import kotlin.Throws
+
+/**
+ * Contains static utility methods that handles processing argument slots for TaskCapabilityImpl.
+ */
+internal object TaskSlotProcessor {
+    /**
+     * Processes all ParamValue for a single slot.
+     *
+     * @return a [SlotProcessingResult] object.
+     */
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    suspend fun processSlot(
+        name: String,
+        pendingArgs: List<CurrentValue>,
+        taskParamMap: Map<String, TaskParamBinding<*>>,
+    ): SlotProcessingResult {
+        // TODO(b/234655571) use slot metadata to ensure that we never auto accept values
+        // for reference slots.
+        val taskParamBinding =
+            taskParamMap[name]
+                ?: return SlotProcessingResult(
+                    true,
+                    pendingArgs.map {
+                        TaskCapabilityUtils.toCurrentValue(it.value, CurrentValue.Status.ACCEPTED)
+                    }
+                )
+        val groundedValues = mutableListOf<ParamValue>()
+        val ungroundedValues = mutableListOf<CurrentValue>()
+        var groundingResult = AppGroundingResult.ofSuccess(ParamValue.getDefaultInstance())
+        for (pendingValue in pendingArgs) {
+            if (pendingValue.hasDisambiguationData()) {
+                // assistant-driven disambiguation
+                groundingResult =
+                    consumeGroundingResult(
+                        chainAssistantGrounding(groundingResult, pendingValue, taskParamBinding),
+                        groundedValues,
+                        ungroundedValues
+                    )
+            } else if (taskParamBinding.groundingPredicate.invoke(pendingValue.value)) {
+                // app-driven disambiguation
+                groundingResult =
+                    consumeGroundingResult(
+                        chainAppGrounding(groundingResult, pendingValue, taskParamBinding),
+                        groundedValues,
+                        ungroundedValues
+                    )
+            } else {
+                groundedValues.add(pendingValue.value)
+            }
+        }
+        return if (groundedValues.isEmpty()) {
+            SlotProcessingResult(
+                /* isSuccessful= */ false,
+                ungroundedValues.toList(),
+            )
+        } else {
+            processValidationResult(
+                invokeValueChange(groundedValues, taskParamBinding),
+                groundedValues,
+                ungroundedValues
+            )
+        }
+    }
+
+    /** enqueues processing of a pending value that requires assistant-driven grounding. */
+    @Throws(InvalidResolverException::class)
+    private suspend fun chainAssistantGrounding(
+        groundingResult: AppGroundingResult,
+        pendingValue: CurrentValue,
+        taskParamBinding: TaskParamBinding<*>
+    ) =
+        when (groundingResult.kind) {
+            AppGroundingResult.Kind.SUCCESS -> {
+                renderAssistantDisambigData(pendingValue.disambiguationData, taskParamBinding)
+                AppGroundingResult.ofFailure(
+                    CurrentValue.newBuilder(pendingValue)
+                        .setStatus(CurrentValue.Status.DISAMBIG)
+                        .build()
+                )
+            }
+            AppGroundingResult.Kind.FAILURE -> AppGroundingResult.ofFailure(pendingValue)
+            else -> throw IllegalStateException("unreachable")
+        }
+
+    /** enqueues processing of a pending value that requires app-driven grounding. */
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    private suspend fun chainAppGrounding(
+        groundingResult: AppGroundingResult,
+        pendingValue: CurrentValue,
+        taskParamBinding: TaskParamBinding<*>,
+    ) =
+        when (groundingResult.kind) {
+            AppGroundingResult.Kind.SUCCESS -> ground(pendingValue.value, taskParamBinding)
+            AppGroundingResult.Kind.FAILURE -> AppGroundingResult.ofFailure(pendingValue)
+            else -> throw IllegalStateException("unreachable")
+        }
+
+    /**
+     * Consumes the result of grounding.
+     *
+     * If grounding was successful (app-driven with 1 returned result) the grounded ParamValue is
+     * added to groundedValues.
+     *
+     * otherwise the ungrounded CurrentValue is added to ungroundedValues.
+     */
+    private fun consumeGroundingResult(
+        groundingResult: AppGroundingResult,
+        groundedValues: MutableList<ParamValue>,
+        ungroundedValues: MutableList<CurrentValue>,
+    ): AppGroundingResult {
+        when (groundingResult.kind) {
+            AppGroundingResult.Kind.SUCCESS -> groundedValues.add(groundingResult.success())
+            AppGroundingResult.Kind.FAILURE -> ungroundedValues.add(groundingResult.failure())
+            else -> throw IllegalStateException("unreachable")
+        }
+        return groundingResult
+    }
+
+    /**
+     * Applies "wildcard capture" technique. For more details see
+     * [...](https://docs.oracle.com/javase/tutorial/java/generics/capture.html)
+     */
+    @Throws(StructConversionException::class)
+    private suspend fun <T> invokeValueChange(
+        updatedValue: List<ParamValue>,
+        binding: TaskParamBinding<T>
+    ): ValidationResult {
+        return binding.resolver.notifyValueChange(updatedValue, binding.converter).await()
+    }
+
+    @Throws(InvalidResolverException::class)
+    private suspend fun renderAssistantDisambigData(
+        disambiguationData: DisambiguationData,
+        binding: TaskParamBinding<*>
+    ) {
+        val entityIds = disambiguationData.entitiesList.map { it.identifier }
+        binding.resolver.invokeEntityRender(entityIds).await()
+    }
+
+    /**
+     * Processes the ValidationResult from sending argument updates to onReceived.
+     *
+     * @param validationResult the ValidationResult returned from value listener.
+     * @param groundedValues a List of all grounded ParamValue.
+     * @param ungroundedValues a List of all ungrounded CurrentValue.
+     */
+    private fun processValidationResult(
+        validationResult: ValidationResult,
+        groundedValues: List<ParamValue>,
+        ungroundedValues: List<CurrentValue>
+    ): SlotProcessingResult {
+        val combinedValues = mutableListOf<CurrentValue>()
+        when (validationResult.kind) {
+            ValidationResult.Kind.ACCEPTED ->
+                combinedValues.addAll(
+                    TaskCapabilityUtils.paramValuesToCurrentValue(
+                        groundedValues,
+                        CurrentValue.Status.ACCEPTED
+                    )
+                )
+            ValidationResult.Kind.REJECTED ->
+                combinedValues.addAll(
+                    TaskCapabilityUtils.paramValuesToCurrentValue(
+                        groundedValues,
+                        CurrentValue.Status.REJECTED
+                    )
+                )
+        }
+        combinedValues.addAll(ungroundedValues)
+        return SlotProcessingResult(
+            /* isSuccessful= */ ungroundedValues.isEmpty() &&
+                validationResult.kind === ValidationResult.Kind.ACCEPTED,
+            combinedValues.toList()
+        )
+    }
+
+    /** perform an in-app search for an ungrounded ParamValue */
+    @Throws(
+        MissingEntityConverterException::class,
+        MissingSearchActionConverterException::class,
+        StructConversionException::class,
+        InvalidResolverException::class,
+    )
+    private suspend fun <T> ground(
+        ungroundedParamValue: ParamValue,
+        binding: TaskParamBinding<T>,
+    ): AppGroundingResult {
+        if (binding.entityConverter == null) {
+            throw MissingEntityConverterException("No entity converter found in the binding.")
+        }
+        if (binding.searchActionConverter == null) {
+            throw MissingSearchActionConverterException(
+                "No search action converter found in the binding."
+            )
+        }
+        val entityConverter = binding.entityConverter
+        val searchActionConverter = binding.searchActionConverter
+        val searchAction = searchActionConverter.toSearchAction(ungroundedParamValue)
+        val entitySearchResult = binding.resolver.invokeLookup(searchAction).await()
+        return processEntitySearchResult<T>(
+            entitySearchResult,
+            entityConverter,
+            ungroundedParamValue
+        )
+    }
+
+    /**
+     * Processes the EntitySearchResult from performing an entity search.
+     *
+     * @param entitySearchResult the EntitySearchResult returned from the app resolver.
+     * @param ungroundedValue the original ungrounded ParamValue.
+     */
+    @Throws(StructConversionException::class)
+    private fun <T> processEntitySearchResult(
+        entitySearchResult: EntitySearchResult<T>,
+        entityConverter: DisambigEntityConverter<T>,
+        ungroundedValue: ParamValue
+    ): AppGroundingResult {
+        return when (entitySearchResult.possibleValues.size) {
+            0 ->
+                AppGroundingResult.ofFailure(
+                    TaskCapabilityUtils.toCurrentValue(
+                        ungroundedValue,
+                        CurrentValue.Status.REJECTED
+                    )
+                )
+            1 -> {
+                val groundedEntity = entityConverter.convert(entitySearchResult.possibleValues[0]!!)
+                AppGroundingResult.ofSuccess(
+                    TaskCapabilityUtils.groundedValueToParamValue(groundedEntity)
+                )
+            }
+            else -> {
+                val disambigEntities =
+                    entitySearchResult.possibleValues.map { entityConverter.convert(it) }
+                AppGroundingResult.ofFailure(
+                    TaskCapabilityUtils.getCurrentValueForDisambiguation(
+                        ungroundedValue,
+                        disambigEntities
+                    )
+                )
+            }
+        }
+    }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TouchEventUpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TouchEventUpdateRequest.kt
index 0cbee46..46731ea 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TouchEventUpdateRequest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/TouchEventUpdateRequest.kt
@@ -13,33 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package androidx.appactions.interaction.capabilities.core.task.impl
 
-import androidx.annotation.RestrictTo
 import androidx.appactions.interaction.proto.ParamValue
 
-/**
- * Represents a fulfillment request coming from user tap.
- *
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-data class TouchEventUpdateRequest(val paramValuesMap: Map<String, List<ParamValue>>) {
-
-    companion object {
-        /**
-         * merge two TouchEventUpdateRequest instances. Map entries in newRequest will take priority
-         * in case of conflict.
-         */
-        @JvmStatic
-        fun merge(
-            oldRequest: TouchEventUpdateRequest,
-            newRequest: TouchEventUpdateRequest,
-        ): TouchEventUpdateRequest {
-            val mergedParamValuesMap = oldRequest.paramValuesMap.toMutableMap()
-            mergedParamValuesMap.putAll(newRequest.paramValuesMap)
-            return TouchEventUpdateRequest(mergedParamValuesMap.toMap())
-        }
+/** Represents a fulfillment request coming from user tap. */
+internal data class TouchEventUpdateRequest(val paramValuesMap: Map<String, List<ParamValue>>) {
+    /**
+     * merge two TouchEventUpdateRequest instances. Map entries in newRequest will take priority in
+     * case of conflict.
+     */
+    fun mergeWith(newRequest: TouchEventUpdateRequest): TouchEventUpdateRequest {
+        val mergedParamValuesMap = this.paramValuesMap.toMutableMap()
+        mergedParamValuesMap.putAll(newRequest.paramValuesMap)
+        return TouchEventUpdateRequest(mergedParamValuesMap.toMap())
     }
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/UpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/UpdateRequest.kt
index 60c3816..e189b7b 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/UpdateRequest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/impl/UpdateRequest.kt
@@ -15,15 +15,8 @@
  */
 package androidx.appactions.interaction.capabilities.core.task.impl
 
-import androidx.annotation.RestrictTo
-
-/**
- * Contains either an AssistantUpdateRequest or a TouchEventUpdateRequest
- *
- * @hide
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-class UpdateRequest
+/** Contains either an [AssistantUpdateRequest] or a [TouchEventUpdateRequest] */
+internal class UpdateRequest
 private constructor(
     val assistantRequest: AssistantUpdateRequest?,
     val touchEventRequest: TouchEventUpdateRequest?,
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/package-info.java
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/package-info.java
index 8f2bd49..838a123 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/task/package-info.java
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package androidx.appactions.interaction.capabilities.core.task;
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+import androidx.annotation.RestrictTo;
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/values/package-info.java
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/values/package-info.java
index 8f2bd49..dcdff02 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/values/package-info.java
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+/** @hide */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package androidx.appactions.interaction.capabilities.core.values;
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
index a5fcd1f..ee5ca8b 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
@@ -17,7 +17,6 @@
 package androidx.appactions.interaction.capabilities.core.impl
 
 import android.util.SizeF
-import androidx.appactions.interaction.capabilities.core.ActionCapability
 import androidx.appactions.interaction.capabilities.core.ActionExecutor
 import androidx.appactions.interaction.capabilities.core.ActionExecutorAsync
 import androidx.appactions.interaction.capabilities.core.ActionExecutorAsync.Companion.toActionExecutorAsync
@@ -30,6 +29,8 @@
 import androidx.appactions.interaction.capabilities.core.properties.EntityProperty
 import androidx.appactions.interaction.capabilities.core.properties.StringProperty
 import androidx.appactions.interaction.capabilities.core.testing.ArgumentUtils
+import androidx.appactions.interaction.capabilities.core.testing.FakeCallbackInternal
+import androidx.appactions.interaction.capabilities.core.testing.TestingUtils.CB_TIMEOUT
 import androidx.appactions.interaction.capabilities.core.testing.spec.Argument
 import androidx.appactions.interaction.capabilities.core.testing.spec.Output
 import androidx.appactions.interaction.capabilities.core.testing.spec.Property
@@ -38,84 +39,126 @@
 import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
 import androidx.appactions.interaction.proto.ParamValue
 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
-import org.mockito.Mockito.verify
-import org.mockito.kotlin.mock
 
 @RunWith(JUnit4::class)
 class SingleTurnCapabilityTest {
-    val hostProperties = HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-    val mockCalback: CallbackInternal = mock()
+    private val hostProperties =
+        HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
 
-    @Ignore // b/271033076
     @Test
     fun oneShotCapability_successWithOutput() {
-        val actionExecutor = object : ActionExecutor<Argument, Output> {
-            override suspend fun execute(argument: Argument): ExecutionResult<Output> =
-                ExecutionResult.Builder<Output>().setOutput(
-                    Output.builder().setOptionalStringField("stringOutput")
+        val actionExecutor =
+            ActionExecutor<Argument, Output> {
+                ExecutionResult.Builder<Output>()
+                    .setOutput(
+                        Output.builder().setOptionalStringField("stringOutput").build(),
+                    )
+                    .build()
+            }
+        val capability =
+            SingleTurnCapabilityImpl(
+                id = "capabilityId",
+                actionSpec = ACTION_SPEC,
+                property =
+                    Property.newBuilder()
+                        .setRequiredEntityField(
+                            EntityProperty.Builder().build(),
+                        )
+                        .setOptionalStringField(
+                            StringProperty.Builder().setProhibited(true).build(),
+                        )
                         .build(),
-                ).build()
-        }
-        val capability: ActionCapability =
-            SingleTurnCapabilityImpl<Property, Argument, Output>(
-                "capabilityId",
-                ACTION_SPEC,
-                Property.newBuilder().setRequiredEntityField(
-                    EntityProperty.Builder().build(),
-                ).setOptionalStringField(
-                    StringProperty.Builder().setProhibited(true).build(),
-                ).build(),
-                actionExecutor.toActionExecutorAsync(),
+                actionExecutorAsync = actionExecutor.toActionExecutorAsync(),
             )
-        val expectedFulfillmentResponse: FulfillmentResponse =
-            FulfillmentResponse.newBuilder().setExecutionOutput(
-                StructuredOutput.newBuilder()
-                    .addOutputValues(
-                        OutputValue.newBuilder()
-                            .setName("optionalStringOutput")
-                            .addValues(
-                                ParamValue.newBuilder()
-                                    .setStringValue("stringOutput")
+
+        val capabilitySession = capability.createSession(hostProperties)
+        val callbackInternal = FakeCallbackInternal(CB_TIMEOUT)
+        capabilitySession.execute(
+            ArgumentUtils.buildArgs(
+                mapOf(
+                    "optionalString" to
+                        ParamValue.newBuilder().setIdentifier("string argument value").build(),
+                ),
+            ),
+            callbackInternal,
+        )
+
+        val response = callbackInternal.receiveResponse()
+        assertThat(response.fulfillmentResponse).isNotNull()
+        assertThat(response.fulfillmentResponse)
+            .isEqualTo(
+                FulfillmentResponse.newBuilder()
+                    .setExecutionOutput(
+                        StructuredOutput.newBuilder()
+                            .addOutputValues(
+                                OutputValue.newBuilder()
+                                    .setName("optionalStringOutput")
+                                    .addValues(
+                                        ParamValue.newBuilder()
+                                            .setStringValue("stringOutput")
+                                            .build(),
+                                    )
                                     .build(),
                             )
                             .build(),
                     )
-                    .build(),
-            ).build()
+                    .build()
+            )
+    }
+    @Test
+    fun oneShotCapability_failure() {
+        val actionExecutor = ActionExecutor<Argument, Output> { throw IllegalStateException("") }
+        val capability =
+            SingleTurnCapabilityImpl(
+                id = "capabilityId",
+                actionSpec = ACTION_SPEC,
+                property =
+                    Property.newBuilder()
+                        .setRequiredEntityField(
+                            EntityProperty.Builder().build(),
+                        )
+                        .setOptionalStringField(
+                            StringProperty.Builder().setProhibited(true).build(),
+                        )
+                        .build(),
+                actionExecutorAsync = actionExecutor.toActionExecutorAsync(),
+            )
 
         val capabilitySession = capability.createSession(hostProperties)
+        val callbackInternal = FakeCallbackInternal(CB_TIMEOUT)
         capabilitySession.execute(
             ArgumentUtils.buildArgs(
                 mapOf(
-                    "optionalString" to ParamValue.newBuilder().setIdentifier(
-                        "string argument value",
-                    ).build(),
+                    "optionalString" to
+                        ParamValue.newBuilder().setIdentifier("string argument value").build(),
                 ),
             ),
-            mockCalback,
+            callbackInternal,
         )
 
-        verify(mockCalback).onSuccess(expectedFulfillmentResponse)
+        val response = callbackInternal.receiveResponse()
+        assertThat(response.errorStatus).isNotNull()
+        assertThat(response.errorStatus).isEqualTo(ErrorStatusInternal.CANCELLED)
     }
 
     @Test
     fun oneShotSession_uiHandle_withActionExecutor() {
         val actionExecutor =
-            ActionExecutor<Argument, Output> {
-                ExecutionResult.getDefaultInstance()
-            }
-        val capability: ActionCapability =
-            SingleTurnCapabilityImpl<Property, Argument, Output>(
-                "capabilityId",
-                ACTION_SPEC,
-                Property.newBuilder().setRequiredEntityField(
-                    EntityProperty.Builder().build(),
-                ).build(),
-                actionExecutor.toActionExecutorAsync(),
+            ActionExecutor<Argument, Output> { ExecutionResult.getDefaultInstance() }
+        val capability =
+            SingleTurnCapabilityImpl(
+                id = "capabilityId",
+                actionSpec = ACTION_SPEC,
+                property =
+                    Property.newBuilder()
+                        .setRequiredEntityField(
+                            EntityProperty.Builder().build(),
+                        )
+                        .build(),
+                actionExecutorAsync = actionExecutor.toActionExecutorAsync(),
             )
         val session = capability.createSession(hostProperties)
         assertThat(session.uiHandle).isSameInstanceAs(actionExecutor)
@@ -123,17 +166,21 @@
 
     @Test
     fun oneShotSession_uiHandle_withActionExecutorAsync() {
-        val actionExecutorAsync = ActionExecutorAsync<Argument, Output> {
-            Futures.immediateFuture(ExecutionResult.getDefaultInstance())
-        }
-        val capability: ActionCapability =
-            SingleTurnCapabilityImpl<Property, Argument, Output>(
-                "capabilityId",
-                ACTION_SPEC,
-                Property.newBuilder().setRequiredEntityField(
-                    EntityProperty.Builder().build(),
-                ).build(),
-                actionExecutorAsync,
+        val actionExecutorAsync =
+            ActionExecutorAsync<Argument, Output> {
+                Futures.immediateFuture(ExecutionResult.getDefaultInstance())
+            }
+        val capability =
+            SingleTurnCapabilityImpl(
+                id = "capabilityId",
+                actionSpec = ACTION_SPEC,
+                property =
+                    Property.newBuilder()
+                        .setRequiredEntityField(
+                            EntityProperty.Builder().build(),
+                        )
+                        .build(),
+                actionExecutorAsync = actionExecutorAsync,
             )
         val session = capability.createSession(hostProperties)
         assertThat(session.uiHandle).isSameInstanceAs(actionExecutorAsync)
@@ -142,8 +189,8 @@
     companion object {
         val ACTION_SPEC: ActionSpec<Property, Argument, Output> =
             ActionSpecBuilder.ofCapabilityNamed(
-                "actions.intent.TEST",
-            )
+                    "actions.intent.TEST",
+                )
                 .setDescriptor(Property::class.java)
                 .setArgument(Argument::class.java, Argument::newBuilder)
                 .setOutput(Output::class.java)
@@ -156,6 +203,7 @@
                     "optionalStringOutput",
                     Output::optionalStringField,
                     TypeConverters::toParamValue,
-                ).build()
+                )
+                .build()
     }
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ListenableFutureHelperTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ListenableFutureHelperTest.kt
index dc09ae2..df2f2ac 100644
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ListenableFutureHelperTest.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ListenableFutureHelperTest.kt
@@ -39,7 +39,6 @@
         assertThat(stringFuture.get()).isEqualTo("hello")
     }
 
-    @Ignore // b/272659961
     @Test
     fun suspendToListenableFuture_pollingTest() {
         val stringChannel = Channel<String>(1)
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.java
deleted file mode 100644
index bf93a0d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.java
+++ /dev/null
@@ -1,105 +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.appactions.interaction.capabilities.core.task.impl;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.appactions.interaction.capabilities.core.impl.converters.PropertyConverter;
-import androidx.appactions.interaction.capabilities.core.properties.StringProperty;
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter;
-import androidx.appactions.interaction.proto.CurrentValue;
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@RunWith(JUnit4.class)
-public final class TaskCapabilityUtilsTest {
-
-    @Test
-    public void isSlotFillingComplete_allRequiredParamsFilled_returnsTrue() {
-        Map<String, List<ParamValue>> args = new HashMap<>();
-        args.put(
-                "required",
-                Collections.singletonList(
-                        ParamValue.newBuilder().setStringValue("Donald").build()));
-        List<IntentParameter> intentParameters = new ArrayList<>();
-        intentParameters.add(
-                PropertyConverter.getIntentParameter(
-                        "required", new StringProperty.Builder().setRequired(true).build()));
-
-        assertThat(TaskCapabilityUtils.isSlotFillingComplete(args, intentParameters)).isTrue();
-    }
-
-    @Test
-    public void isSlotFillingComplete_notAllRequiredParamsFilled_returnsFalse() {
-        List<IntentParameter> intentParameters = new ArrayList<>();
-        intentParameters.add(
-                PropertyConverter.getIntentParameter(
-                        "required", new StringProperty.Builder().setRequired(true).build()));
-
-        assertThat(
-                TaskCapabilityUtils.isSlotFillingComplete(Collections.emptyMap(), intentParameters))
-                .isFalse();
-    }
-
-    @Test
-    public void canSkipSlotProcessing_true() {
-        List<CurrentValue> currentValues =
-                Collections.singletonList(
-                        CurrentValue.newBuilder()
-                                .setValue(ParamValue.newBuilder().setBoolValue(true).build())
-                                .setStatus(CurrentValue.Status.ACCEPTED)
-                                .build());
-        List<FulfillmentValue> fulfillmentValues =
-                Collections.singletonList(
-                        FulfillmentValue.newBuilder()
-                                .setValue(ParamValue.newBuilder().setBoolValue(true).build())
-                                .build());
-        assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
-                .isTrue();
-    }
-
-    @Test
-    public void canSkipSlotProcessing_false_sizeDifference() {
-        List<CurrentValue> currentValues =
-                Collections.singletonList(
-                        CurrentValue.newBuilder()
-                                .setValue(ParamValue.newBuilder().setStringValue("a").build())
-                                .setStatus(CurrentValue.Status.ACCEPTED)
-                                .build());
-        List<FulfillmentValue> fulfillmentValues = new ArrayList<>();
-        fulfillmentValues.add(
-                FulfillmentValue.newBuilder()
-                        .setValue(ParamValue.newBuilder().setStringValue("a").build())
-                        .build());
-        fulfillmentValues.add(
-                FulfillmentValue.newBuilder()
-                        .setValue(ParamValue.newBuilder().setStringValue("b").build())
-                        .build());
-        assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
-                .isFalse();
-    }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.kt
new file mode 100644
index 0000000..54f25db
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskCapabilityUtilsTest.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.appactions.interaction.capabilities.core.task.impl
+
+import androidx.appactions.interaction.capabilities.core.impl.converters.PropertyConverter
+import androidx.appactions.interaction.capabilities.core.properties.StringProperty
+import androidx.appactions.interaction.proto.AppActionsContext
+import androidx.appactions.interaction.proto.CurrentValue
+import androidx.appactions.interaction.proto.FulfillmentRequest
+import androidx.appactions.interaction.proto.ParamValue
+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 TaskCapabilityUtilsTest {
+    @Test
+    fun isSlotFillingComplete_allRequiredParamsFilled_returnsTrue() {
+        val args: MutableMap<String, List<ParamValue>> = HashMap()
+        args["required"] = listOf(ParamValue.newBuilder().setStringValue("Donald").build())
+        val intentParameters: MutableList<AppActionsContext.IntentParameter> = ArrayList()
+        intentParameters.add(
+            PropertyConverter.getIntentParameter(
+                "required",
+                StringProperty.Builder().setRequired(true).build()
+            )
+        )
+        assertThat(TaskCapabilityUtils.isSlotFillingComplete(args, intentParameters)).isTrue()
+    }
+
+    @Test
+    fun isSlotFillingComplete_notAllRequiredParamsFilled_returnsFalse() {
+        val intentParameters: MutableList<AppActionsContext.IntentParameter> = ArrayList()
+        intentParameters.add(
+            PropertyConverter.getIntentParameter(
+                "required",
+                StringProperty.Builder().setRequired(true).build()
+            )
+        )
+        assertThat(TaskCapabilityUtils.isSlotFillingComplete(emptyMap(), intentParameters))
+            .isFalse()
+    }
+
+    @Test
+    fun canSkipSlotProcessing_true() {
+        val currentValues =
+            listOf(
+                CurrentValue.newBuilder()
+                    .setValue(ParamValue.newBuilder().setBoolValue(true).build())
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .build()
+            )
+        val fulfillmentValues =
+            listOf(
+                FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
+                    .setValue(ParamValue.newBuilder().setBoolValue(true).build())
+                    .build()
+            )
+        assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
+            .isTrue()
+    }
+
+    @Test
+    fun canSkipSlotProcessing_false_sizeDifference() {
+        val currentValues =
+            listOf(
+                CurrentValue.newBuilder()
+                    .setValue(ParamValue.newBuilder().setStringValue("a").build())
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .build()
+            )
+        val fulfillmentValues: MutableList<FulfillmentRequest.Fulfillment.FulfillmentValue> =
+            ArrayList()
+        fulfillmentValues.add(
+            FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
+                .setValue(ParamValue.newBuilder().setStringValue("a").build())
+                .build()
+        )
+        fulfillmentValues.add(
+            FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
+                .setValue(ParamValue.newBuilder().setStringValue("b").build())
+                .build()
+        )
+        assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
+            .isFalse()
+    }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.java
deleted file mode 100644
index 4a000eb..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.java
+++ /dev/null
@@ -1,402 +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.appactions.interaction.capabilities.core.task.impl;
-
-import static androidx.appactions.interaction.capabilities.core.testing.ArgumentUtils.buildSearchActionParamValue;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures;
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters;
-import androidx.appactions.interaction.capabilities.core.task.AppEntityResolver;
-import androidx.appactions.interaction.capabilities.core.task.EntitySearchResult;
-import androidx.appactions.interaction.capabilities.core.task.InventoryResolver;
-import androidx.appactions.interaction.capabilities.core.task.ValidationResult;
-import androidx.appactions.interaction.capabilities.core.task.ValueListener;
-import androidx.appactions.interaction.capabilities.core.testing.spec.SettableFutureWrapper;
-import androidx.appactions.interaction.capabilities.core.values.SearchAction;
-import androidx.appactions.interaction.proto.CurrentValue;
-import androidx.appactions.interaction.proto.CurrentValue.Status;
-import androidx.appactions.interaction.proto.DisambiguationData;
-import androidx.appactions.interaction.proto.Entity;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-@RunWith(JUnit4.class)
-public final class TaskSlotProcessorTest {
-
-    private <T> GenericResolverInternal<T> createAssistantDisambigResolver(
-            ValidationResult validationResult,
-            Consumer<T> valueConsumer,
-            Consumer<List<String>> renderConsumer) {
-        return GenericResolverInternal.fromInventoryResolver(
-                new InventoryResolver<T>() {
-                    @NonNull
-                    @Override
-                    public ListenableFuture<ValidationResult> onReceivedAsync(T value) {
-                        valueConsumer.accept(value);
-                        return Futures.immediateFuture(validationResult);
-                    }
-
-                    @NonNull
-                    @Override
-                    public ListenableFuture<Void> renderChoices(@NonNull List<String> entityIDs) {
-                        renderConsumer.accept(entityIDs);
-                        return Futures.immediateVoidFuture();
-                    }
-                });
-    }
-
-    private <T> GenericResolverInternal<T> createValueResolver(
-            ValidationResult validationResult, Consumer<T> valueConsumer) {
-        return GenericResolverInternal.fromValueListener(
-                new ValueListener<T>() {
-                    @NonNull
-                    @Override
-                    public ListenableFuture<ValidationResult> onReceivedAsync(T value) {
-                        valueConsumer.accept(value);
-                        return Futures.immediateFuture(validationResult);
-                    }
-                });
-    }
-
-    private <T> GenericResolverInternal<T> createValueResolver(ValidationResult validationResult) {
-        return createValueResolver(validationResult, (unused) -> {});
-    }
-
-    private <T> GenericResolverInternal<T> createValueListResolver(
-            ValidationResult validationResult, Consumer<List<T>> valueConsumer) {
-        return GenericResolverInternal.fromValueListListener(
-                new ValueListener<List<T>>() {
-                    @NonNull
-                    @Override
-                    public ListenableFuture<ValidationResult> onReceivedAsync(List<T> value) {
-                        valueConsumer.accept(value);
-                        return Futures.immediateFuture(validationResult);
-                    }
-                });
-    }
-
-    private <T> GenericResolverInternal<T> createAppEntityResolver(
-            ValidationResult validationResult,
-            Consumer<T> valueConsumer,
-            EntitySearchResult<T> appSearchResult,
-            Consumer<SearchAction<T>> appSearchConsumer) {
-        return GenericResolverInternal.fromAppEntityResolver(
-                new AppEntityResolver<T>() {
-                    @NonNull
-                    @Override
-                    public ListenableFuture<ValidationResult> onReceivedAsync(T value) {
-                        valueConsumer.accept(value);
-                        return Futures.immediateFuture(validationResult);
-                    }
-
-                    @NonNull
-                    @Override
-                    public ListenableFuture<EntitySearchResult<T>> lookupAndRender(
-                            @NonNull SearchAction<T> searchAction) {
-                        appSearchConsumer.accept(searchAction);
-                        return Futures.immediateFuture(appSearchResult);
-                    }
-                });
-    }
-
-    @Test
-    public void processSlot_singleValue_accepted() throws Exception {
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "singularValue",
-                        (paramValue) -> false,
-                        createValueResolver(ValidationResult.newAccepted()),
-                        TypeConverters::toStringValue,
-                        null,
-                        null);
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("singularValue", binding);
-        List<ParamValue> args =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setIdentifier("testValue").build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot(
-                                "singularValue",
-                                TaskCapabilityUtils.paramValuesToCurrentValue(args, Status.PENDING),
-                                taskParamMap,
-                                Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isTrue();
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(0))
-                                .setStatus(Status.ACCEPTED)
-                                .build());
-    }
-
-    @Test
-    public void processSlot_singleValue_rejected() throws Exception {
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "singularValue",
-                        (paramValue) -> false,
-                        createValueResolver(ValidationResult.newRejected()),
-                        TypeConverters::toStringValue,
-                        null,
-                        null);
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("singularValue", binding);
-        List<ParamValue> args =
-                Collections.singletonList(
-                        ParamValue.newBuilder().setIdentifier("testValue").build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot(
-                                "singularValue",
-                                TaskCapabilityUtils.paramValuesToCurrentValue(args, Status.PENDING),
-                                taskParamMap,
-                                Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isFalse();
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(0))
-                                .setStatus(Status.REJECTED)
-                                .build());
-    }
-
-    @Test
-    public void processSlot_repeatedValue_accepted() throws Exception {
-        SettableFutureWrapper<List<String>> lastReceivedArgs = new SettableFutureWrapper<>();
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "repeatedValue",
-                        (paramValue) -> false,
-                        createValueListResolver(
-                                ValidationResult.newAccepted(), lastReceivedArgs::set),
-                        TypeConverters::toStringValue,
-                        null,
-                        null);
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("repeatedValue", binding);
-        List<ParamValue> args =
-                Arrays.asList(
-                        ParamValue.newBuilder().setIdentifier("testValue1").build(),
-                        ParamValue.newBuilder().setIdentifier("testValue2").build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot(
-                                "repeatedValue",
-                                TaskCapabilityUtils.paramValuesToCurrentValue(args, Status.PENDING),
-                                taskParamMap,
-                                Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isTrue();
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(0))
-                                .setStatus(Status.ACCEPTED)
-                                .build(),
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(1))
-                                .setStatus(Status.ACCEPTED)
-                                .build());
-        assertThat(lastReceivedArgs.getFuture().get()).containsExactly("testValue1", "testValue2");
-    }
-
-    @Test
-    public void processSlot_repeatedValue_rejected() throws Exception {
-        SettableFutureWrapper<List<String>> lastReceivedArgs = new SettableFutureWrapper<>();
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "repeatedValue",
-                        (paramValue) -> false,
-                        createValueListResolver(
-                                ValidationResult.newRejected(), lastReceivedArgs::set),
-                        TypeConverters::toStringValue,
-                        null,
-                        null);
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("repeatedValue", binding);
-        List<ParamValue> args =
-                Arrays.asList(
-                        ParamValue.newBuilder().setIdentifier("testValue1").build(),
-                        ParamValue.newBuilder().setIdentifier("testValue2").build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot(
-                                "repeatedValue",
-                                TaskCapabilityUtils.paramValuesToCurrentValue(args, Status.PENDING),
-                                taskParamMap,
-                                Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isFalse();
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(0))
-                                .setStatus(Status.REJECTED)
-                                .build(),
-                        CurrentValue.newBuilder()
-                                .setValue(args.get(1))
-                                .setStatus(Status.REJECTED)
-                                .build());
-        assertThat(lastReceivedArgs.getFuture().get()).containsExactly("testValue1", "testValue2");
-    }
-
-    @Test
-    public void listValues_oneAccepted_oneAssistantDisambig_invokesRendererAndOnReceived()
-            throws Exception {
-        SettableFutureWrapper<String> onReceivedCb = new SettableFutureWrapper<>();
-        SettableFutureWrapper<List<String>> renderCb = new SettableFutureWrapper<>();
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "assistantDrivenSlot",
-                        (paramValue) -> !paramValue.hasIdentifier(),
-                        createAssistantDisambigResolver(
-                                ValidationResult.newAccepted(), onReceivedCb::set, renderCb::set),
-                        TypeConverters::toStringValue,
-                        null,
-                        null);
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("assistantDrivenSlot", binding);
-        CurrentValue previouslyAccepted =
-                CurrentValue.newBuilder()
-                        .setStatus(Status.ACCEPTED)
-                        .setValue(
-                                ParamValue.newBuilder()
-                                        .setIdentifier("id")
-                                        .setStructValue(
-                                                Struct.newBuilder()
-                                                        .putFields(
-                                                                "id",
-                                                                Value.newBuilder()
-                                                                        .setStringValue("1234")
-                                                                        .build())))
-                        .build();
-        List<CurrentValue> values =
-                Arrays.asList(
-                        previouslyAccepted,
-                        CurrentValue.newBuilder()
-                                .setStatus(Status.PENDING)
-                                .setDisambiguationData(
-                                        DisambiguationData.newBuilder()
-                                                .addEntities(
-                                                        Entity.newBuilder()
-                                                                .setIdentifier("entity-1"))
-                                                .addEntities(
-                                                        Entity.newBuilder()
-                                                                .setIdentifier("entity-2")))
-                                .build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot(
-                                "assistantDrivenSlot", values, taskParamMap, Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isFalse();
-        assertThat(onReceivedCb.getFuture().get()).isEqualTo("id");
-        assertThat(renderCb.getFuture().get()).containsExactly("entity-1", "entity-2");
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        previouslyAccepted,
-                        CurrentValue.newBuilder()
-                                .setStatus(Status.DISAMBIG)
-                                .setDisambiguationData(
-                                        DisambiguationData.newBuilder()
-                                                .addEntities(
-                                                        Entity.newBuilder()
-                                                                .setIdentifier("entity-1"))
-                                                .addEntities(
-                                                        Entity.newBuilder()
-                                                                .setIdentifier("entity-2")))
-                                .build());
-    }
-
-    @Test
-    public void singularValue_appDisambigRejected_onReceivedNotCalled() throws Exception {
-        SettableFutureWrapper<String> onReceivedCb = new SettableFutureWrapper<>();
-        SettableFutureWrapper<SearchAction<String>> appSearchCb = new SettableFutureWrapper<>();
-        EntitySearchResult<String> entitySearchResult = EntitySearchResult.empty();
-        GenericResolverInternal<String> resolver =
-                createAppEntityResolver(
-                        ValidationResult.newAccepted(), // should not be invoked.
-                        onReceivedCb::set,
-                        entitySearchResult, // app-grounding returns REJECTED in all cases
-                        appSearchCb::set);
-        TaskParamBinding<String> binding =
-                new TaskParamBinding<>(
-                        "appDrivenSlot",
-                        (paramValue) -> true, // always invoke app-grounding in all cases
-                        resolver,
-                        TypeConverters::toStringValue, // Not invoked
-                        (unused) -> Entity.getDefaultInstance(),
-                        (unused) ->
-                                SearchAction.<String>newBuilder()
-                                        .setQuery("A")
-                                        .setObject("nested")
-                                        .build());
-        Map<String, TaskParamBinding<?>> taskParamMap = new HashMap<>();
-        taskParamMap.put("appDrivenSlot", binding);
-        List<CurrentValue> values =
-                Collections.singletonList(
-                        CurrentValue.newBuilder()
-                                .setStatus(Status.PENDING)
-                                .setValue(buildSearchActionParamValue("A"))
-                                .build());
-
-        SlotProcessingResult result =
-                TaskSlotProcessor.processSlot("appDrivenSlot", values, taskParamMap, Runnable::run)
-                        .get();
-
-        assertThat(result.isSuccessful()).isFalse();
-        assertThat(onReceivedCb.getFuture().isDone()).isFalse();
-        assertThat(appSearchCb.getFuture().isDone()).isTrue();
-        assertThat(appSearchCb.getFuture().get())
-                .isEqualTo(
-                        SearchAction.<String>newBuilder()
-                                .setQuery("A")
-                                .setObject("nested")
-                                .build());
-        assertThat(result.getProcessedValues())
-                .containsExactly(
-                        CurrentValue.newBuilder()
-                                .setStatus(Status.REJECTED)
-                                .setValue(buildSearchActionParamValue("A"))
-                                .build());
-    }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.kt
new file mode 100644
index 0000000..38a6cde
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/task/impl/TaskSlotProcessorTest.kt
@@ -0,0 +1,380 @@
+/*
+ * 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.appactions.interaction.capabilities.core.task.impl
+
+import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
+import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
+import androidx.appactions.interaction.capabilities.core.task.AppEntityResolver
+import androidx.appactions.interaction.capabilities.core.task.EntitySearchResult
+import androidx.appactions.interaction.capabilities.core.task.EntitySearchResult.Companion.empty
+import androidx.appactions.interaction.capabilities.core.task.InventoryResolver
+import androidx.appactions.interaction.capabilities.core.task.ValidationResult
+import androidx.appactions.interaction.capabilities.core.task.ValidationResult.Companion.newAccepted
+import androidx.appactions.interaction.capabilities.core.task.ValidationResult.Companion.newRejected
+import androidx.appactions.interaction.capabilities.core.task.ValueListener
+import androidx.appactions.interaction.capabilities.core.testing.ArgumentUtils
+import androidx.appactions.interaction.capabilities.core.testing.spec.SettableFutureWrapper
+import androidx.appactions.interaction.capabilities.core.values.SearchAction
+import androidx.appactions.interaction.proto.CurrentValue
+import androidx.appactions.interaction.proto.DisambiguationData
+import androidx.appactions.interaction.proto.Entity
+import androidx.appactions.interaction.proto.ParamValue
+import androidx.appactions.interaction.protobuf.Struct
+import androidx.appactions.interaction.protobuf.Value
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.ListenableFuture
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class TaskSlotProcessorTest {
+    private fun <T> createAssistantDisambigResolver(
+        validationResult: ValidationResult,
+        valueConsumer: (T) -> Unit,
+        renderConsumer: (List<String>) -> Unit,
+    ): GenericResolverInternal<T> {
+        return GenericResolverInternal.fromInventoryResolver(
+            object : InventoryResolver<T> {
+                override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
+                    valueConsumer.invoke(value)
+                    return Futures.immediateFuture(validationResult)
+                }
+
+                override fun renderChoices(entityIDs: List<String>): ListenableFuture<Void> {
+                    renderConsumer.invoke(entityIDs)
+                    return Futures.immediateVoidFuture()
+                }
+            }
+        )
+    }
+
+    private fun <T> createValueResolver(
+        validationResult: ValidationResult,
+        valueConsumer: (T) -> Unit,
+    ): GenericResolverInternal<T> {
+        return GenericResolverInternal.fromValueListener(
+            object : ValueListener<T> {
+                override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
+                    valueConsumer.invoke(value)
+                    return Futures.immediateFuture(validationResult)
+                }
+            }
+        )
+    }
+
+    private fun <T> createValueResolver(
+        validationResult: ValidationResult
+    ): GenericResolverInternal<T> {
+        return createValueResolver(validationResult) { _: T -> }
+    }
+
+    private fun <T> createValueListResolver(
+        validationResult: ValidationResult,
+        valueConsumer: (List<T>) -> Unit,
+    ): GenericResolverInternal<T> {
+        return GenericResolverInternal.fromValueListListener(
+            object : ValueListener<List<T>> {
+                override fun onReceivedAsync(value: List<T>): ListenableFuture<ValidationResult> {
+                    valueConsumer.invoke(value)
+                    return Futures.immediateFuture(validationResult)
+                }
+            }
+        )
+    }
+
+    private fun <T> createAppEntityResolver(
+        validationResult: ValidationResult,
+        valueConsumer: (T) -> Unit,
+        appSearchResult: EntitySearchResult<T>,
+        appSearchConsumer: (SearchAction<T>) -> Unit,
+    ): GenericResolverInternal<T> {
+        return GenericResolverInternal.fromAppEntityResolver(
+            object : AppEntityResolver<T> {
+                override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
+                    valueConsumer.invoke(value)
+                    return Futures.immediateFuture(validationResult)
+                }
+
+                override fun lookupAndRender(
+                    searchAction: SearchAction<T>
+                ): ListenableFuture<EntitySearchResult<T>> {
+                    appSearchConsumer.invoke(searchAction)
+                    return Futures.immediateFuture(appSearchResult)
+                }
+            }
+        )
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun processSlot_singleValue_accepted(): Unit = runBlocking {
+        val binding =
+            TaskParamBinding(
+                "singularValue",
+                { false },
+                createValueResolver(newAccepted()),
+                { TypeConverters.toStringValue(it) },
+                null,
+                null
+            )
+        val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+        taskParamMap["singularValue"] = binding
+        val args = listOf(ParamValue.newBuilder().setIdentifier("testValue").build())
+        val (isSuccessful, processedValues) =
+            TaskSlotProcessor.processSlot(
+                "singularValue",
+                TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
+                taskParamMap
+            )
+        assertThat(isSuccessful).isTrue()
+        assertThat(processedValues)
+            .containsExactly(
+                CurrentValue.newBuilder()
+                    .setValue(args[0])
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .build()
+            )
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun processSlot_singleValue_rejected(): Unit = runBlocking {
+        val binding =
+            TaskParamBinding(
+                "singularValue",
+                { false },
+                createValueResolver(newRejected()),
+                { TypeConverters.toStringValue(it) },
+                null,
+                null
+            )
+        val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+        taskParamMap["singularValue"] = binding
+        val args = listOf(ParamValue.newBuilder().setIdentifier("testValue").build())
+        val (isSuccessful, processedValues) =
+            TaskSlotProcessor.processSlot(
+                "singularValue",
+                TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
+                taskParamMap
+            )
+        assertThat(isSuccessful).isFalse()
+        assertThat(processedValues)
+            .containsExactly(
+                CurrentValue.newBuilder()
+                    .setValue(args[0])
+                    .setStatus(CurrentValue.Status.REJECTED)
+                    .build()
+            )
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun processSlot_repeatedValue_accepted(): Unit = runBlocking {
+        val lastReceivedArgs = SettableFutureWrapper<List<String?>>()
+        val binding =
+            TaskParamBinding(
+                "repeatedValue",
+                { false },
+                createValueListResolver(newAccepted()) { lastReceivedArgs.set(it) },
+                { TypeConverters.toStringValue(it) },
+                null,
+                null
+            )
+        val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+        taskParamMap["repeatedValue"] = binding
+        val args =
+            listOf(
+                ParamValue.newBuilder().setIdentifier("testValue1").build(),
+                ParamValue.newBuilder().setIdentifier("testValue2").build()
+            )
+        val (isSuccessful, processedValues) =
+            TaskSlotProcessor.processSlot(
+                "repeatedValue",
+                TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
+                taskParamMap
+            )
+        assertThat(isSuccessful).isTrue()
+        assertThat(processedValues)
+            .containsExactly(
+                CurrentValue.newBuilder()
+                    .setValue(args[0])
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .build(),
+                CurrentValue.newBuilder()
+                    .setValue(args[1])
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .build()
+            )
+        assertThat(lastReceivedArgs.future.get()).containsExactly("testValue1", "testValue2")
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun processSlot_repeatedValue_rejected(): Unit = runBlocking {
+        val lastReceivedArgs = SettableFutureWrapper<List<String>>()
+        val binding =
+            TaskParamBinding(
+                "repeatedValue",
+                { false },
+                createValueListResolver(newRejected()) { lastReceivedArgs.set(it) },
+                { TypeConverters.toStringValue(it) },
+                null,
+                null
+            )
+        val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+        taskParamMap["repeatedValue"] = binding
+        val args =
+            listOf(
+                ParamValue.newBuilder().setIdentifier("testValue1").build(),
+                ParamValue.newBuilder().setIdentifier("testValue2").build()
+            )
+        val (isSuccessful, processedValues) =
+            TaskSlotProcessor.processSlot(
+                "repeatedValue",
+                TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
+                taskParamMap
+            )
+        assertThat(isSuccessful).isFalse()
+        assertThat(processedValues)
+            .containsExactly(
+                CurrentValue.newBuilder()
+                    .setValue(args[0])
+                    .setStatus(CurrentValue.Status.REJECTED)
+                    .build(),
+                CurrentValue.newBuilder()
+                    .setValue(args[1])
+                    .setStatus(CurrentValue.Status.REJECTED)
+                    .build()
+            )
+        assertThat(lastReceivedArgs.future.get()).containsExactly("testValue1", "testValue2")
+    }
+
+    @Test
+    @Throws(Exception::class)
+    fun listValues_oneAccepted_oneAssistantDisambig_invokesRendererAndOnReceived(): Unit =
+        runBlocking {
+            val onReceivedCb = SettableFutureWrapper<String>()
+            val renderCb = SettableFutureWrapper<List<String?>>()
+            val binding =
+                TaskParamBinding(
+                    "assistantDrivenSlot",
+                    { !it.hasIdentifier() },
+                    createAssistantDisambigResolver(newAccepted(), { onReceivedCb.set(it) }) {
+                        renderCb.set(it)
+                    },
+                    { TypeConverters.toStringValue(it) },
+                    null,
+                    null
+                )
+            val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+            taskParamMap["assistantDrivenSlot"] = binding
+            val previouslyAccepted =
+                CurrentValue.newBuilder()
+                    .setStatus(CurrentValue.Status.ACCEPTED)
+                    .setValue(
+                        ParamValue.newBuilder()
+                            .setIdentifier("id")
+                            .setStructValue(
+                                Struct.newBuilder()
+                                    .putFields(
+                                        "id",
+                                        Value.newBuilder().setStringValue("1234").build()
+                                    )
+                            )
+                    )
+                    .build()
+            val values =
+                listOf(
+                    previouslyAccepted,
+                    CurrentValue.newBuilder()
+                        .setStatus(CurrentValue.Status.PENDING)
+                        .setDisambiguationData(
+                            DisambiguationData.newBuilder()
+                                .addEntities(Entity.newBuilder().setIdentifier("entity-1"))
+                                .addEntities(Entity.newBuilder().setIdentifier("entity-2"))
+                        )
+                        .build()
+                )
+            val (isSuccessful, processedValues) =
+                TaskSlotProcessor.processSlot("assistantDrivenSlot", values, taskParamMap)
+            assertThat(isSuccessful).isFalse()
+            assertThat(onReceivedCb.future.get()).isEqualTo("id")
+            assertThat(renderCb.future.get()).containsExactly("entity-1", "entity-2")
+            assertThat(processedValues)
+                .containsExactly(
+                    previouslyAccepted,
+                    CurrentValue.newBuilder()
+                        .setStatus(CurrentValue.Status.DISAMBIG)
+                        .setDisambiguationData(
+                            DisambiguationData.newBuilder()
+                                .addEntities(Entity.newBuilder().setIdentifier("entity-1"))
+                                .addEntities(Entity.newBuilder().setIdentifier("entity-2"))
+                        )
+                        .build()
+                )
+        }
+
+    @Test
+    @Throws(Exception::class)
+    fun singularValue_appDisambigRejected_onReceivedNotCalled(): Unit = runBlocking {
+        val onReceivedCb = SettableFutureWrapper<String>()
+        val appSearchCb = SettableFutureWrapper<SearchAction<String>>()
+        val entitySearchResult = empty<String>()
+        val resolver =
+            createAppEntityResolver(
+                newAccepted(),
+                { result: String -> onReceivedCb.set(result) },
+                entitySearchResult
+            ) { result: SearchAction<String> ->
+                appSearchCb.set(result)
+            }
+        val binding =
+            TaskParamBinding(
+                "appDrivenSlot",
+                { true }, // always invoke app-grounding in all cases
+                resolver,
+                { TypeConverters.toStringValue(it) }, // Not invoked
+                { Entity.getDefaultInstance() }
+            ) {
+                SearchAction.newBuilder<String>().setQuery("A").setObject("nested").build()
+            }
+        val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
+        taskParamMap["appDrivenSlot"] = binding
+        val values =
+            listOf(
+                CurrentValue.newBuilder()
+                    .setStatus(CurrentValue.Status.PENDING)
+                    .setValue(ArgumentUtils.buildSearchActionParamValue("A"))
+                    .build()
+            )
+        val (isSuccessful, processedValues) =
+            TaskSlotProcessor.processSlot("appDrivenSlot", values, taskParamMap)
+        assertThat(isSuccessful).isFalse()
+        assertThat(onReceivedCb.future.isDone).isFalse()
+        assertThat(appSearchCb.future.isDone).isTrue()
+        assertThat(appSearchCb.future.get())
+            .isEqualTo(SearchAction.newBuilder<String>().setQuery("A").setObject("nested").build())
+        assertThat(processedValues)
+            .containsExactly(
+                CurrentValue.newBuilder()
+                    .setStatus(CurrentValue.Status.REJECTED)
+                    .setValue(ArgumentUtils.buildSearchActionParamValue("A"))
+                    .build()
+            )
+    }
+}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/TestingUtils.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/TestingUtils.kt
new file mode 100644
index 0000000..b29bbed
--- /dev/null
+++ b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/TestingUtils.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.appactions.interaction.capabilities.core.testing
+
+import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
+import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
+import androidx.appactions.interaction.proto.FulfillmentResponse
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withTimeout
+
+/** A wrapper being used for testing [CallbackInternal] */
+class CallbackResponse
+constructor(val fulfillmentResponse: FulfillmentResponse?, val errorStatus: ErrorStatusInternal?)
+
+/**
+ * A fake CallbackInternal instance being used for testing to receive the [CallbackResponse]
+ * containing either [FulfillmentResponse] or [ErrorStatusInternal]
+ */
+class FakeCallbackInternal constructor(private val sendTimeoutMs: Long) : CallbackInternal {
+
+    private val channel = Channel<CallbackResponse>(1)
+
+    override fun onSuccess(fulfillmentResponse: FulfillmentResponse) {
+        runBlocking {
+            withTimeout(sendTimeoutMs) { channel.send(CallbackResponse(fulfillmentResponse, null)) }
+        }
+        channel.close()
+    }
+
+    override fun onError(errorStatus: ErrorStatusInternal) {
+        runBlocking {
+            withTimeout(sendTimeoutMs) { channel.send(CallbackResponse(null, errorStatus)) }
+        }
+        channel.close()
+    }
+
+    fun receiveResponse(): CallbackResponse = runBlocking {
+        withTimeout(sendTimeoutMs) { channel.receive() }
+    }
+}
diff --git a/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto b/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto
index ff4aec8..f30d013 100644
--- a/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto
+++ b/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto
@@ -163,7 +163,7 @@
   message AppDialogState {
     // Each App capability can be associated with multiple dialogs. Use this
     // field to identify the dialog instance.
-    string dialog_identifier = 1;
+    string session_identifier = 1;
 
     // Identifier of the corresponding capability that this dialog state maps
     // to. This field maps to AppActionsContext.AppAction.identifier.
@@ -210,7 +210,7 @@
 }
 
 // Represents the data used to perform an intent.
-// Next ID: 8
+// Next ID: 7
 message FulfillmentRequest {
   message Fulfillment {
     // Name of the intent. For example: actions.intent.UPDATE_FORM_FIELD
@@ -220,24 +220,6 @@
     // |identifier| field with in `AppActionsContext.AppAction`.
     string identifier = 2;
 
-    message SessionInfo {
-      // Identifier of the dialog session that the user is currently interacting
-      // with. Assistant will generate this ID as UUID. This is different from
-      // the identifier field in FulfillmentRequest.Fulfillment in that identifier
-      // stays constant for each intent, even when there are multiple dialog
-      // instances of the intent, but the session_identifier is unique per dialog
-      // instance.
-      string session_identifier = 1;
-
-      // True if this fulfillment request is from a new dialog. Mainly used for
-      // debugging purpose.
-      bool is_new_session = 2;
-    }
-
-    // Information related to this dialog session. Used by the SDK to create a new
-    // session.
-    optional SessionInfo session_info = 7;
-
     message FulfillmentValue {
       // The resolved value for the parameter.
       ParamValue value = 1;
diff --git a/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto b/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto
index e67272e..e4cbeb2 100644
--- a/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto
+++ b/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto
@@ -30,11 +30,11 @@
 // user issues a query. This proto contains user's query (parsed into BII).
 // NEXT_ID: 3
 message Request {
-  // Session_id is used to identify the hosts. When there are multiple hosts
-  // connecting to the provider at the same time for different requests,
-  // provider can use the session_ids to distinguish sessions, thus
-  // providing different responses to different hosts.
-  int32 session_id = 1  [deprecated = true];
+  // This session id corresponds to the one in [AppDialogState]. Session id is used to identify the
+  // hosts. When there are multiple hosts connecting to the provider at the same time for different
+  // requests, provider can use the session_ids to distinguish sessions, thus providing different
+  // responses to different hosts.
+  string session_identifier = 1;
   // FulfillmentRequest contains the request data sent from Assistant, such as
   // new values of BII arguments.
   .androidx.appactions.interaction.proto.FulfillmentRequest fulfillment_request = 2;
@@ -91,8 +91,8 @@
 // NEXT_ID: 3
 message UiRequest {
   int32 session_id = 1 [deprecated = true];
-  // Indicates the UiResponse should contain only the responses for this
-  // particular session.
+  // This session id corresponds to the one in [AppDialogState]. Indicates the UiResponse should
+  // contain only the responses for this particular session.
   string session_identifier = 2;
 }
 
@@ -195,8 +195,8 @@
 // NEXT_ID: 11
 message CollectionRequest {
   int32 session_id = 1 [deprecated = true];
-  // Indicates the CollectionResponse should contain only the responses for this
-  // particular session.
+  // This session id corresponds to the one in [AppDialogState]. Indicates the CollectionResponse
+  // should contain only the responses for this particular session.
   string session_identifier = 10;
   int32 view_id = 2;
   oneof request_data {
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.java b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.java
index eac1758..238fbfb 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.java
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.java
@@ -221,9 +221,8 @@
                                     ERROR_NO_ACTION_CAPABILITY)));
             return;
         }
-        String sessionId = selectedFulfillment.getSessionInfo().getSessionIdentifier();
-        ActionCapabilitySession currentSession =
-                SessionManager.INSTANCE.getSession(sessionId);
+        String sessionId = request.getSessionIdentifier();
+        ActionCapabilitySession currentSession = SessionManager.INSTANCE.getSession(sessionId);
         if (currentSession == null) {
             responseObserver.onError(
                     new StatusRuntimeException(
@@ -245,8 +244,7 @@
                         Response.Builder responseBuilder =
                                 convertFulfillmentResponse(fulfillmentResponse, capability.get())
                                         .toBuilder();
-                        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(
-                                currentSession.getUiHandle());
+                        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(sessionId);
                         if (uiCache != null && uiCache.hasUnreadUiResponse()) {
                             responseBuilder.setUiUpdate(UiUpdate.getDefaultInstance());
                             if (!uiCache.getCachedChangedViewIds().isEmpty()) {
@@ -286,8 +284,9 @@
     public void requestUi(
             AppInteractionServiceProto.UiRequest req,
             StreamObserver<AppInteractionServiceProto.UiResponse> responseObserver) {
+        String sessionId = req.getSessionIdentifier();
         ActionCapabilitySession currentSession = SessionManager.INSTANCE
-                .getSession(req.getSessionIdentifier());
+                .getSession(sessionId);
         if (currentSession == null) {
             responseObserver.onError(
                     new StatusRuntimeException(
@@ -301,7 +300,7 @@
                             Status.FAILED_PRECONDITION.withDescription(ERROR_SESSION_ENDED)));
             return;
         }
-        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(currentSession.getUiHandle());
+        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(sessionId);
         if (uiCache == null) {
             destroySession(req.getSessionIdentifier());
             responseObserver.onError(
@@ -349,8 +348,9 @@
     @Override
     public void requestCollection(
             CollectionRequest req, StreamObserver<CollectionResponse> responseObserver) {
+        String sessionId = req.getSessionIdentifier();
         ActionCapabilitySession currentSession = SessionManager.INSTANCE
-                .getSession(req.getSessionIdentifier());
+                .getSession(sessionId);
         if (currentSession == null) {
             responseObserver.onError(
                     new StatusRuntimeException(
@@ -364,7 +364,7 @@
                             Status.FAILED_PRECONDITION.withDescription(ERROR_SESSION_ENDED)));
             return;
         }
-        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(currentSession.getUiHandle());
+        UiCache uiCache = UiSessions.INSTANCE.getUiCacheOrNull(sessionId);
         if (uiCache == null) {
             destroySession(req.getSessionIdentifier());
             responseObserver.onError(
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt
index f68fc64..db4d7fe 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt
@@ -18,6 +18,7 @@
 
 import androidx.annotation.GuardedBy
 import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession
+import java.util.IdentityHashMap
 import javax.annotation.concurrent.ThreadSafe
 
 /** Global object for managing capability sessions. */
@@ -29,8 +30,20 @@
     @GuardedBy("lock")
     private val sessions = mutableMapOf<String, ActionCapabilitySession>()
 
+    /**
+     * stores a map of uiHandle reference to sessionId, in order to get/set UiCache entries with
+     * sessionId key.
+     *
+     * if sessionId is the key, we can release the lock as soon as the ActionExecutor finishes.
+     */
+    @GuardedBy("lock")
+    private val uiHandleToSessionId = IdentityHashMap<Any, String>()
+
     fun putSession(sessionId: String, session: ActionCapabilitySession) {
-        synchronized(lock) { sessions[sessionId] = session }
+        synchronized(lock) {
+            sessions[sessionId] = session
+            uiHandleToSessionId[session.uiHandle] = sessionId
+        }
     }
 
     fun getSession(sessionId: String): ActionCapabilitySession? {
@@ -39,7 +52,17 @@
         }
     }
 
+    fun getLatestSessionIdFromUiHandle(uiHandle: Any): String? {
+        synchronized(lock) {
+            return uiHandleToSessionId[uiHandle]
+        }
+    }
+
     fun removeSession(sessionId: String) {
-        synchronized(lock) { sessions.remove(sessionId) }
+        synchronized(lock) {
+            val session = sessions[sessionId]
+            session?.let { uiHandleToSessionId.remove(it.uiHandle) }
+            sessions.remove(sessionId)
+        }
     }
 }
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.java b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.java
index a91237a..5683769 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.java
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.java
@@ -46,7 +46,6 @@
     private final Object mLock = new Object();
     @GuardedBy("mLock")
     private final Map<Integer, RemoteViewsFactory> mCachedRemoteViewsFactories = new HashMap<>();
-    private final Object mUiHandle;
 
     @GuardedBy("mLock")
     @Nullable
@@ -65,10 +64,6 @@
     @GuardedBy("mLock")
     private boolean mUnreadUiResponse;
 
-    UiCache(Object uiHandle) {
-        this.mUiHandle = uiHandle;
-    }
-
     /**
      * Caches a UiResponse for this particular {@link BaseSession}.
      */
@@ -84,11 +79,6 @@
         }
     }
 
-    @NonNull
-    Object getUiHandle() {
-        return mUiHandle;
-    }
-
     @Nullable
     RemoteViewsFactory onGetViewFactoryInternal(int viewId) {
         synchronized (mLock) {
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
index 5908f8a..f6f514e 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
@@ -33,37 +33,44 @@
 @ThreadSafe
 internal object UiSessions {
     private val lock = Any()
-    @GuardedBy("lock") private val uiCacheList = mutableListOf<UiCache>()
+    @GuardedBy("lock")
+    private val sessionIdToUiCache = mutableMapOf<String, UiCache>()
 
-    fun removeUiCache(uiHandle: Any): Boolean {
+    fun removeUiCache(sessionId: String): Boolean {
         synchronized(lock) {
-            return uiCacheList.remove(getUiCacheOrNull(uiHandle))
+            return sessionIdToUiCache.remove(sessionId) != null
         }
     }
 
-    fun getOrCreateUiCache(uiHandle: Any): UiCache {
+    fun getOrCreateUiCache(sessionId: String): UiCache {
         synchronized(lock) {
-            return uiCacheList.find { it.uiHandle === uiHandle } ?: createUiCache(uiHandle)
+            return sessionIdToUiCache[sessionId] ?: createUiCache(sessionId)
         }
     }
 
-    fun getUiCacheOrNull(uiHandle: Any): UiCache? {
+    fun getUiCacheOrNull(sessionId: String): UiCache? {
         synchronized(lock) {
-            return uiCacheList.find { it.uiHandle === uiHandle }
+            return sessionIdToUiCache[sessionId]
         }
     }
 
-    private fun createUiCache(uiHandle: Any): UiCache {
-        val uiSession = UiCache(uiHandle)
-        uiCacheList.add(uiSession)
-        return uiSession
+    private fun createUiCache(sessionId: String): UiCache {
+        val uiCache = UiCache()
+        synchronized(lock) {
+            sessionIdToUiCache[sessionId] = uiCache
+        }
+        return uiCache
     }
 }
 
 /** Return a UI associated with this [BaseSession]. */
 fun BaseSession<*, *>.updateUi(uiResponse: UiResponse) =
-    UiSessions.getOrCreateUiCache(this).updateUiInternal(uiResponse)
+    UiSessions.getOrCreateUiCache(
+        SessionManager.getLatestSessionIdFromUiHandle(this)!!
+    ).updateUiInternal(uiResponse)
 
 /** Return a UI associated with this [ActionExecutor]. */
 fun ActionExecutor<*, *>.updateUi(uiResponse: UiResponse) =
-    UiSessions.getOrCreateUiCache(this).updateUiInternal(uiResponse)
+    UiSessions.getOrCreateUiCache(
+        SessionManager.getLatestSessionIdFromUiHandle(this)!!
+    ).updateUiInternal(uiResponse)
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt
index 8cfa1da..9b7e7e6 100644
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt
+++ b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt
@@ -24,7 +24,6 @@
 import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
 import androidx.appactions.interaction.proto.FulfillmentRequest
 import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.SessionInfo
 import androidx.appactions.interaction.proto.FulfillmentResponse
 import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
 import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
@@ -66,8 +65,6 @@
 import java.util.Collections
 import kotlin.test.assertFailsWith
 import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.junit.Before
 import org.junit.Rule
@@ -76,7 +73,6 @@
 
 // TODO(b/271929200) Implement tests for the 2 UI related RPCs
 @RunWith(AndroidJUnit4::class)
-@kotlinx.coroutines.ExperimentalCoroutinesApi
 class AppInteractionServiceGrpcImplTest {
 
     @get:Rule val grpcCleanup = GrpcCleanupRule()
@@ -96,18 +92,14 @@
     private val testFulfillmentRequest =
         FulfillmentRequest.newBuilder()
             .addFulfillments(
-                Fulfillment.newBuilder()
-                    .setName(testBiiName)
-                    .setIdentifier(capabilityId)
-                    .setSessionInfo(SessionInfo.newBuilder().setSessionIdentifier(sessionId))
-                    .build()
+                Fulfillment.newBuilder().setName(testBiiName).setIdentifier(capabilityId).build()
             )
             .build()
     private val testFulfillmentResponse =
         FulfillmentResponse.newBuilder()
             .setExecutionOutput(
                 StructuredOutput.newBuilder()
-                    .addOutputValues(OutputValue.newBuilder().setName("bio_arg1"))
+                    .addOutputValues(OutputValue.newBuilder().setName("bio_arg1")),
             )
             .build()
     private var capability1 = mock<ActionCapability>()
@@ -126,36 +118,33 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
 
-                // Set up gRPC response capture
-                val startUpSessionCallback = CompletableDeferred<Unit>()
-                val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
-                whenever(startSessionResponseObserver.onNext(any())) doAnswer
-                    {
-                        startUpSessionCallback.complete(Unit)
-                        Unit
-                    }
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
 
-                // Send startup request
-                val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
-                startSessionRequestObserver.onNext(defaultStartSessionRequest)
-
-                // Assert startup response
-                startUpSessionCallback.await()
-                val responseCaptor = argumentCaptor<StartSessionResponse>()
-                verify(startSessionResponseObserver).onNext(responseCaptor.capture())
-                val startSessionResponse = responseCaptor.firstValue
-                assertThat(startSessionResponse)
-                    .isEqualTo(StartSessionResponse.getDefaultInstance())
-                verify(startSessionResponseObserver, times(1)).onNext(any())
+        // Set up gRPC response capture
+        val startUpSessionCallback = CompletableDeferred<Unit>()
+        val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
+        whenever(startSessionResponseObserver.onNext(any())) doAnswer
+            {
+                startUpSessionCallback.complete(Unit)
+                Unit
             }
-        }
+
+        // Send startup request
+        val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
+        startSessionRequestObserver.onNext(defaultStartSessionRequest)
+
+        // Assert startup response
+        startUpSessionCallback.await()
+        val responseCaptor = argumentCaptor<StartSessionResponse>()
+        verify(startSessionResponseObserver).onNext(responseCaptor.capture())
+        val startSessionResponse = responseCaptor.firstValue
+        assertThat(startSessionResponse).isEqualTo(StartSessionResponse.getDefaultInstance())
+        verify(startSessionResponseObserver, times(1)).onNext(any())
+
         server.shutdownNow()
     }
 
@@ -164,34 +153,32 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
 
-                // Send startup request
-                val invalidStartSessionRequest =
-                    StartSessionRequest.newBuilder()
-                        .setIntentName(testBiiName)
-                        .setIdentifier("UNKNOWN_FULFILLMENT_ID")
-                        .setSessionIdentifier(sessionId)
-                        .build()
-                val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
-                startSessionRequestObserver.onNext(invalidStartSessionRequest)
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
 
-                // Assert.
-                val exceptionCaptor = argumentCaptor<StatusRuntimeException>()
-                verify(startSessionResponseObserver).onError(exceptionCaptor.capture())
-                assertThat(Status.fromThrowable(exceptionCaptor.firstValue).code)
-                    .isEqualTo(Status.Code.FAILED_PRECONDITION)
-                assertThat(Status.fromThrowable(exceptionCaptor.firstValue).description)
-                    .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
-                verify(capability1, never()).createSession(any())
-            }
-        }
+        // Send startup request
+        val invalidStartSessionRequest =
+            StartSessionRequest.newBuilder()
+                .setIntentName(testBiiName)
+                .setIdentifier("UNKNOWN_FULFILLMENT_ID")
+                .setSessionIdentifier(sessionId)
+                .build()
+        val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
+        startSessionRequestObserver.onNext(invalidStartSessionRequest)
+
+        // Assert.
+        val exceptionCaptor = argumentCaptor<StatusRuntimeException>()
+        verify(startSessionResponseObserver).onError(exceptionCaptor.capture())
+        assertThat(Status.fromThrowable(exceptionCaptor.firstValue).code)
+            .isEqualTo(Status.Code.FAILED_PRECONDITION)
+        assertThat(Status.fromThrowable(exceptionCaptor.firstValue).description)
+            .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
+        verify(capability1, never()).createSession(any())
+
         server.shutdownNow()
     }
 
@@ -200,26 +187,25 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-                assertStartupSession(stub)
-                verify(capability1, times(1)).createSession(any())
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
+        assertStartupSession(stub)
+        verify(capability1, times(1)).createSession(any())
 
-                // Send fulfillment request
-                val request =
-                    Request.newBuilder().setFulfillmentRequest(testFulfillmentRequest).build()
-                val responseFuture = futureStub.sendRequestFulfillment(request)
+        // Send fulfillment request
+        val request =
+            Request.newBuilder()
+                .setSessionIdentifier(sessionId)
+                .setFulfillmentRequest(testFulfillmentRequest)
+                .build()
+        val responseFuture = futureStub.sendRequestFulfillment(request)
 
-                val response = responseFuture.await()
-                assertThat(response).isNotNull()
-                assertThat(response.fulfillmentResponse).isEqualTo(testFulfillmentResponse)
-            }
-        }
+        val response = responseFuture.await()
+        assertThat(response).isNotNull()
+        assertThat(response.fulfillmentResponse).isEqualTo(testFulfillmentResponse)
         server.shutdownNow()
     }
 
@@ -228,31 +214,28 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-                assertStartupSession(stub)
-                verify(capability1, times(1)).createSession(any())
 
-                // Ensure a failed future is returned when missing fulfillment
-                val requestWithMissingFulfillment =
-                    Request.newBuilder()
-                        .setFulfillmentRequest(FulfillmentRequest.getDefaultInstance())
-                        .build()
-                val exception =
-                    assertFailsWith<StatusRuntimeException> {
-                        futureStub.sendRequestFulfillment(requestWithMissingFulfillment).await()
-                    }
-                assertThat(Status.fromThrowable(exception).code)
-                    .isEqualTo(Status.Code.FAILED_PRECONDITION)
-                assertThat(Status.fromThrowable(exception).description)
-                    .isEqualTo(ERROR_NO_FULFILLMENT_REQUEST)
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
+        assertStartupSession(stub)
+        verify(capability1, times(1)).createSession(any())
+
+        // Ensure a failed future is returned when missing fulfillment
+        val requestWithMissingFulfillment =
+            Request.newBuilder()
+                .setFulfillmentRequest(FulfillmentRequest.getDefaultInstance())
+                .build()
+        val exception =
+            assertFailsWith<StatusRuntimeException> {
+                futureStub.sendRequestFulfillment(requestWithMissingFulfillment).await()
             }
-        }
+        assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
+        assertThat(Status.fromThrowable(exception).description)
+            .isEqualTo(ERROR_NO_FULFILLMENT_REQUEST)
+
         server.shutdownNow()
     }
 
@@ -261,41 +244,33 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-                assertStartupSession(stub)
-                verify(capability1, times(1)).createSession(any())
 
-                val requestWithUnknownFulfillmentId =
-                    Request.newBuilder()
-                        .setFulfillmentRequest(
-                            FulfillmentRequest.newBuilder()
-                                .addFulfillments(
-                                    Fulfillment.newBuilder()
-                                        .setIdentifier("UNKNOWN_FULFILLMENT_ID")
-                                        .setSessionInfo(
-                                            SessionInfo.newBuilder()
-                                                .setIsNewSession(true)
-                                                .setSessionIdentifier(sessionId)
-                                        )
-                                )
-                        )
-                        .build()
-                val exception =
-                    assertFailsWith<StatusRuntimeException> {
-                        futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
-                    }
-                assertThat(Status.fromThrowable(exception).code)
-                    .isEqualTo(Status.Code.FAILED_PRECONDITION)
-                assertThat(Status.fromThrowable(exception).description)
-                    .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
+        assertStartupSession(stub)
+        verify(capability1, times(1)).createSession(any())
+
+        val requestWithUnknownFulfillmentId =
+            Request.newBuilder()
+                .setSessionIdentifier(sessionId)
+                .setFulfillmentRequest(
+                    FulfillmentRequest.newBuilder()
+                        .addFulfillments(
+                            Fulfillment.newBuilder().setIdentifier("UNKNOWN_FULFILLMENT_ID")
+                        ),
+                )
+                .build()
+        val exception =
+            assertFailsWith<StatusRuntimeException> {
+                futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
             }
-        }
+        assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
+        assertThat(Status.fromThrowable(exception).description)
+            .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
+
         server.shutdownNow()
     }
 
@@ -304,40 +279,30 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-                assertStartupSession(stub)
-                verify(capability1, times(1)).createSession(any())
 
-                val requestWithUnknownFulfillmentId =
-                    Request.newBuilder()
-                        .setFulfillmentRequest(
-                            FulfillmentRequest.newBuilder()
-                                .addFulfillments(
-                                    Fulfillment.newBuilder()
-                                        .setIdentifier(capabilityId)
-                                        .setSessionInfo(
-                                            SessionInfo.newBuilder()
-                                                .setIsNewSession(true)
-                                                .setSessionIdentifier("UNKNOWN_SESSION_ID")
-                                        )
-                                )
-                        )
-                        .build()
-                val exception =
-                    assertFailsWith<StatusRuntimeException> {
-                        futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
-                    }
-                assertThat(Status.fromThrowable(exception).code)
-                    .isEqualTo(Status.Code.FAILED_PRECONDITION)
-                assertThat(Status.fromThrowable(exception).description).isEqualTo(ERROR_NO_SESSION)
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
+        assertStartupSession(stub)
+        verify(capability1, times(1)).createSession(any())
+
+        val requestWithUnknownFulfillmentId =
+            Request.newBuilder()
+                .setSessionIdentifier("UNKNOWN_SESSION_ID")
+                .setFulfillmentRequest(
+                    FulfillmentRequest.newBuilder()
+                        .addFulfillments(Fulfillment.newBuilder().setIdentifier(capabilityId)),
+                )
+                .build()
+        val exception =
+            assertFailsWith<StatusRuntimeException> {
+                futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
             }
-        }
+        assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
+        assertThat(Status.fromThrowable(exception).description).isEqualTo(ERROR_NO_SESSION)
+
         server.shutdownNow()
     }
 
@@ -346,34 +311,33 @@
         val server =
             createInProcessServer(
                 AppInteractionServiceGrpcImpl(FakeAppInteractionService(listOf(capability1))),
-                remoteViewsInterceptor
+                remoteViewsInterceptor,
             )
-        coroutineScope {
-            launch {
-                val channel = createInProcessChannel()
-                val stub = AppInteractionServiceGrpc.newStub(channel)
-                val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
 
-                // Verify capability session is created
-                val mockSession = createMockSession()
-                whenever(mockSession.status).thenReturn(ActionCapabilitySession.Status.COMPLETED)
-                whenever(capability1.createSession(any())).thenReturn(mockSession)
-                assertStartupSession(stub)
-                verify(capability1, times(1)).createSession(any())
+        val channel = createInProcessChannel()
+        val stub = AppInteractionServiceGrpc.newStub(channel)
+        val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
 
-                // Send request to completed session.
-                val requestToEndedSession =
-                    Request.newBuilder().setFulfillmentRequest(testFulfillmentRequest).build()
-                val exception =
-                    assertFailsWith<StatusRuntimeException> {
-                        futureStub.sendRequestFulfillment(requestToEndedSession).await()
-                    }
-                assertThat(Status.fromThrowable(exception).code)
-                    .isEqualTo(Status.Code.FAILED_PRECONDITION)
-                assertThat(Status.fromThrowable(exception).description)
-                    .isEqualTo(ERROR_SESSION_ENDED)
+        // Verify capability session is created
+        val mockSession = createMockSession()
+        whenever(mockSession.status).thenReturn(ActionCapabilitySession.Status.COMPLETED)
+        whenever(capability1.createSession(any())).thenReturn(mockSession)
+        assertStartupSession(stub)
+        verify(capability1, times(1)).createSession(any())
+
+        // Send request to completed session.
+        val requestToEndedSession =
+            Request.newBuilder()
+                .setSessionIdentifier(sessionId)
+                .setFulfillmentRequest(testFulfillmentRequest)
+                .build()
+        val exception =
+            assertFailsWith<StatusRuntimeException> {
+                futureStub.sendRequestFulfillment(requestToEndedSession).await()
             }
-        }
+        assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
+        assertThat(Status.fromThrowable(exception).description).isEqualTo(ERROR_SESSION_ENDED)
+
         server.shutdownNow()
     }
 
@@ -403,20 +367,20 @@
     @Throws(IOException::class)
     private fun createInProcessServer(
         service: BindableService,
-        vararg interceptors: ServerInterceptor
+        vararg interceptors: ServerInterceptor,
     ): Server {
         return grpcCleanup.register(
             InProcessServerBuilder.forName(testServerName)
                 .directExecutor()
                 .addService(ServerInterceptors.intercept(service, *interceptors))
                 .build()
-                .start()
+                .start(),
         )
     }
 
     private fun createInProcessChannel(): ManagedChannel {
         return grpcCleanup.register(
-            InProcessChannelBuilder.forName(testServerName).directExecutor().build()
+            InProcessChannelBuilder.forName(testServerName).directExecutor().build(),
         )
     }
 
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt
index bf2888f..4cf3bbe 100644
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt
+++ b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt
@@ -57,7 +57,7 @@
 
     @Test
     fun unreadUiResponseFlag_lifecycle() {
-        val uiCache = UiCache(capabilitySession)
+        val uiCache = UiCache()
         assertThat(uiCache.hasUnreadUiResponse()).isFalse()
 
         // Test set unread flag.
@@ -72,7 +72,7 @@
 
     @Test
     fun remoteViewsUiResponse_noFactoryNoChangedViews() {
-        val uiCache = UiCache(capabilitySession)
+        val uiCache = UiCache()
         assertEmptyCache(uiCache)
 
         uiCache.updateUiInternal(remoteViewsUiResponse)
@@ -85,7 +85,7 @@
 
     @Test
     fun remoteViewsUiResponse_withFactory() {
-        val uiCache = UiCache(capabilitySession)
+        val uiCache = UiCache()
         assertEmptyCache(uiCache)
 
         uiCache.updateUiInternal(remoteViewsUiResponseWithFactory)
@@ -97,7 +97,7 @@
 
     @Test
     fun remoteViewsUiResponse_withChangeView() {
-        val uiCache = UiCache(capabilitySession)
+        val uiCache = UiCache()
         assertEmptyCache(uiCache)
 
         uiCache.updateUiInternal(remoteViewsUiResponseWithChangeId)
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
index 0aefa0f..1ed52d5 100644
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
+++ b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
@@ -22,19 +22,29 @@
 import androidx.appactions.interaction.capabilities.core.ActionExecutor
 import androidx.appactions.interaction.capabilities.core.BaseSession
 import androidx.appactions.interaction.capabilities.core.ExecutionResult
+import androidx.appactions.interaction.capabilities.core.impl.ActionCapabilitySession
 import androidx.appactions.interaction.service.test.R
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.wear.tiles.LayoutElementBuilders
 import androidx.wear.tiles.ResourceBuilders
 import com.google.common.truth.Truth.assertThat
+import com.nhaarman.mockitokotlin2.doReturn
+import com.nhaarman.mockitokotlin2.mock
+import org.junit.After
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
 class UiSessionsTest {
 
-    private val capabilitySession = object : BaseSession<String, String> {}
+    private val externalSession = object : BaseSession<String, String> {}
+    private val actionCapabilitySession = mock<ActionCapabilitySession>() {
+        on { this.uiHandle } doReturn(externalSession)
+    }
+    private val sessionId = "fakeSessionId"
+
     private val context: Context = ApplicationProvider.getApplicationContext()
     private val remoteViewsFactoryId = 123
     private val changeViewId = 111
@@ -52,24 +62,34 @@
                     .addContent(
                         LayoutElementBuilders.Column.Builder()
                             .addContent(
-                                LayoutElementBuilders.Text.Builder().setText("LA8JE92").build()
+                                LayoutElementBuilders.Text.Builder().setText("LA8JE92").build(),
                             )
-                            .build()
+                            .build(),
                     )
-                    .build()
+                    .build(),
             )
             .build()
     private val resources = ResourceBuilders.Resources.Builder().setVersion("1234").build()
     private val tileLayoutUiResponse: UiResponse =
         UiResponse.TileLayoutBuilder().setTileLayout(layout, resources).build()
 
+    @Before
+    fun setup() {
+        SessionManager.putSession(sessionId, actionCapabilitySession)
+    }
+    @After
+    fun cleanup() {
+        UiSessions.removeUiCache(sessionId)
+        SessionManager.removeSession(sessionId)
+    }
+
     @Test
     fun sessionExtensionMethod_createsCache() {
-        assertThat(UiSessions.getUiCacheOrNull(capabilitySession)).isNull()
+        assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
 
-        capabilitySession.updateUi(remoteViewsUiResponse)
+        externalSession.updateUi(remoteViewsUiResponse)
 
-        val uiCache = UiSessions.getUiCacheOrNull(capabilitySession)
+        val uiCache = UiSessions.getUiCacheOrNull(sessionId)
         assertThat(uiCache).isNotNull()
         assertThat(uiCache?.hasUnreadUiResponse()).isTrue()
         assertThat(uiCache?.cachedChangedViewIds).containsExactly(changeViewId)
@@ -79,46 +99,56 @@
 
     @Test
     fun removeUiCache_removesWhatWasPreviouslyCreated() {
-        assertThat(UiSessions.getUiCacheOrNull(capabilitySession)).isNull()
+        assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
 
         // Invoke extension method.
-        capabilitySession.updateUi(remoteViewsUiResponse)
+        externalSession.updateUi(remoteViewsUiResponse)
 
-        val uiCache = UiSessions.getUiCacheOrNull(capabilitySession)
+        val uiCache = UiSessions.getUiCacheOrNull(sessionId)
         assertThat(uiCache).isNotNull()
         assertThat(uiCache?.hasUnreadUiResponse()).isTrue()
 
         // Test removing.
-        assertThat(UiSessions.removeUiCache(capabilitySession)).isTrue()
-        assertThat(UiSessions.getUiCacheOrNull(capabilitySession)).isNull()
+        assertThat(UiSessions.removeUiCache(sessionId)).isTrue()
+        assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
     }
 
     @Test
     fun getOrCreateUiCache_explicitTest() {
-        val uiCache = UiSessions.getOrCreateUiCache(capabilitySession)
+        val uiCache = UiSessions.getOrCreateUiCache(sessionId)
         assertThat(uiCache).isNotNull()
 
         // Calling a second time does not create a new cache instance.
-        val uiCache2 = UiSessions.getOrCreateUiCache(capabilitySession)
+        val uiCache2 = UiSessions.getOrCreateUiCache(sessionId)
         assertThat(uiCache).isEqualTo(uiCache2)
     }
 
     @Test
     fun multipleSession_haveTheirOwnCache() {
-        val capabilitySession1 = object : BaseSession<String, String> {}
-        val capabilitySession2 = object : BaseSession<String, String> {}
+        val externalSession1 = object : BaseSession<String, String> {}
+        val capabilitySession1 = mock<ActionCapabilitySession> {
+            on { this.uiHandle } doReturn(externalSession1)
+        }
+        val sessionId1 = "fakeSessionId1"
+        val externalSession2 = object : BaseSession<String, String> {}
+        val capabilitySession2 = mock<ActionCapabilitySession> {
+            on { this.uiHandle } doReturn(externalSession2)
+        }
+        val sessionId2 = "fakeSessionId2"
+        SessionManager.putSession(sessionId1, capabilitySession1)
+        SessionManager.putSession(sessionId2, capabilitySession2)
 
-        capabilitySession1.updateUi(remoteViewsUiResponse)
+        externalSession1.updateUi(remoteViewsUiResponse)
 
-        val uiCache1 = UiSessions.getUiCacheOrNull(capabilitySession1)
+        val uiCache1 = UiSessions.getUiCacheOrNull(sessionId1)
         assertThat(uiCache1).isNotNull()
         assertThat(uiCache1?.hasUnreadUiResponse()).isTrue()
         assertThat(uiCache1?.cachedRemoteViews).isEqualTo(remoteViews)
         assertThat(uiCache1?.cachedTileLayout).isNull()
 
-        capabilitySession2.updateUi(tileLayoutUiResponse)
+        externalSession2.updateUi(tileLayoutUiResponse)
 
-        val uiCache2 = UiSessions.getUiCacheOrNull(capabilitySession2)
+        val uiCache2 = UiSessions.getUiCacheOrNull(sessionId2)
         assertThat(uiCache2).isNotNull()
         assertThat(uiCache2?.hasUnreadUiResponse()).isTrue()
         assertThat(uiCache2?.cachedTileLayout).isNotNull()
@@ -128,6 +158,9 @@
         uiCache1?.resetUnreadUiResponse()
         assertThat(uiCache2?.hasUnreadUiResponse()).isTrue()
         assertThat(uiCache2?.cachedTileLayout).isNotNull()
+
+        SessionManager.removeSession(sessionId1)
+        SessionManager.removeSession(sessionId2)
     }
 
     @Test
@@ -135,14 +168,21 @@
         val actionExecutor = ActionExecutor<String, String> {
             ExecutionResult.getDefaultInstance()
         }
+        val session = mock<ActionCapabilitySession> {
+            on { this.uiHandle } doReturn(actionExecutor)
+        }
+        val sessionId = "actionExecutorSessionId"
+        SessionManager.putSession(sessionId, session)
 
         actionExecutor.updateUi(remoteViewsUiResponse)
 
-        val uiCache = UiSessions.getUiCacheOrNull(actionExecutor)
+        val uiCache = UiSessions.getUiCacheOrNull(sessionId)
         assertThat(uiCache).isNotNull()
         assertThat(uiCache?.hasUnreadUiResponse()).isTrue()
         assertThat(uiCache?.cachedChangedViewIds).containsExactly(changeViewId)
         assertThat(uiCache?.cachedRemoteViewsSize).isEqualTo(SizeF(10f, 15f))
         assertThat(uiCache?.cachedRemoteViews).isEqualTo(remoteViews)
+
+        SessionManager.removeSession(sessionId)
     }
 }
diff --git a/appcompat/OWNERS b/appcompat/OWNERS
index 43a6878..880f490 100644
--- a/appcompat/OWNERS
+++ b/appcompat/OWNERS
@@ -1,6 +1,10 @@
 # Bug component: 461199
 clarabayarri@google.com
 
+# For UI
+aelias@google.com
+ryanmentley@google.com
+
 # For text related files
 nona@google.com
 siyamed@google.com
diff --git a/appcompat/appcompat/build.gradle b/appcompat/appcompat/build.gradle
index b381126..80e9dfd 100644
--- a/appcompat/appcompat/build.gradle
+++ b/appcompat/appcompat/build.gradle
@@ -30,7 +30,7 @@
     api("androidx.drawerlayout:drawerlayout:1.0.0")
     implementation(projectOrArtifact(":lifecycle:lifecycle-runtime"))
     implementation("androidx.lifecycle:lifecycle-viewmodel:2.5.1")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
     implementation("androidx.resourceinspection:resourceinspection-annotation:1.0.1")
     api("androidx.savedstate:savedstate:1.2.1")
 
diff --git a/appsearch/appsearch-local-storage/src/androidTest/java/androidx/appsearch/localstorage/AppSearchImplTest.java b/appsearch/appsearch-local-storage/src/androidTest/java/androidx/appsearch/localstorage/AppSearchImplTest.java
index 4fef3f4..63bba79 100644
--- a/appsearch/appsearch-local-storage/src/androidTest/java/androidx/appsearch/localstorage/AppSearchImplTest.java
+++ b/appsearch/appsearch-local-storage/src/androidTest/java/androidx/appsearch/localstorage/AppSearchImplTest.java
@@ -78,6 +78,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -938,6 +939,7 @@
         assertThat(suggestions.get(1).getSuggestedResult()).isEqualTo("term2");
     }
 
+    @Ignore("b/273733335")
     @Test
     public void testSearchSuggestion_invalidPrefix() throws Exception {
         // Insert schema just put something in the AppSearch to make it searchable.
diff --git a/benchmark/baseline-profile-gradle-plugin/build.gradle b/benchmark/baseline-profile-gradle-plugin/build.gradle
index 3fe8fa6..ebf6019 100644
--- a/benchmark/baseline-profile-gradle-plugin/build.gradle
+++ b/benchmark/baseline-profile-gradle-plugin/build.gradle
@@ -62,7 +62,7 @@
 
 androidx {
     name = "Android Baseline Profile Gradle Plugin"
-    publish = Publish.SNAPSHOT_ONLY
+    publish = Publish.SNAPSHOT_AND_RELEASE
     type = LibraryType.GRADLE_PLUGIN
     inceptionYear = "2022"
     description = "Android Baseline Profile Gradle Plugin"
diff --git a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPlugin.kt b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPlugin.kt
index db9d280..c0d95dd 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPlugin.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPlugin.kt
@@ -89,7 +89,7 @@
         // They're named `<BUILD_TYPE_BASELINE_PROFILE_PREFIX><originalBuildTypeName>`.
         createExtendedBuildTypes(
             project = project,
-            extension = extension,
+            extensionBuildTypes = extension.buildTypes,
             newBuildTypePrefix = BUILD_TYPE_BASELINE_PROFILE_PREFIX,
             filterBlock = {
                 // Create baseline profile build types only for non debuggable builds.
diff --git a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPlugin.kt b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPlugin.kt
index dd17b89..cb98bc2 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPlugin.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPlugin.kt
@@ -281,6 +281,8 @@
                                 .variant(variant)
                                 .automaticGenerationDuringBuild
 
+                            // TODO: this causes a circular task dependency when the producer points
+                            //  to a consumer that does not have the appTarget plugin. (b/272851616)
                             if (automaticGeneration) {
                                 it.dependsOn(copyTaskProvider)
                             } else {
diff --git a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPlugin.kt b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPlugin.kt
index fb31417..a7cb238 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPlugin.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPlugin.kt
@@ -107,6 +107,24 @@
             enableAndroidTestCoverage = false
             enableUnitTestCoverage = false
             signingConfig = extension.buildTypes.getByName("debug").signingConfig
+
+            // TODO: The matching fallback is causing a circular dependency when app target plugin
+            //  is not applied. Normally this is not used, but if an app defines only the consumer
+            //  plugin the `nonMinified` build won't exist. If the provider points to it, the
+            //  matching fallback will kick in and will use the `release` build instead of the
+            //  `nonMinifiedRelease`. When this happens, since  we depend on
+            //  `mergeArtReleaseProfile` to ensure that a profile is copied is the baseline profile
+            //  src sets before the build is complete, it will trigger a circular task dependency:
+            //      collectNonMinifiedReleaseBaselineProfile ->
+            //          connectedNonMinifiedReleaseAndroidTest ->
+            //              packageRelease ->
+            //                  compileReleaseArtProfile ->
+            //                      mergeReleaseArtProfile ->
+            //                          copyReleaseBaselineProfileIntoSrc ->
+            //                              mergeReleaseBaselineProfile ->
+            //                                  collectNonMinifiedReleaseBaselineProfile
+            //  Note that the error is expected but we should handle it gracefully with proper
+            //  explanation. (b/272851616)
             matchingFallbacks += listOf(RELEASE)
         }
 
@@ -118,7 +136,7 @@
         // flavors, so that the same variant names are created.
         createExtendedBuildTypes(
             project = project,
-            extension = extension,
+            extensionBuildTypes = extension.buildTypes,
             newBuildTypePrefix = BUILD_TYPE_BASELINE_PROFILE_PREFIX,
             extendedBuildTypeToOriginalBuildTypeMapping = extendedTypeToOriginalTypeMapping,
             configureBlock = configureBlock,
@@ -131,7 +149,7 @@
         )
         createBuildTypeIfNotExists(
             project = project,
-            extension = extension,
+            extensionBuildTypes = extension.buildTypes,
             buildTypeName = nonObfuscatedReleaseName,
             configureBlock = configureBlock
         )
diff --git a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt
index 3926416..5b8181c 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt
@@ -16,19 +16,19 @@
 package androidx.baselineprofile.gradle.utils
 
 import com.android.build.api.dsl.BuildType
-import com.android.build.api.dsl.CommonExtension
 import org.gradle.api.GradleException
+import org.gradle.api.NamedDomainObjectContainer
 import org.gradle.api.Project
 
 internal inline fun <reified T : BuildType> createExtendedBuildTypes(
     project: Project,
-    extension: CommonExtension<*, T, *, *>,
+    extensionBuildTypes: NamedDomainObjectContainer<out T>,
     newBuildTypePrefix: String,
     crossinline filterBlock: (T) -> (Boolean),
     crossinline configureBlock: T.() -> (Unit),
     extendedBuildTypeToOriginalBuildTypeMapping: MutableMap<String, String> = mutableMapOf()
 ) {
-    extension.buildTypes.filter { buildType ->
+    extensionBuildTypes.filter { buildType ->
             if (buildType !is T) {
                 throw GradleException(
                     "Build type `${buildType.name}` is not of type ${T::class}"
@@ -40,14 +40,14 @@
             val newBuildTypeName = camelCase(newBuildTypePrefix, buildType.name)
 
             // Check in case the build type was created manually (to allow full customization)
-            if (extension.buildTypes.findByName(newBuildTypeName) != null) {
+            if (extensionBuildTypes.findByName(newBuildTypeName) != null) {
                 project.logger.info(
                     "Build type $newBuildTypeName won't be created because already exists."
                 )
             } else {
                 // If the new build type doesn't exist, create it simply extending the configured
                 // one (by default release).
-                extension.buildTypes.create(newBuildTypeName).apply {
+                extensionBuildTypes.create(newBuildTypeName).apply {
                     initWith(buildType)
                     matchingFallbacks += listOf(buildType.name)
                     configureBlock(this as T)
@@ -60,12 +60,12 @@
 
 internal inline fun <reified T : BuildType> createBuildTypeIfNotExists(
     project: Project,
-    extension: CommonExtension<*, T, *, *>,
+    extensionBuildTypes: NamedDomainObjectContainer<out T>,
     buildTypeName: String,
     crossinline configureBlock: T.() -> (Unit),
 ) {
     // Check in case the build type was created manually (to allow full customization)
-    if (extension.buildTypes.findByName(buildTypeName) != null) {
+    if (extensionBuildTypes.findByName(buildTypeName) != null) {
         project.logger.info(
             "Build type $buildTypeName won't be created because already exists."
         )
@@ -73,7 +73,7 @@
     }
     // If the new build type doesn't exist, create it simply extending the configured
     // one (by default release).
-    extension.buildTypes.create(buildTypeName).apply {
+    extensionBuildTypes.create(buildTypeName).apply {
         configureBlock(this)
     }
 }
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPluginTest.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPluginTest.kt
index ed34636..205a7b5 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPluginTest.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/apptarget/BaselineProfileAppTargetPluginTest.kt
@@ -16,11 +16,8 @@
 
 package androidx.baselineprofile.gradle.apptarget
 
-import androidx.baselineprofile.gradle.utils.GRADLE_CODE_PRINT_TASK
-import androidx.testutils.gradle.ProjectSetupRule
-import com.google.common.truth.Truth.assertThat
-import org.gradle.testkit.runner.GradleRunner
-import org.junit.Before
+import androidx.baselineprofile.gradle.utils.BaselineProfileProjectSetupRule
+import androidx.baselineprofile.gradle.utils.buildAndAssertThatOutput
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -30,66 +27,45 @@
 class BaselineProfileAppTargetPluginTest {
 
     @get:Rule
-    val projectSetup = ProjectSetupRule()
-
-    private lateinit var gradleRunner: GradleRunner
-
-    @Before
-    fun setUp() {
-        gradleRunner = GradleRunner.create()
-            .withProjectDir(projectSetup.rootDir)
-            .withPluginClasspath()
-    }
+    val projectSetup = BaselineProfileProjectSetupRule()
 
     @Test
     fun verifyBuildTypes() {
-        projectSetup.writeDefaultBuildGradle(
-            prefix = """
-                plugins {
-                    id("com.android.application")
-                    id("androidx.baselineprofile.apptarget")
-                }
-                android {
-                    namespace 'com.example.namespace'
-                    buildTypes {
-                        anotherRelease { initWith(release) }
-                    }
-                }
-
-                $GRADLE_CODE_PRINT_TASK
-
-                def registerTask(buildTypeName, taskName) {
-                    tasks.register(taskName, PrintTask) { t ->
-                        def buildType = android.buildTypes[buildTypeName]
-                        def text = "minifyEnabled=" + buildType.minifyEnabled.toString() + "\n"
-                        text += "testCoverageEnabled=" + buildType.testCoverageEnabled.toString() + "\n"
-                        text += "debuggable=" + buildType.debuggable.toString() + "\n"
-                        text += "profileable=" + buildType.profileable.toString() + "\n"
-                        t.text.set(text)
-                    }
-                }
-                registerTask("nonMinifiedRelease", "printNonMinifiedReleaseBuildType")
-                registerTask("nonMinifiedAnotherRelease", "printNonMinifiedAnotherReleaseBuildType")
-            """.trimIndent(),
-            suffix = ""
-        )
-
-        val runGradleAndAssertOutput: (String, (String) -> (Unit)) -> (Unit) =
-            { taskName, assertBlock ->
-                gradleRunner
-                    .withArguments(taskName, "--stacktrace")
-                    .build()
-                    .output
-                    .let(assertBlock)
+        projectSetup.appTarget.setBuildGradle(
+            """
+            plugins {
+                id("com.android.application")
+                id("androidx.baselineprofile.apptarget")
             }
+            android {
+                namespace 'com.example.namespace'
+                buildTypes {
+                    anotherRelease { initWith(release) }
+                }
+            }
+
+            def registerTask(buildTypeName, taskName) {
+                tasks.register(taskName, PrintTask) { t ->
+                    def buildType = android.buildTypes[buildTypeName]
+                    def text = "minifyEnabled=" + buildType.minifyEnabled.toString() + "\n"
+                    text += "testCoverageEnabled=" + buildType.testCoverageEnabled.toString() + "\n"
+                    text += "debuggable=" + buildType.debuggable.toString() + "\n"
+                    text += "profileable=" + buildType.profileable.toString() + "\n"
+                    t.text.set(text)
+                }
+            }
+            registerTask("nonMinifiedRelease", "printNonMinifiedReleaseBuildType")
+            registerTask("nonMinifiedAnotherRelease", "printNonMinifiedAnotherReleaseBuildType")
+            """.trimIndent()
+        )
 
         arrayOf("printNonMinifiedReleaseBuildType", "printNonMinifiedAnotherReleaseBuildType")
             .forEach { taskName ->
-                runGradleAndAssertOutput(taskName) {
-                    assertThat(it).contains("minifyEnabled=false")
-                    assertThat(it).contains("testCoverageEnabled=false")
-                    assertThat(it).contains("debuggable=false")
-                    assertThat(it).contains("profileable=true")
+                projectSetup.appTarget.gradleRunner.buildAndAssertThatOutput(taskName) {
+                    contains("minifyEnabled=false")
+                    contains("testCoverageEnabled=false")
+                    contains("debuggable=false")
+                    contains("profileable=true")
                 }
             }
     }
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPluginTest.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPluginTest.kt
index f688f3b..d5974d9 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPluginTest.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/consumer/BaselineProfileConsumerPluginTest.kt
@@ -16,11 +16,15 @@
 
 package androidx.baselineprofile.gradle.consumer
 
+import androidx.baselineprofile.gradle.utils.ANDROID_APPLICATION_PLUGIN
+import androidx.baselineprofile.gradle.utils.ANDROID_LIBRARY_PLUGIN
+import androidx.baselineprofile.gradle.utils.ANDROID_TEST_PLUGIN
 import androidx.baselineprofile.gradle.utils.BaselineProfileProjectSetupRule
-import androidx.baselineprofile.gradle.utils.CONFIGURATION_NAME_BASELINE_PROFILES
+import androidx.baselineprofile.gradle.utils.Fixtures
+import androidx.baselineprofile.gradle.utils.VariantProfile
 import androidx.baselineprofile.gradle.utils.build
 import androidx.baselineprofile.gradle.utils.buildAndAssertThatOutput
-import androidx.baselineprofile.gradle.utils.camelCase
+import androidx.baselineprofile.gradle.utils.buildAndFailAndAssertThatOutput
 import com.google.common.truth.Truth.assertThat
 import java.io.File
 import org.junit.Rule
@@ -37,18 +41,15 @@
 
     companion object {
         private const val EXPECTED_PROFILE_FOLDER = "generated/baselineProfiles"
-        private const val ANDROID_APPLICATION_PLUGIN = "com.android.application"
-        private const val ANDROID_LIBRARY_PLUGIN = "com.android.library"
-        private const val ANDROID_TEST_PLUGIN = "com.android.test"
     }
 
     @get:Rule
-    val projectSetupRule = BaselineProfileProjectSetupRule()
+    val projectSetup = BaselineProfileProjectSetupRule()
 
-    private val gradleRunner by lazy { projectSetupRule.consumer.gradleRunner }
+    private val gradleRunner by lazy { projectSetup.consumer.gradleRunner }
 
     private fun baselineProfileFile(variantName: String) = File(
-        projectSetupRule.consumer.rootDir,
+        projectSetup.consumer.rootDir,
         "src/$variantName/$EXPECTED_PROFILE_FOLDER/baseline-prof.txt"
     )
 
@@ -57,14 +58,24 @@
 
     @Test
     fun testGenerateTaskWithNoFlavors() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_LIBRARY_PLUGIN,
             dependencyOnProducerProject = true,
             flavors = false
         )
-        setupProducerProject(
-            listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
-            listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2)
+        projectSetup.producer.setup(
+            variantProfiles = listOf(
+                VariantProfile(
+                    flavor = null,
+                    buildType = "release",
+                    profileLines = listOf(
+                        Fixtures.CLASS_1_METHOD_1,
+                        Fixtures.CLASS_1,
+                        Fixtures.CLASS_2_METHOD_1,
+                        Fixtures.CLASS_2
+                    )
+                )
+            )
         )
 
         gradleRunner
@@ -82,12 +93,12 @@
 
     @Test
     fun testGenerateTaskWithFlavorsAndDefaultMerge() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             dependencyOnProducerProject = true
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
@@ -118,7 +129,7 @@
 
     @Test
     fun testGenerateTaskWithFlavorsAndMergeAll() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             dependencyOnProducerProject = true,
@@ -126,7 +137,7 @@
                 mergeIntoMain = true
             """.trimIndent()
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2)
         )
@@ -153,23 +164,9 @@
     }
 
     @Test
-    fun testPluginAppliedToApplicationModule() {
-        setupProducerProject()
-        setupConsumerProject(
-            androidPlugin = ANDROID_APPLICATION_PLUGIN,
-            addAppTargetPlugin = false,
-            dependencyOnProducerProject = true
-        )
-        gradleRunner
-            .withArguments("generateBaselineProfile", "--stacktrace")
-            .build()
-        // This should not fail.
-    }
-
-    @Test
     fun testPluginAppliedToLibraryModule() {
-        setupProducerProject()
-        setupConsumerProject(
+        projectSetup.producer.setup()
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_LIBRARY_PLUGIN,
             addAppTargetPlugin = false,
             dependencyOnProducerProject = true
@@ -182,8 +179,8 @@
 
     @Test
     fun testPluginAppliedToNonApplicationAndNonLibraryModule() {
-        setupProducerProject()
-        setupConsumerProject(
+        projectSetup.producer.setup()
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_TEST_PLUGIN,
             addAppTargetPlugin = false,
             dependencyOnProducerProject = true
@@ -196,12 +193,12 @@
 
     @Test
     fun testSrcSetAreAddedToVariants() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2)
         )
-        setupConsumerProject(
-            androidPlugin = "com.android.application",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             dependencyOnProducerProject = true,
             baselineProfileBlock = """
@@ -225,7 +222,7 @@
                 // not exist so we need to create it.
                 val expected =
                     File(
-                        projectSetupRule.consumer.rootDir,
+                        projectSetup.consumer.rootDir,
                         "src/$it/$EXPECTED_PROFILE_FOLDER"
                     )
                         .apply {
@@ -241,8 +238,8 @@
 
     @Test
     fun testWhenPluginIsAppliedAndNoDependencyIsSetShouldFailWithErrorMsg() {
-        setupConsumerProject(
-            androidPlugin = "com.android.application",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = false,
             dependencyOnProducerProject = false
         )
@@ -262,12 +259,12 @@
 
     @Test
     fun testR8RewriteBaselineProfilePropertySet() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2)
         )
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             dependencyOnProducerProject = true,
             flavors = true,
             buildTypeAnotherRelease = true,
@@ -299,8 +296,8 @@
 
     @Test
     fun testFilterAndSortAndMerge() {
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
                 filter {
@@ -308,7 +305,7 @@
                 }
             """.trimIndent()
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(
                 Fixtures.CLASS_1_METHOD_1,
                 Fixtures.CLASS_1_METHOD_2,
@@ -343,7 +340,7 @@
 
     @Test
     fun testSaveInSrcTrueAndAutomaticGenerationDuringBuildTrue() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
@@ -351,7 +348,7 @@
                 automaticGenerationDuringBuild = true
             """.trimIndent()
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
@@ -364,7 +361,7 @@
                 "mergeFreeReleaseArtProfile",
                 "compileFreeReleaseArtProfile",
                 "assembleFreeRelease"
-            ).forEach { contains(":${projectSetupRule.consumer.name}:$it") }
+            ).forEach { contains(":${projectSetup.consumer.name}:$it") }
         }
 
         // Asserts that the profile is generated in the src folder
@@ -379,7 +376,7 @@
 
     @Test
     fun testSaveInSrcTrueAndAutomaticGenerationDuringBuildFalse() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
@@ -387,7 +384,7 @@
                 automaticGenerationDuringBuild = false
             """.trimIndent()
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
@@ -397,12 +394,12 @@
             arrayOf(
                 "mergeFreeReleaseBaselineProfile",
                 "copyFreeReleaseBaselineProfileIntoSrc"
-            ).forEach { doesNotContain(":${projectSetupRule.consumer.name}:$it") }
+            ).forEach { doesNotContain(":${projectSetup.consumer.name}:$it") }
             arrayOf(
                 "mergeFreeReleaseArtProfile",
                 "compileFreeReleaseArtProfile",
                 "assembleFreeRelease"
-            ).forEach { contains(":${projectSetupRule.consumer.name}:$it") }
+            ).forEach { contains(":${projectSetup.consumer.name}:$it") }
         }
 
         // Asserts that the profile is generated in the src folder
@@ -417,7 +414,7 @@
 
     @Test
     fun testSaveInSrcFalseAndAutomaticGenerationDuringBuildTrue() {
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
@@ -425,7 +422,7 @@
                 automaticGenerationDuringBuild = true
             """.trimIndent()
         )
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
@@ -437,9 +434,9 @@
                 "mergeFreeReleaseArtProfile",
                 "compileFreeReleaseArtProfile",
                 "assembleFreeRelease"
-            ).forEach { contains(":${projectSetupRule.consumer.name}:$it") }
+            ).forEach { contains(":${projectSetup.consumer.name}:$it") }
             doesNotContain(
-                ":${projectSetupRule.consumer.name}:copyFreeReleaseBaselineProfileIntoSrc"
+                ":${projectSetup.consumer.name}:copyFreeReleaseBaselineProfileIntoSrc"
             )
         }
 
@@ -452,8 +449,8 @@
 
     @Test
     fun testSaveInSrcFalseAndAutomaticGenerationDuringBuildFalse() {
-        setupProducerProject()
-        setupConsumerProject(
+        projectSetup.producer.setup()
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             baselineProfileBlock = """
                 saveInSrc = false
@@ -476,16 +473,22 @@
 
     @Test
     fun testWhenFiltersFilterOutAllTheProfileRules() {
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             baselineProfileBlock = """
                 filter { include("nothing.**") }
             """.trimIndent()
         )
-        setupProducerProject(
-            releaseProfile = listOf(
-                Fixtures.CLASS_1_METHOD_1,
-                Fixtures.CLASS_1,
+        projectSetup.producer.setup(
+            variantProfiles = listOf(
+                VariantProfile(
+                    flavor = null,
+                    buildType = "release",
+                    profileLines = listOf(
+                        Fixtures.CLASS_1_METHOD_1,
+                        Fixtures.CLASS_1
+                    )
+                )
             )
         )
         gradleRunner
@@ -503,22 +506,32 @@
     }
 
     @Test
-    fun testWhenProfileProducerProducesEmptyArtifact() {
-        setupConsumerProject(androidPlugin = "com.android.library")
-        setupProducerProject(releaseProfile = listOf())
-        gradleRunner.buildAndAssertThatOutput("generateReleaseBaselineProfile") {
-            contains("No baseline profile rules were generated for the variant `release`")
+    fun testWhenProfileProducerProducesEmptyProfile() {
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN
+        )
+        projectSetup.producer.setup(
+            variantProfiles = listOf(
+                VariantProfile(
+                    flavor = null,
+                    buildType = "release",
+                    profileLines = listOf()
+                )
+            )
+        )
+        gradleRunner.buildAndFailAndAssertThatOutput("generateReleaseBaselineProfile") {
+            contains("No baseline profile found in test outputs.")
         }
     }
 
     @Test
     fun testVariantConfigurationOverrideForFlavors() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
 
@@ -573,12 +586,12 @@
 
     @Test
     fun testVariantConfigurationOverrideForBuildTypes() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
 
@@ -633,12 +646,12 @@
 
     @Test
     fun testVariantConfigurationOverrideForFlavorsAndBuildType() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
-        setupConsumerProject(
-            androidPlugin = "com.android.library",
+        projectSetup.consumer.setup(
+            androidPlugin = ANDROID_LIBRARY_PLUGIN,
             flavors = true,
             baselineProfileBlock = """
                 variants {
@@ -664,24 +677,24 @@
 
     @Test
     fun testVariantDependenciesWithFlavors() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
 
         // In this setup no dependency is being added through the dependency block.
         // Instead dependencies are being added through per-variant configuration block.
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             dependencyOnProducerProject = false,
             baselineProfileBlock = """
                 variants {
                     free {
-                        from(project(":${projectSetupRule.producer.name}"))
+                        from(project(":${projectSetup.producer.name}"))
                     }
                     paid {
-                        from(project(":${projectSetupRule.producer.name}"))
+                        from(project(":${projectSetup.producer.name}"))
                     }
                 }
 
@@ -705,24 +718,24 @@
 
     @Test
     fun testVariantDependenciesWithVariantsAndDirectConfiguration() {
-        setupProducerProjectWithFlavors(
+        projectSetup.producer.setupWithFreeAndPaidFlavors(
             freeReleaseProfileLines = listOf(Fixtures.CLASS_1_METHOD_1, Fixtures.CLASS_1),
             paidReleaseProfileLines = listOf(Fixtures.CLASS_2_METHOD_1, Fixtures.CLASS_2),
         )
 
         // In this setup no dependency is being added through the dependency block.
         // Instead dependencies are being added through per-variant configuration block.
-        setupConsumerProject(
+        projectSetup.consumer.setup(
             androidPlugin = ANDROID_APPLICATION_PLUGIN,
             flavors = true,
             dependencyOnProducerProject = false,
             baselineProfileBlock = """
                 variants {
                     freeRelease {
-                        from(project(":${projectSetupRule.producer.name}"))
+                        from(project(":${projectSetup.producer.name}"))
                     }
                     paidRelease {
-                        from(project(":${projectSetupRule.producer.name}"), "freeRelease")
+                        from(project(":${projectSetup.producer.name}"), "freeRelease")
                     }
                 }
 
@@ -745,207 +758,4 @@
                 Fixtures.CLASS_1_METHOD_1,
             )
     }
-
-    private fun setupConsumerProject(
-        androidPlugin: String,
-        flavors: Boolean = false,
-        dependencyOnProducerProject: Boolean = true,
-        buildTypeAnotherRelease: Boolean = false,
-        addAppTargetPlugin: Boolean = androidPlugin == ANDROID_APPLICATION_PLUGIN,
-        baselineProfileBlock: String = "",
-        additionalGradleCodeBlock: String = "",
-    ) {
-        val flavorsBlock = """
-            productFlavors {
-                flavorDimensions = ["version"]
-                free { dimension "version" }
-                paid { dimension "version" }
-            }
-
-        """.trimIndent()
-
-        val buildTypeAnotherReleaseBlock = """
-            buildTypes {
-                anotherRelease { initWith(release) }
-            }
-
-        """.trimIndent()
-
-        val dependencyOnProducerProjectBlock = """
-            dependencies {
-                baselineProfile(project(":${projectSetupRule.producer.name}"))
-            }
-
-        """.trimIndent()
-
-        projectSetupRule.consumer.setBuildGradle(
-            """
-                plugins {
-                    id("$androidPlugin")
-                    id("androidx.baselineprofile.consumer")
-                    ${if (addAppTargetPlugin) "id(\"androidx.baselineprofile.apptarget\")" else ""}
-                }
-                android {
-                    namespace 'com.example.namespace'
-                    ${if (flavors) flavorsBlock else ""}
-                    ${if (buildTypeAnotherRelease) buildTypeAnotherReleaseBlock else ""}
-                }
-
-               ${if (dependencyOnProducerProject) dependencyOnProducerProjectBlock else ""}
-
-                baselineProfile {
-                    $baselineProfileBlock
-                }
-
-                $additionalGradleCodeBlock
-
-            """.trimIndent()
-        )
-    }
-
-    private fun setupProducerProjectWithFlavors(
-        freeReleaseProfileLines: List<String>,
-        paidReleaseProfileLines: List<String>,
-    ) {
-        projectSetupRule.producer.setBuildGradle(
-            MockProducerBuildGrade()
-                .withProducedBaselineProfile(
-                    lines = freeReleaseProfileLines,
-                    flavorName = "free",
-                    buildType = "release",
-                    productFlavors = mapOf("version" to "free")
-                )
-                .withProducedBaselineProfile(
-                    lines = paidReleaseProfileLines,
-                    flavorName = "paid",
-                    buildType = "release",
-                    productFlavors = mapOf("version" to "paid")
-                )
-                .build()
-        )
-    }
-
-    private fun setupProducerProject(
-        releaseProfile: List<String> = listOf(
-            Fixtures.CLASS_1_METHOD_1,
-            Fixtures.CLASS_2_METHOD_2,
-            Fixtures.CLASS_2,
-            Fixtures.CLASS_1
-        ),
-        vararg additionalReleaseProfiles: List<String>
-    ) {
-        val mock = MockProducerBuildGrade()
-            .withProducedBaselineProfile(
-                lines = releaseProfile,
-                flavorName = "",
-                buildType = "release",
-                productFlavors = mapOf()
-            )
-        for (profile in additionalReleaseProfiles) {
-            mock.withProducedBaselineProfile(
-                lines = profile,
-                flavorName = "",
-                buildType = "release",
-                productFlavors = mapOf()
-            )
-        }
-        projectSetupRule.producer.setBuildGradle(mock.build())
-    }
 }
-
-private class MockProducerBuildGrade {
-
-    private var profileIndex = 0
-    private var content = """
-        plugins { id("com.android.library") }
-        android { namespace 'com.example.namespace' }
-
-        import com.android.build.api.attributes.BuildTypeAttr
-        import com.android.build.api.attributes.ProductFlavorAttr
-        import com.android.build.gradle.internal.attributes.VariantAttr
-        import androidx.baselineprofile.gradle.configuration.attribute.BaselineProfilePluginVersionAttr
-
-        // This task produces a file with a fixed output
-        abstract class TestProfileTask extends DefaultTask {
-            @Input abstract Property<String> getFileContent()
-            @OutputFile abstract RegularFileProperty getOutputFile()
-            @TaskAction void exec() { getOutputFile().get().asFile.write(getFileContent().get()) }
-        }
-
-    """.trimIndent()
-
-    fun withProducedBaselineProfile(
-        lines: List<String>,
-        productFlavors: Map<String, String>,
-        flavorName: String = "",
-        buildType: String
-    ): MockProducerBuildGrade {
-        val productFlavorAttributes = productFlavors.map { (name, value) ->
-            """
-            attribute(ProductFlavorAttr.of("$name"), objects.named(ProductFlavorAttr, "$value"))
-
-            """.trimIndent()
-        }.joinToString("\n")
-
-        content += """
-
-        configurations {
-            ${configurationName(flavorName, buildType)} {
-                canBeConsumed = true
-                canBeResolved = false
-                attributes {
-                    attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, "baselineProfile"))
-                    attribute(BuildTypeAttr.ATTRIBUTE, objects.named(BuildTypeAttr, "$buildType"))
-                    attribute(
-                        TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
-                        objects.named(TargetJvmEnvironment, "android")
-                    )
-                    attribute(
-                        BaselineProfilePluginVersionAttr.ATTRIBUTE,
-                        objects.named(BaselineProfilePluginVersionAttr, "alpha1")
-                    )
-
-                    $productFlavorAttributes
-                }
-            }
-        }
-
-        """.trimIndent()
-        profileIndex++
-        content += """
-
-        def task$profileIndex = tasks.register('testProfile$profileIndex', TestProfileTask)
-        task$profileIndex.configure {
-            it.outputFile.set(project.layout.buildDirectory.file("test$profileIndex"))
-            it.fileContent.set(${"\"\"\"${lines.joinToString("\n")}\"\"\""})
-        }
-        artifacts {
-            add("${
-            configurationName(
-                flavorName,
-                buildType
-            )
-        }", task$profileIndex.map { it.outputFile })
-        }
-
-        """.trimIndent()
-        return this
-    }
-
-    fun build() = content
-}
-
-private fun configurationName(flavor: String, buildType: String): String =
-    camelCase(flavor, buildType, CONFIGURATION_NAME_BASELINE_PROFILES)
-
-object Fixtures {
-    const val CLASS_1 = "Lcom/sample/Activity;"
-    const val CLASS_1_METHOD_1 = "HSPLcom/sample/Activity;-><init>()V"
-    const val CLASS_1_METHOD_2 = "HSPLcom/sample/Activity;->onCreate(Landroid/os/Bundle;)V"
-    const val CLASS_2 = "Lcom/sample/Utils;"
-    const val CLASS_2_METHOD_1 = "HSLcom/sample/Utils;-><init>()V"
-    const val CLASS_2_METHOD_2 = "HLcom/sample/Utils;->someMethod()V"
-    const val CLASS_2_METHOD_3 = "HLcom/sample/Utils;->someOtherMethod()V"
-    const val CLASS_2_METHOD_4 = "HSLcom/sample/Utils;->someOtherMethod()V"
-    const val CLASS_2_METHOD_5 = "HSPLcom/sample/Utils;->someOtherMethod()V"
-}
\ No newline at end of file
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPluginTest.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPluginTest.kt
index 354e899..18474e6 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPluginTest.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/producer/BaselineProfileProducerPluginTest.kt
@@ -17,7 +17,9 @@
 package androidx.baselineprofile.gradle.producer
 
 import androidx.baselineprofile.gradle.utils.BaselineProfileProjectSetupRule
-import com.google.common.truth.Truth.assertThat
+import androidx.baselineprofile.gradle.utils.VariantProfile
+import androidx.baselineprofile.gradle.utils.buildAndAssertThatOutput
+import androidx.baselineprofile.gradle.utils.buildAndFailAndAssertThatOutput
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -26,46 +28,73 @@
 @RunWith(JUnit4::class)
 class BaselineProfileProducerPluginTest {
 
-    // Unit test will be minimal because the producer plugin is applied to an android test module,
-    // that requires a working target application. Testing will be covered only by integration tests.
-
     @get:Rule
     val projectSetup = BaselineProfileProjectSetupRule()
 
+    private val emptyReleaseVariantProfile = VariantProfile(
+        flavor = null,
+        buildType = "release",
+        profileLines = listOf()
+    )
+
     @Test
     fun verifyTasksWithAndroidTestPlugin() {
-        projectSetup.appTarget.setBuildGradle(
-            """
-                plugins {
-                    id("com.android.application")
-                    id("androidx.baselineprofile.apptarget")
-                }
-                android {
-                    namespace 'com.example.namespace'
-                }
-            """.trimIndent()
+        projectSetup.appTarget.setup()
+        projectSetup.producer.setup(
+            variantProfiles = listOf(emptyReleaseVariantProfile),
+            targetProject = projectSetup.appTarget
         )
-        projectSetup.producer.setBuildGradle(
-            """
-                plugins {
-                    id("com.android.test")
-                    id("androidx.baselineprofile.producer")
-                }
-                android {
-                    targetProjectPath = ":${projectSetup.appTarget.name}"
-                    namespace 'com.example.namespace.test'
-                }
-                tasks.register("mergeNonMinifiedReleaseTestResultProtos") { println("Stub") }
+
+        projectSetup.producer.gradleRunner.buildAndAssertThatOutput("tasks") {
+            contains("connectedNonMinifiedReleaseAndroidTest - ")
+            contains("collectNonMinifiedReleaseBaselineProfile - ")
+        }
+    }
+
+    @Test
+    fun nonExistingManagedDeviceShouldThrowError() {
+        projectSetup.appTarget.setup()
+        projectSetup.producer.setup(
+            variantProfiles = listOf(emptyReleaseVariantProfile),
+            targetProject = projectSetup.appTarget,
+            managedDevices = listOf(),
+            baselineProfileBlock = """
+                managedDevices = ["nonExisting"]
             """.trimIndent()
         )
 
-        projectSetup.producer.gradleRunner
-            .withArguments("tasks", "--stacktrace")
-            .build()
-            .output
-            .let {
-                assertThat(it).contains("connectedNonMinifiedReleaseAndroidTest - ")
-                assertThat(it).contains("collectNonMinifiedReleaseBaselineProfile - ")
+        projectSetup.producer.gradleRunner.buildAndFailAndAssertThatOutput("tasks") {
+            contains("It wasn't possible to determine the test task for managed device")
+        }
+    }
+
+    @Test
+    fun existingManagedDeviceShouldCreateCollectTaskDependingOnManagedDeviceTask() {
+        projectSetup.appTarget.setup()
+        projectSetup.producer.setup(
+            variantProfiles = listOf(emptyReleaseVariantProfile),
+            targetProject = projectSetup.appTarget,
+            managedDevices = listOf("somePixelDevice"),
+            baselineProfileBlock = """
+                managedDevices = ["somePixelDevice"]
+            """.trimIndent()
+        )
+
+        projectSetup
+            .producer
+            .gradleRunner
+            .buildAndAssertThatOutput(
+                "collectNonMinifiedReleaseBaselineProfile",
+                "--dry-run"
+            ) {
+                contains(
+                    ":${projectSetup.appTarget.name}:packageNonMinifiedRelease")
+                contains(
+                    ":${projectSetup.producer.name}:somePixelDeviceNonMinifiedReleaseAndroidTest")
+                contains(
+                    ":${projectSetup.producer.name}:connectedNonMinifiedReleaseAndroidTest")
+                contains(
+                    ":${projectSetup.producer.name}:collectNonMinifiedReleaseBaselineProfile")
             }
     }
 }
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/BaselineProfileProjectSetupRule.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/BaselineProfileProjectSetupRule.kt
index aacf3c7..d0df57b 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/BaselineProfileProjectSetupRule.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/BaselineProfileProjectSetupRule.kt
@@ -17,7 +17,14 @@
 package androidx.baselineprofile.gradle.utils
 
 import androidx.testutils.gradle.ProjectSetupRule
+import com.google.testing.platform.proto.api.core.LabelProto
+import com.google.testing.platform.proto.api.core.PathProto
+import com.google.testing.platform.proto.api.core.TestArtifactProto
+import com.google.testing.platform.proto.api.core.TestResultProto
+import com.google.testing.platform.proto.api.core.TestStatusProto
+import com.google.testing.platform.proto.api.core.TestSuiteResultProto
 import java.io.File
+import org.gradle.configurationcache.extensions.capitalized
 import org.gradle.testkit.runner.GradleRunner
 import org.junit.rules.ExternalResource
 import org.junit.rules.RuleChain
@@ -25,18 +32,68 @@
 import org.junit.runner.Description
 import org.junit.runners.model.Statement
 
+internal const val ANDROID_APPLICATION_PLUGIN = "com.android.application"
+internal const val ANDROID_LIBRARY_PLUGIN = "com.android.library"
+internal const val ANDROID_TEST_PLUGIN = "com.android.test"
+
 class BaselineProfileProjectSetupRule : ExternalResource() {
 
+    /**
+     * Root folder for the project setup that contains 3 modules.
+     */
     val rootFolder = TemporaryFolder().also { it.create() }
 
+    /**
+     * Represents a module with the app target plugin applied.
+     */
+    val appTarget by lazy {
+        AppTargetModule(
+            rule = appTargetSetupRule,
+            name = appTargetName,
+        )
+    }
+
+    /**
+     * Represents a module with the consumer plugin applied.
+     */
+    val consumer by lazy {
+        ConsumerModule(
+            rule = consumerSetupRule,
+            name = consumerName,
+            producerName = producerName
+        )
+    }
+
+    /**
+     * Represents a module with the producer plugin applied.
+     */
+    val producer by lazy {
+        ProducerModule(
+            rule = producerSetupRule,
+            name = producerName,
+            tempFolder = tempFolder,
+            consumer = consumer
+        )
+    }
+
+    // Temp folder for temp generated files that need to be referenced by a module.
+    private val tempFolder by lazy { File(rootFolder.root, "temp").apply { mkdirs() } }
+
     // Project setup rules
     private val appTargetSetupRule by lazy { ProjectSetupRule(rootFolder.root) }
     private val consumerSetupRule by lazy { ProjectSetupRule(rootFolder.root) }
     private val producerSetupRule by lazy { ProjectSetupRule(rootFolder.root) }
 
-    val appTarget by lazy { Module(appTargetSetupRule, rootFolder) }
-    val consumer by lazy { Module(consumerSetupRule, rootFolder) }
-    val producer by lazy { Module(producerSetupRule, rootFolder) }
+    // Module names (generated automatically)
+    private val appTargetName: String by lazy {
+        appTargetSetupRule.rootDir.relativeTo(rootFolder.root).name
+    }
+    private val consumerName: String by lazy {
+        consumerSetupRule.rootDir.relativeTo(rootFolder.root).name
+    }
+    private val producerName: String by lazy {
+        producerSetupRule.rootDir.relativeTo(rootFolder.root).name
+    }
 
     override fun apply(base: Statement, description: Description): Statement {
         return RuleChain
@@ -53,9 +110,9 @@
             // Creates the main settings.gradle
             rootFolder.newFile("settings.gradle").writeText(
                 """
-                include '${appTarget.name}'
-                include '${producer.name}'
-                include '${consumer.name}'
+                include '$appTargetName'
+                include '$producerName'
+                include '$consumerName'
             """.trimIndent()
             )
 
@@ -75,20 +132,22 @@
     }
 }
 
-class Module internal constructor(
-    private val rule: ProjectSetupRule,
-    rootFolder: TemporaryFolder
+data class VariantProfile(
+    val flavor: String?,
+    val buildType: String = "release",
+    val profileLines: List<String> = listOf()
 ) {
+    val nonMinifiedVariant = "${flavor ?: ""}NonMinified${buildType.capitalized()}"
+}
 
-    val rootDir = rule.rootDir
-    val name: String = rule.rootDir.relativeTo(rootFolder.root).name
+interface Module {
 
-    val gradleRunner: GradleRunner by lazy {
-        GradleRunner
-            .create()
-            .withProjectDir(rule.rootDir)
-            .withPluginClasspath()
-    }
+    val name: String
+    val rule: ProjectSetupRule
+    val rootDir: File
+        get() = rule.rootDir
+    val gradleRunner: GradleRunner
+        get() = GradleRunner.create().withProjectDir(rule.rootDir).withPluginClasspath()
 
     fun setBuildGradle(buildGradleContent: String) =
         rule.writeDefaultBuildGradle(
@@ -98,3 +157,265 @@
             """.trimIndent()
         )
 }
+
+class AppTargetModule(
+    override val rule: ProjectSetupRule,
+    override val name: String,
+) : Module {
+
+    fun setup() {
+        setBuildGradle(
+            """
+                plugins {
+                    id("com.android.application")
+                    id("androidx.baselineprofile.apptarget")
+                }
+                android {
+                    namespace 'com.example.namespace'
+                }
+            """.trimIndent()
+        )
+    }
+}
+
+class ProducerModule(
+    override val rule: ProjectSetupRule,
+    override val name: String,
+    private val tempFolder: File,
+    private val consumer: Module
+) : Module {
+
+    fun setupWithFreeAndPaidFlavors(
+        freeReleaseProfileLines: List<String>,
+        paidReleaseProfileLines: List<String>,
+    ) {
+        setup(
+            variantProfiles = listOf(
+                VariantProfile(
+                    flavor = "free",
+                    buildType = "release",
+                    profileLines = freeReleaseProfileLines
+                ),
+                VariantProfile(
+                    flavor = "paid",
+                    buildType = "release",
+                    profileLines = paidReleaseProfileLines
+                ),
+            )
+        )
+    }
+
+    fun setup(
+        variantProfiles: List<VariantProfile> = listOf(
+            VariantProfile(
+                flavor = null,
+                buildType = "release",
+                profileLines = listOf(
+                    Fixtures.CLASS_1_METHOD_1,
+                    Fixtures.CLASS_2_METHOD_2,
+                    Fixtures.CLASS_2,
+                    Fixtures.CLASS_1
+                )
+            )
+        ),
+        baselineProfileBlock: String = "",
+        additionalGradleCodeBlock: String = "",
+        targetProject: Module = consumer,
+        managedDevices: List<String> = listOf()
+    ) {
+        val managedDevicesBlock = """
+            testOptions.managedDevices.devices {
+            ${
+            managedDevices.joinToString("\n") {
+                """
+                $it(ManagedVirtualDevice) {
+                    device = "Pixel 6"
+                    apiLevel = 31
+                    systemImageSource = "aosp"
+                }
+
+            """.trimIndent()
+            }
+        }
+            }
+        """.trimIndent()
+
+        val flavorsBlock = """
+            productFlavors {
+                flavorDimensions = ["version"]
+                ${
+            variantProfiles
+                .filter { !it.flavor.isNullOrBlank() }
+                .joinToString("\n") { " ${it.flavor} { dimension \"version\" } " }
+        }
+            }
+        """.trimIndent()
+
+        val buildTypesBlock = """
+            buildTypes {
+                ${
+            variantProfiles
+                .filter { it.buildType.isNotBlank() && it.buildType != "release" }
+                .joinToString("\n") { " ${it.buildType} { initWith(debug) } " }
+        }
+            }
+        """.trimIndent()
+
+        val disableConnectedAndroidTestsBlock = variantProfiles.joinToString("\n") {
+
+            // Creates a folder to use as results dir
+            val outputDir = File(tempFolder, it.nonMinifiedVariant).apply { mkdirs() }
+
+            // Writes the fake test result proto in it, with the given lines
+            writeFakeTestResultsProto(
+                outputDir = outputDir,
+                profileLines = it.profileLines
+            )
+
+            // Gradle script to injects a fake and disable the actual task execution for
+            // android test
+            """
+            afterEvaluate {
+                project.tasks.named("connected${it.nonMinifiedVariant.capitalized()}AndroidTest") {
+                    it.resultsDir.set(new File("${outputDir.absolutePath}"))
+                    onlyIf { false }
+                }
+            }
+
+                """.trimIndent()
+        }
+
+        setBuildGradle(
+            """
+                import com.android.build.api.dsl.ManagedVirtualDevice
+
+                plugins {
+                    id("com.android.test")
+                    id("androidx.baselineprofile.producer")
+                }
+
+                android {
+                    $flavorsBlock
+
+                    $buildTypesBlock
+
+                    $managedDevicesBlock
+
+                    namespace 'com.example.namespace.test'
+                    targetProjectPath = ":${targetProject.name}"
+                }
+
+                dependencies {
+                }
+
+                baselineProfile {
+                    $baselineProfileBlock
+                }
+
+                $disableConnectedAndroidTestsBlock
+
+                $additionalGradleCodeBlock
+
+            """.trimIndent()
+        )
+    }
+
+    private fun writeFakeTestResultsProto(
+        outputDir: File,
+        profileLines: List<String>
+    ) {
+
+        val generatedProfileFile = File
+            .createTempFile("fake-baseline-prof-", ".txt")
+            .apply { writeText(profileLines.joinToString(System.lineSeparator())) }
+
+        val testResultProto = TestResultProto.TestResult.newBuilder()
+            .addOutputArtifact(
+                TestArtifactProto.Artifact.newBuilder()
+                    .setLabel(
+                        LabelProto.Label.newBuilder()
+                            .setLabel("additionaltestoutput.benchmark.trace")
+                            .build()
+                    )
+                    .setSourcePath(
+                        PathProto.Path.newBuilder()
+                            .setPath(generatedProfileFile.absolutePath)
+                            .build()
+                    )
+                    .build()
+            )
+            .build()
+
+        val testSuiteResultProto = TestSuiteResultProto.TestSuiteResult.newBuilder()
+            .setTestStatus(TestStatusProto.TestStatus.PASSED)
+            .addTestResult(testResultProto)
+            .build()
+
+        File(outputDir, "test-result.pb")
+            .apply { outputStream().use { testSuiteResultProto.writeTo(it) } }
+    }
+}
+
+class ConsumerModule(
+    override val rule: ProjectSetupRule,
+    override val name: String,
+    private val producerName: String
+) : Module {
+
+    fun setup(
+        androidPlugin: String,
+        flavors: Boolean = false,
+        dependencyOnProducerProject: Boolean = true,
+        buildTypeAnotherRelease: Boolean = false,
+        addAppTargetPlugin: Boolean = androidPlugin == ANDROID_APPLICATION_PLUGIN,
+        baselineProfileBlock: String = "",
+        additionalGradleCodeBlock: String = "",
+    ) {
+        val flavorsBlock = """
+            productFlavors {
+                flavorDimensions = ["version"]
+                free { dimension "version" }
+                paid { dimension "version" }
+            }
+
+        """.trimIndent()
+
+        val buildTypeAnotherReleaseBlock = """
+            buildTypes {
+                anotherRelease { initWith(release) }
+            }
+
+        """.trimIndent()
+
+        val dependencyOnProducerProjectBlock = """
+            dependencies {
+                baselineProfile(project(":$producerName"))
+            }
+
+        """.trimIndent()
+
+        setBuildGradle(
+            """
+                plugins {
+                    id("$androidPlugin")
+                    id("androidx.baselineprofile.consumer")
+                    ${if (addAppTargetPlugin) "id(\"androidx.baselineprofile.apptarget\")" else ""}
+                }
+                android {
+                    namespace 'com.example.namespace'
+                    ${if (flavors) flavorsBlock else ""}
+                    ${if (buildTypeAnotherRelease) buildTypeAnotherReleaseBlock else ""}
+                }
+
+               ${if (dependencyOnProducerProject) dependencyOnProducerProjectBlock else ""}
+
+                baselineProfile {
+                    $baselineProfileBlock
+                }
+
+                $additionalGradleCodeBlock
+
+            """.trimIndent()
+        )
+    }
+}
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/Fixtures.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/Fixtures.kt
new file mode 100644
index 0000000..f9ee2d5c
--- /dev/null
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/Fixtures.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.baselineprofile.gradle.utils
+
+object Fixtures {
+    const val CLASS_1 = "Lcom/sample/Activity;"
+    const val CLASS_1_METHOD_1 = "HSPLcom/sample/Activity;-><init>()V"
+    const val CLASS_1_METHOD_2 = "HSPLcom/sample/Activity;->onCreate(Landroid/os/Bundle;)V"
+    const val CLASS_2 = "Lcom/sample/Utils;"
+    const val CLASS_2_METHOD_1 = "HSLcom/sample/Utils;-><init>()V"
+    const val CLASS_2_METHOD_2 = "HLcom/sample/Utils;->someMethod()V"
+    const val CLASS_2_METHOD_3 = "HLcom/sample/Utils;->someOtherMethod()V"
+    const val CLASS_2_METHOD_4 = "HSLcom/sample/Utils;->someOtherMethod()V"
+    const val CLASS_2_METHOD_5 = "HSPLcom/sample/Utils;->someOtherMethod()V"
+}
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/TestUtils.kt b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/TestUtils.kt
index 40a46ab..051778b 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/TestUtils.kt
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/kotlin/androidx/baselineprofile/gradle/utils/TestUtils.kt
@@ -36,9 +36,24 @@
         .let(block)
 }
 
+internal fun GradleRunner.buildAndFail(vararg arguments: String, block: (String) -> (Unit)) {
+    this
+        .withArguments(*arguments, "--stacktrace")
+        .buildAndFail()
+        .output
+        .let(block)
+}
+
 internal fun GradleRunner.buildAndAssertThatOutput(
     vararg arguments: String,
     assertBlock: StringSubject.() -> (Unit)
 ) {
     this.build(*arguments) { assertBlock(assertThat(it)) }
 }
+
+internal fun GradleRunner.buildAndFailAndAssertThatOutput(
+    vararg arguments: String,
+    assertBlock: StringSubject.() -> (Unit)
+) {
+    this.buildAndFail(*arguments) { assertBlock(assertThat(it)) }
+}
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/test-data/app-target/src/main/AndroidManifest.xml b/benchmark/baseline-profile-gradle-plugin/src/test/test-data/app-target/src/main/AndroidManifest.xml
index b28ade2..3908578 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/test-data/app-target/src/main/AndroidManifest.xml
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/test-data/app-target/src/main/AndroidManifest.xml
@@ -14,4 +14,9 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <application android:label="BaselineProfileApp">
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/baseline-profile-gradle-plugin/src/test/test-data/consumer/src/main/AndroidManifest.xml b/benchmark/baseline-profile-gradle-plugin/src/test/test-data/consumer/src/main/AndroidManifest.xml
index df45767..3c9246e 100644
--- a/benchmark/baseline-profile-gradle-plugin/src/test/test-data/consumer/src/main/AndroidManifest.xml
+++ b/benchmark/baseline-profile-gradle-plugin/src/test/test-data/consumer/src/main/AndroidManifest.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   Copyright 2019 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,4 +13,9 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
\ No newline at end of file
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <application android:label="BaselineProfileApp">
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/benchmark-common/api/public_plus_experimental_current.txt b/benchmark/benchmark-common/api/public_plus_experimental_current.txt
index 1d9e4cd..a5a3dc8 100644
--- a/benchmark/benchmark-common/api/public_plus_experimental_current.txt
+++ b/benchmark/benchmark-common/api/public_plus_experimental_current.txt
@@ -31,7 +31,7 @@
   @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalPerfettoCaptureApi {
   }
 
-  @RequiresApi(21) @androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi public final class PerfettoTrace {
+  @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, 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);
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 17134b9..95b10d3 100644
--- a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt
+++ b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt
@@ -33,7 +33,7 @@
 import kotlin.test.assertTrue
 
 @LargeTest
-@SdkSuppress(minSdkVersion = 21)
+@SdkSuppress(minSdkVersion = 23)
 @RunWith(AndroidJUnit4::class)
 class PerfettoHelperTest {
     @Before
diff --git a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoTraceTest.kt b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoTraceTest.kt
index 73d01c3..8eba619 100644
--- a/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoTraceTest.kt
+++ b/benchmark/benchmark-common/src/androidTest/java/androidx/benchmark/PerfettoTraceTest.kt
@@ -32,7 +32,7 @@
 @OptIn(ExperimentalPerfettoCaptureApi::class)
 @LargeTest
 @RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = 21)
+@SdkSuppress(minSdkVersion = 23)
 class PerfettoTraceTest {
     @Test
     fun record_basic() {
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
index 8cc6dde..26a4da0 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCapture.kt
@@ -42,13 +42,13 @@
  * @suppress
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-@RequiresApi(21)
+@RequiresApi(23)
 public class PerfettoCapture(
     /**
      * Bundled is available above API 28, but we default to using unbundled as well on API 29, as
      * ProcessStatsConfig.scan_all_processes_on_start isn't supported on the bundled version.
      */
-    unbundled: Boolean = Build.VERSION.SDK_INT in 21..29
+    unbundled: Boolean = Build.VERSION.SDK_INT <= 29
 ) {
 
     private val helper: PerfettoHelper = PerfettoHelper(unbundled)
@@ -98,7 +98,7 @@
      * Enables Perfetto SDK tracing in an app if present. Provides required binary dependencies to
      * the app if they're missing and the [provideBinariesIfMissing] parameter is set to `true`.
      */
-    @RequiresApi(Build.VERSION_CODES.R) // TODO(234351579): Support API < 30
+    @RequiresApi(30) // TODO(234351579): Support API < 30
     fun enableAndroidxTracingPerfetto(
         targetPackage: String,
         provideBinariesIfMissing: Boolean
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
index 9725c61..010cde4 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
@@ -28,7 +28,7 @@
 import androidx.benchmark.perfetto.PerfettoHelper.Companion.isAbiSupported
 
 /**
- * Wrapper for [PerfettoCapture] which does nothing below L.
+ * Wrapper for [PerfettoCapture] which does nothing below API 23.
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 class PerfettoCaptureWrapper {
@@ -36,7 +36,7 @@
     private val TRACE_ENABLE_PROP = "persist.traced.enable"
 
     init {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+        if (Build.VERSION.SDK_INT >= 23) {
             capture = PerfettoCapture()
         }
     }
@@ -52,16 +52,16 @@
         var inUse = false
     }
 
-    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+    @RequiresApi(23)
     private fun start(
         appTagPackages: List<String>,
         userspaceTracingPackage: String?
     ): Boolean {
         capture?.apply {
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            if (Build.VERSION.SDK_INT >= 23) {
                 Log.d(LOG_TAG, "Recording perfetto trace")
                 if (userspaceTracingPackage != null &&
-                    Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
+                    Build.VERSION.SDK_INT >= 30
                 ) {
                     val result = enableAndroidxTracingPerfetto(
                         targetPackage = userspaceTracingPackage,
@@ -76,7 +76,7 @@
         return true
     }
 
-    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+    @RequiresApi(23)
     private fun stop(traceLabel: String): String {
         return Outputs.writeFile(
             fileName = "${traceLabel}_${dateToFileName()}.perfetto-trace",
@@ -100,7 +100,7 @@
         block: () -> Unit
     ): String? {
         // skip if Perfetto not supported, or on Cuttlefish (where tracing doesn't work)
-        if (Build.VERSION.SDK_INT < 21 || !isAbiSupported()) {
+        if (Build.VERSION.SDK_INT < 23 || !isAbiSupported()) {
             block()
             return null
         }
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 e3a3d72..a2e8f73 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
@@ -37,7 +37,7 @@
  * @suppress
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-@RequiresApi(21)
+@RequiresApi(23)
 public class PerfettoHelper(
     private val unbundled: Boolean = Build.VERSION.SDK_INT < LOWEST_BUNDLED_VERSION_SUPPORTED
 ) {
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoTrace.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoTrace.kt
index 98ed9d8..5e2c29a 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoTrace.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoTrace.kt
@@ -20,7 +20,7 @@
 import androidx.test.platform.app.InstrumentationRegistry
 import java.io.File
 
-@RequiresApi(21)
+@RequiresApi(23)
 @ExperimentalPerfettoCaptureApi
 class PerfettoTrace(
     /**
diff --git a/benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/PerfettoTraceRule.kt b/benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/PerfettoTraceRule.kt
index aa35558..d8dcd99 100644
--- a/benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/PerfettoTraceRule.kt
+++ b/benchmark/benchmark-junit4/src/main/java/androidx/benchmark/junit4/PerfettoTraceRule.kt
@@ -87,7 +87,7 @@
     ): Statement = object : Statement() {
         override fun evaluate() {
             val thisPackage = InstrumentationRegistry.getInstrumentation().context.packageName
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            if (Build.VERSION.SDK_INT >= 23) {
                 val label = "${description.className}_${description.methodName}"
                 PerfettoTrace.record(
                     fileLabel = label,
diff --git a/benchmark/benchmark-macro/build.gradle b/benchmark/benchmark-macro/build.gradle
index d167114..e1f7240 100644
--- a/benchmark/benchmark-macro/build.gradle
+++ b/benchmark/benchmark-macro/build.gradle
@@ -60,7 +60,7 @@
 
     implementation(project(":benchmark:benchmark-common"))
     implementation("androidx.core:core:1.9.0")
-    implementation("androidx.profileinstaller:profileinstaller:1.0.3")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
     implementation("androidx.tracing:tracing-ktx:1.1.0-rc01")
     implementation(libs.testCore)
     implementation(libs.testUiautomator)
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoCaptureTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoCaptureTest.kt
index fa830d2..c9c8608 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoCaptureTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoCaptureTest.kt
@@ -34,7 +34,7 @@
 @RunWith(AndroidJUnit4::class)
 class PerfettoCaptureTest {
     @SdkSuppress(
-        minSdkVersion = 21,
+        minSdkVersion = 23,
         maxSdkVersion = LOWEST_BUNDLED_VERSION_SUPPORTED - 1
     )
     @SmallTest
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
index e7ea76a..b6bc2ca 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/PerfettoSdkHandshakeTest.kt
@@ -47,7 +47,7 @@
 import org.junit.runners.Parameterized
 import org.junit.runners.Parameterized.Parameters
 
-private const val tracingPerfettoVersion = "1.0.0-alpha12" // TODO(224510255): get by 'reflection'
+private const val tracingPerfettoVersion = "1.0.0-alpha13" // TODO(224510255): get by 'reflection'
 private const val minSupportedSdk = Build.VERSION_CODES.R // TODO(234351579): Support API < 30
 
 @RunWith(Parameterized::class)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/FtlRunner.kt b/buildSrc/private/src/main/kotlin/androidx/build/FtlRunner.kt
index b805725..5c45e4e 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/FtlRunner.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/FtlRunner.kt
@@ -83,6 +83,14 @@
     @get:Option(option = "pullScreenshots", description = "true if screenshots should be pulled")
     abstract val pullScreenshots: Property<String>
 
+    @get:Optional
+    @get:Input
+    @get:Option(
+        option = "instrumentationArgs",
+        description = "instrumentation arguments to pass to FTL test runner"
+    )
+    abstract val instrumentationArgs: Property<String>
+
     @get:Input
     abstract val device: Property<String>
 
@@ -142,6 +150,8 @@
                     if (shouldPull) {
                         "/sdcard/Android/data/${apkPackageName.get()}/cache/androidx_screenshots"
                     } else null,
+                    if (instrumentationArgs.isPresent) "--environment-variables" else null,
+                    if (instrumentationArgs.isPresent) instrumentationArgs.get() else null,
                 )
             )
         }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
index ba8cc8b..d05f222 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
@@ -15,19 +15,23 @@
  */
 package androidx.build
 
+import androidx.build.uptodatedness.cacheEvenIfNoOutputs
 import com.android.build.gradle.LibraryExtension
 import org.gradle.api.Action
+import org.gradle.api.DefaultTask
 import org.gradle.api.GradleException
 import org.gradle.api.Project
 import org.gradle.api.Task
 import org.gradle.api.file.DuplicatesStrategy
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.TaskProvider
 import org.gradle.api.tasks.bundling.Zip
 import org.gradle.plugin.devel.GradlePluginDevelopmentExtension
 import org.gradle.work.DisableCachingByDefault
 import java.io.File
+import java.io.FileNotFoundException
 import java.util.Locale
 
 /**
@@ -51,6 +55,10 @@
 // See https://github.com/gradle/gradle/commit/7e5c5bc9b2c23d872e1c45c855f07ca223f6c270#diff-ce55b0f0cdcf2174eb47d333d348ff6fbd9dbe5cd8c3beeeaf633ea23b74ed9eR38
 open class GMavenZipTask : Zip() {
 
+    @Internal
+    @Transient
+    val verifyTask: TaskProvider<VerifyGMavenZipTask>
+
     init {
         // multiple artifacts in the same group might have the same maven-metadata.xml
         duplicatesStrategy = DuplicatesStrategy.EXCLUDE
@@ -69,6 +77,18 @@
                 )
             }
         }
+
+        val zipTask = this
+
+        verifyTask = project.maybeRegister(
+            name = "verify${zipTask.name}",
+            onConfigure = { verifierTask ->
+                verifierTask.addFile(zipTask.archiveFile.get().getAsFile())
+            },
+            onRegister = {
+            }
+        )
+        finalizedBy(verifyTask)
     }
 
     /**
@@ -95,12 +115,14 @@
         )
         // We specifically pass the subdirectory into 'from' so that changes in other artifacts
         // won't cause this task to become out of date
-        from("$androidxRepoOut/$projectSubdir") { spec ->
+        val fromDir = project.file("$androidxRepoOut/$projectSubdir")
+        from(fromDir) { spec ->
             spec.into("m2repository/$projectSubdir")
             for (inclusion in includes) {
                 include(inclusion)
             }
         }
+        verifyTask.get().addFile(fromDir)
     }
     /**
      * Config action that configures the task when necessary.
@@ -355,6 +377,38 @@
     }
 }
 
+// b/273294710
+@DisableCachingByDefault(
+    because = "This task only checks the existence of files and isn't worth caching"
+)
+open class VerifyGMavenZipTask : DefaultTask() {
+    @Input
+    val filesToVerify = mutableListOf<File>()
+
+    init {
+        cacheEvenIfNoOutputs()
+    }
+
+    fun addFile(file: File) {
+        filesToVerify.add(file)
+    }
+
+    @TaskAction
+    fun execute() {
+        val missingFiles = mutableListOf<String>()
+        filesToVerify.forEach { file ->
+            if (!file.exists()) {
+                missingFiles.add(file.path)
+            }
+        }
+
+        if (missingFiles.isNotEmpty()) {
+            val missingFileString = missingFiles.reduce { acc, s -> "$acc, $s" }
+            throw FileNotFoundException("GMavenZip file missing: $missingFileString")
+        }
+    }
+}
+
 /**
  * Let you configure a library variant associated with [Release.DEFAULT_PUBLISH_CONFIG]
  */
@@ -395,9 +449,10 @@
 
 private val AndroidXExtension.publishPlatforms: List<String>
     get() {
-        val declaredTargets = project.multiplatformExtension?.targets?.asMap?.keys?.map {
+        val potentialTargets = project.multiplatformExtension?.targets?.asMap?.keys?.map {
             it.lowercase()
         } ?: emptySet()
+        val declaredTargets = potentialTargets.filter { it != "metadata" }
         return declaredTargets.toList()
     }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
index 4a8a0d2..cab8d67 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
@@ -25,6 +25,7 @@
 import androidx.build.enforceKtlintVersion
 import androidx.build.getAndroidJar
 import androidx.build.getBuildId
+import androidx.build.getCheckoutRoot
 import androidx.build.getDistributionDirectory
 import androidx.build.getKeystore
 import androidx.build.getLibraryByName
@@ -465,7 +466,9 @@
                 jvmSourcesDir = unzippedJvmSourcesDirectory
                 multiplatformSourcesDir = unzippedMultiplatformSourcesDirectory
                 docsProjectDir = File(project.rootDir, "docs-public")
-                dependenciesClasspath = project.getAndroidJar() + dependencyClasspath
+                dependenciesClasspath = dependencyClasspath +
+                    project.getAndroidJar() +
+                    project.getExtraCommonDependencies()
                 excludedPackages = hiddenPackages.toSet()
                 excludedPackagesForJava = hiddenPackagesJava
                 excludedPackagesForKotlin = emptySet()
@@ -745,3 +748,31 @@
         }
     }
 }
+
+private fun Project.getPrebuiltsExternalPath() =
+    File(project.getCheckoutRoot(), "prebuilts/androidx/external/")
+
+private val PLATFORMS =
+    listOf("linuxx64", "macosarm64", "macosx64", "iosx64", "iossimulatorarm64", "iosarm64")
+
+private fun Project.getExtraCommonDependencies(): FileCollection = files(
+    arrayOf(
+        File(
+            getPrebuiltsExternalPath(),
+            "org/jetbrains/kotlinx/kotlinx-coroutines-core/1.6.4/kotlinx-coroutines-core-1.6.4.jar"
+        ),
+        File(
+            getPrebuiltsExternalPath(),
+            "org/jetbrains/kotlinx/atomicfu/0.17.0/atomicfu-0.17.0.jar"
+        ),
+        File(
+            getPrebuiltsExternalPath(),
+            "com/squareup/okio/okio-jvm/3.1.0/okio-jvm-3.1.0.jar"
+        )
+    ) + PLATFORMS.map {
+        File(
+            getPrebuiltsExternalPath(),
+            "com/squareup/okio/okio-$it/3.1.0/okio-$it-3.1.0.klib"
+        )
+    }
+)
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
index f8bb7fb..fab238c 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
@@ -30,6 +30,7 @@
 import androidx.camera.camera2.pipe.integration.config.DaggerCameraAppComponent
 import androidx.camera.camera2.pipe.integration.internal.CameraCompatibilityFilter
 import androidx.camera.camera2.pipe.integration.internal.CameraSelectionOptimizer
+import androidx.camera.core.CameraInfo
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.concurrent.CameraCoordinator
 import androidx.camera.core.concurrent.CameraCoordinator.ConcurrentCameraModeListener
@@ -97,13 +98,11 @@
                 return mutableListOf()
             }
 
-            override fun getActiveConcurrentCameraSelectors(): MutableList<CameraSelector> {
+            override fun getActiveConcurrentCameraInfos(): MutableList<CameraInfo> {
                 return mutableListOf()
             }
 
-            override fun setActiveConcurrentCameraSelectors(
-                cameraSelectors: MutableList<CameraSelector>
-            ) {
+            override fun setActiveConcurrentCameraInfos(cameraInfos: MutableList<CameraInfo>) {
             }
 
             override fun getPairedConcurrentCameraId(cameraId: String): String? {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
index a9e1348..4c4a936 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompat.kt
@@ -24,6 +24,7 @@
 import android.os.Build
 import android.util.Range
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.integration.compat.workaround.getControlZoomRatioRangeSafely
 import androidx.camera.camera2.pipe.integration.impl.CameraProperties
 import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera
 import dagger.Module
@@ -51,8 +52,7 @@
             @Provides
             fun provideZoomRatio(cameraProperties: CameraProperties): ZoomCompat {
                 return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-                    val range =
-                        cameraProperties.metadata[CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE]
+                    val range = cameraProperties.metadata.getControlZoomRatioRangeSafely()
                     if (range != null) {
                         AndroidRZoomCompat(cameraProperties, range)
                     } else {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirk.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirk.kt
new file mode 100644
index 0000000..518a228
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirk.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.camera.camera2.pipe.integration.compat.quirk
+
+import android.annotation.SuppressLint
+import android.hardware.camera2.CameraCharacteristics
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.camera.core.impl.Quirk
+import java.nio.BufferUnderflowException
+
+/**
+ * A quirk for devices that throw a [BufferUnderflowException] when querying the flash availability.
+ *
+ * QuirkSummary
+ * - Bug Id: 231701345
+ * - Description: When attempting to retrieve the
+ *   [CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE] characteristic, an
+ *   [AssertionError] is thrown. This is an undocumented exception
+ *   on the [CameraCharacteristics.get] method, so this violates the API contract.
+ * - Device(s): Jio JioPhone Next, Samsung Galaxy A02s, Vivo V2039
+ *
+ * @see androidx.camera.camera2.pipe.integration.compat.workaround.getControlZoomRatioRangeSafely
+ */
+@SuppressLint("CameraXQuirksClassDetector") // TODO(b/270421716): enable when kotlin is supported.
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+class ControlZoomRatioRangeAssertionErrorQuirk : Quirk {
+    companion object {
+        fun isEnabled() = isJioPhoneNext() || isSamsungA2s() || isVivo2039()
+
+        private fun isJioPhoneNext() = Build.BRAND.equals("JIO", ignoreCase = true) &&
+            Build.MODEL.startsWith("LS1542QW", ignoreCase = true)
+
+        private fun isSamsungA2s() = Build.BRAND.equals("SAMSUNG", ignoreCase = true) && (
+            Build.MODEL.startsWith("SM-A025", ignoreCase = true) ||
+            Build.MODEL.equals("SM-S124DL", ignoreCase = true)
+        )
+
+        private fun isVivo2039() = Build.BRAND.equals("VIVO", ignoreCase = true) &&
+            Build.MODEL.equals("VIVO 2039", ignoreCase = true)
+    }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt
index 55b7820..4508e2f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/quirk/DeviceQuirksLoader.kt
@@ -38,6 +38,10 @@
             quirks.add(CrashWhenTakingPhotoWithAutoFlashAEModeQuirk())
         }
 
+        if (ControlZoomRatioRangeAssertionErrorQuirk.isEnabled()) {
+            quirks.add(ControlZoomRatioRangeAssertionErrorQuirk())
+        }
+
         if (FlashAvailabilityBufferUnderflowQuirk.isEnabled()) {
             quirks.add(FlashAvailabilityBufferUnderflowQuirk())
         }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/CameraMetadataSafeGetter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/CameraMetadataSafeGetter.kt
new file mode 100644
index 0000000..6597f3d
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/compat/workaround/CameraMetadataSafeGetter.kt
@@ -0,0 +1,89 @@
+/*
+ * 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:RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+
+package androidx.camera.camera2.pipe.integration.compat.workaround
+
+import android.hardware.camera2.CameraCharacteristics
+import android.os.Build
+import android.util.Range
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.core.Log
+import androidx.camera.camera2.pipe.integration.compat.quirk.ControlZoomRatioRangeAssertionErrorQuirk
+import androidx.camera.camera2.pipe.integration.compat.quirk.DeviceQuirks
+
+/**
+ * Gets a [CameraCharacteristics] value with additional error handling.
+ *
+ * @param T the type of the characteristic value
+ * @param key the [CameraCharacteristics.Key] of the characteristic
+ * @return the value of the characteristic
+ */
+fun <T> CameraMetadata.getSafely(key: CameraCharacteristics.Key<T>): T? {
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
+        key == CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE
+    ) {
+        @Suppress("UNCHECKED_CAST") // T is guaranteed to be Range<Float>
+        return getControlZoomRatioRangeSafely() as T?
+    }
+
+    return get(key)
+}
+
+/**
+ * Gets the value of [CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE] with additional error
+ * handling.
+ *
+ * Some devices may throw [AssertionError] when getting the value of
+ * [CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE]. Here, the error is caught and logged before
+ * returning null as workaround.
+ *
+ * Ref: b/231701345
+ *
+ * @return the CONTROL_ZOOM_RATIO_RANGE characteristic value, null in case of [AssertionError].
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+fun CameraMetadata.getControlZoomRatioRangeSafely(): Range<Float>? = try {
+    get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE)
+} catch (e: AssertionError) {
+    if (DeviceQuirks[ControlZoomRatioRangeAssertionErrorQuirk::class.java] != null) {
+        Log.debug {
+            "Device is known to throw an exception while retrieving" +
+                " the value for CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE." +
+                " CONTROL_ZOOM_RATIO_RANGE is not supported." +
+                " [Manufacturer: ${Build.MANUFACTURER}, Model:" +
+                " ${Build.MODEL}, API Level: ${Build.VERSION.SDK_INT}]."
+        }
+    } else {
+        Log.error(e) {
+            "Exception thrown while retrieving the value for" +
+                " CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE on devices not known to " +
+                "throw exceptions during this operation. Please file an issue at " +
+                "https://issuetracker.google.com/issues/new?component=618491&template=1257717" +
+                " with this error message [Manufacturer: ${Build.MANUFACTURER}, Model:" +
+                " ${Build.MODEL}, API Level: ${Build.VERSION.SDK_INT}]." +
+                " CONTROL_ZOOM_RATIO_RANGE is not available."
+        }
+    }
+
+    Log.warn(e) {
+        "AssertionError: " +
+            "failed to get CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE"
+    }
+    null
+}
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfo.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfo.kt
index 209c893..2372dd3 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfo.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraInfo.kt
@@ -20,6 +20,7 @@
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
 import androidx.camera.camera2.pipe.integration.adapter.CameraInfoAdapter
+import androidx.camera.camera2.pipe.integration.compat.workaround.getSafely
 import androidx.camera.camera2.pipe.integration.impl.CameraProperties
 import androidx.camera.core.CameraInfo
 import androidx.core.util.Preconditions
@@ -45,9 +46,9 @@
      * @return the value of the characteristic.
     </T> */
     fun <T> getCameraCharacteristic(
-        @Suppress("UNUSED_PARAMETER") key: CameraCharacteristics.Key<T>
+        key: CameraCharacteristics.Key<T>
     ): T? {
-        return cameraProperties.metadata[key]
+        return cameraProperties.metadata.getSafely(key)
     }
 
     /**
@@ -103,4 +104,4 @@
         @JvmStatic
         fun create(cameraProperties: CameraProperties) = Camera2CameraInfo(cameraProperties)
     }
-}
\ No newline at end of file
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompatTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompatTest.kt
new file mode 100644
index 0000000..a194ad5
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/ZoomCompatTest.kt
@@ -0,0 +1,103 @@
+/*
+ * 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.camera.camera2.pipe.integration.compat
+
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.CaptureResult
+import android.os.Build
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.Metadata
+import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
+import androidx.camera.camera2.pipe.integration.impl.CameraProperties
+import com.google.common.truth.Truth.assertThat
+import kotlin.reflect.KClass
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+@DoNotInstrument
+class ZoomCompatTest {
+    @Test
+    @Config(minSdk = 30)
+    fun canProvideZoomCompat_whenGettingControlZoomRatioThrowsError() {
+        assertThat(ZoomCompat.Bindings.provideZoomRatio(throwingCameraProperties))
+            .isInstanceOf(CropRegionZoomCompat::class.java)
+    }
+
+    private val throwingCameraProperties = object : CameraProperties {
+        override val cameraId: CameraId
+            get() = TODO("Not yet implemented")
+        override val metadata: CameraMetadata
+            get() = throwingCameraMetadata
+    }
+
+    private val throwingCameraMetadata = object : CameraMetadata {
+        override val camera: CameraId
+            get() = TODO("Not yet implemented")
+        override val isRedacted: Boolean
+            get() = TODO("Not yet implemented")
+        override val keys: Set<CameraCharacteristics.Key<*>>
+            get() = TODO("Not yet implemented")
+        override val physicalCameraIds: Set<CameraId>
+            get() = TODO("Not yet implemented")
+        override val physicalRequestKeys: Set<CaptureRequest.Key<*>>
+            get() = TODO("Not yet implemented")
+        override val requestKeys: Set<CaptureRequest.Key<*>>
+            get() = TODO("Not yet implemented")
+        override val resultKeys: Set<CaptureResult.Key<*>>
+            get() = TODO("Not yet implemented")
+        override val sessionKeys: Set<CaptureRequest.Key<*>>
+            get() = TODO("Not yet implemented")
+
+        override fun awaitPhysicalMetadata(cameraId: CameraId): CameraMetadata {
+            TODO("Not yet implemented")
+        }
+
+        override fun <T> get(key: CameraCharacteristics.Key<T>): T? {
+            println("throwingCameraMetadata get: key = $key")
+            if (key == CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE) {
+                throw AssertionError()
+            }
+            TODO("Not yet implemented")
+        }
+
+        override fun <T> get(key: Metadata.Key<T>): T? {
+            TODO("Not yet implemented")
+        }
+
+        override fun <T> getOrDefault(key: CameraCharacteristics.Key<T>, default: T): T {
+            TODO("Not yet implemented")
+        }
+
+        override fun <T> getOrDefault(key: Metadata.Key<T>, default: T): T {
+            TODO("Not yet implemented")
+        }
+
+        override suspend fun getPhysicalMetadata(cameraId: CameraId): CameraMetadata {
+            TODO("Not yet implemented")
+        }
+
+        override fun <T : Any> unwrapAs(type: KClass<T>): T? {
+            TODO("Not yet implemented")
+        }
+    }
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirkTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirkTest.kt
new file mode 100644
index 0000000..7a13679
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/compat/quirk/ControlZoomRatioRangeAssertionErrorQuirkTest.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.camera.camera2.pipe.integration.compat.quirk
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.ParameterizedRobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadows.ShadowBuild
+
+@RunWith(ParameterizedRobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = 21)
+class ControlZoomRatioRangeAssertionErrorQuirkTest(
+    private val brand: String,
+    private val model: String,
+    private val quirkEnablingExpected: Boolean
+) {
+    @Test
+    fun canEnableControlZoomRatioRangeAssertionErrorQuirkCorrectly() {
+        ShadowBuild.setBrand(brand)
+        ShadowBuild.setModel(model)
+
+        assertThat(DeviceQuirks[ControlZoomRatioRangeAssertionErrorQuirk::class.java] != null)
+            .isEqualTo(quirkEnablingExpected)
+    }
+
+    companion object {
+        @JvmStatic
+        @ParameterizedRobolectricTestRunner.Parameters(name = "Brand: {0}, Model: {1}")
+        fun data() = listOf(
+            arrayOf("jio", "LS1542QWN", true),
+            arrayOf("samsung", "SM-A025M/DS", true),
+            arrayOf("Samsung", "SM-S124DL", true),
+            arrayOf("vivo", "vivo 2039", true),
+            arrayOf("motorola", "MotoG100", false),
+        )
+    }
+}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2CameraControlDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2CameraControlDeviceTest.java
index 7977243..04c3858 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2CameraControlDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2CameraControlDeviceTest.java
@@ -70,7 +70,7 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 @OptIn(markerClass = ExperimentalCamera2Interop.class)
-@SdkSuppress(minSdkVersion = 21)
+@SdkSuppress(minSdkVersion = 22) // b/272066193
 public final class Camera2CameraControlDeviceTest {
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
     private CameraSelector mCameraSelector;
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
index 471ab2c..29a28b7 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/interop/Camera2InteropDeviceTest.java
@@ -71,7 +71,7 @@
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 @OptIn(markerClass = ExperimentalCamera2Interop.class)
-@SdkSuppress(minSdkVersion = 21)
+@SdkSuppress(minSdkVersion = 22) // b/272066193
 public final class Camera2InteropDeviceTest {
     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
     private CameraSelector mCameraSelector;
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
index 1a64c2e..e893e30 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraInfoImpl.java
@@ -121,7 +121,7 @@
      * Constructs an instance. Before {@link #linkWithCameraControl(Camera2CameraControlImpl)} is
      * called, camera control related API (torch/exposure/zoom) will return default values.
      */
-    Camera2CameraInfoImpl(@NonNull String cameraId,
+    public Camera2CameraInfoImpl(@NonNull String cameraId,
             @NonNull CameraManagerCompat cameraManager) throws CameraAccessExceptionCompat {
         mCameraId = Preconditions.checkNotNull(cameraId);
         mCameraManager = cameraManager;
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ZslControlImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ZslControlImpl.java
index bcf5423..d69d972 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ZslControlImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ZslControlImpl.java
@@ -74,9 +74,6 @@
     static final int MAX_IMAGES = RING_BUFFER_CAPACITY * 3;
 
     @NonNull
-    private final Map<Integer, Size> mReprocessingInputSizeMap;
-
-    @NonNull
     private final CameraCharacteristicsCompat mCameraCharacteristicsCompat;
 
     @VisibleForTesting
@@ -104,8 +101,6 @@
                 isCapabilitySupported(mCameraCharacteristicsCompat,
                         REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
 
-        mReprocessingInputSizeMap = createReprocessingInputSizeMap(mCameraCharacteristicsCompat);
-
         mShouldZslDisabledByQuirks = DeviceQuirks.get(ZslDisablerQuirk.class) != null;
 
         mImageRingBuffer = new ZslRingBuffer(
@@ -149,6 +144,9 @@
             return;
         }
 
+        Map<Integer, Size> mReprocessingInputSizeMap =
+                createReprocessingInputSizeMap(mCameraCharacteristicsCompat);
+
         // Due to b/232268355 and feedback from pixel team that private format will have better
         // performance, we will use private only for zsl.
         if (!mIsPrivateReprocessingSupported
@@ -283,9 +281,15 @@
     @NonNull
     private Map<Integer, Size> createReprocessingInputSizeMap(
             @NonNull CameraCharacteristicsCompat cameraCharacteristicsCompat) {
-        StreamConfigurationMap map =
-                cameraCharacteristicsCompat.get(
-                        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        StreamConfigurationMap map = null;
+        try {
+            map = cameraCharacteristicsCompat.get(
+                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        } catch (AssertionError e) {
+            // Some devices may throw AssertionError when retrieving the stream configuration map.
+            Logger.e(TAG, "Failed to retrieve StreamConfigurationMap, error = "
+                    + e.getMessage());
+        }
 
         if (map == null || map.getInputFormats() == null) {
             return new HashMap<>();
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java
new file mode 100644
index 0000000..e7d3d64
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompat.java
@@ -0,0 +1,166 @@
+/*
+ * 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.camera.camera2.internal.compat.params;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.params.DynamicRangeProfiles;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
+import androidx.camera.core.DynamicRange;
+import androidx.core.util.Preconditions;
+
+import java.util.Set;
+
+/**
+ * Helper for accessing features in DynamicRangeProfiles in a backwards compatible fashion.
+ */
+@RequiresApi(21)
+public final class DynamicRangesCompat {
+
+    private final DynamicRangeProfilesCompatImpl mImpl;
+
+    DynamicRangesCompat(@NonNull DynamicRangeProfilesCompatImpl impl) {
+        mImpl = impl;
+    }
+
+    /**
+     * Returns a set of supported {@link DynamicRange} that can be referenced in a single
+     * capture request.
+     *
+     * <p>For example if a particular 10-bit output capable device returns (STANDARD,
+     * HLG10, HDR10) as result from calling {@link #getSupportedDynamicRanges()} and
+     * getProfileCaptureRequestConstraints(long) returns (STANDARD, HLG10) when given an argument
+     * of STANDARD. This means that the corresponding camera device will only accept and process
+     * capture requests that reference outputs configured using HDR10 dynamic range or
+     * alternatively some combination of STANDARD and HLG10. However trying to queue capture
+     * requests to outputs that reference both HDR10 and STANDARD/HLG10 will result in
+     * IllegalArgumentException.
+     *
+     * <p>The list will be empty in case there are no constraints for the given dynamic range.
+     *
+     * @param dynamicRange The dynamic range that will be checked for constraints
+     * @return non-modifiable set of dynamic ranges
+     * @throws IllegalArgumentException If the dynamic range argument is not within the set
+     * returned by {@link #getSupportedDynamicRanges()}.
+     */
+    @NonNull
+    public Set<DynamicRange> getDynamicRangeCaptureRequestConstraints(
+            @NonNull DynamicRange dynamicRange) {
+        return mImpl.getDynamicRangeCaptureRequestConstraints(dynamicRange);
+    }
+
+    /**
+     * Returns a set of supported dynamic ranges.
+     *
+     * @return a non-modifiable set of dynamic ranges.
+     */
+    @NonNull
+    public Set<DynamicRange> getSupportedDynamicRanges() {
+        return mImpl.getSupportedDynamicRanges();
+    }
+
+    /**
+     * Checks whether a given dynamic range is suitable for latency sensitive use cases.
+     *
+     * <p>Due to internal lookahead logic, camera outputs configured with some dynamic range
+     * profiles may experience additional latency greater than 3 buffers. Using camera outputs
+     * with such dynamic ranges for latency sensitive use cases such as camera preview is not
+     * recommended. Dynamic ranges that have such extra streaming delay are typically utilized for
+     * scenarios such as offscreen video recording.
+     *
+     * @param dynamicRange The dynamic range to check for extra latency
+     * @return {@code true} if the given profile is not suitable for latency sensitive use cases,
+     * {@code false} otherwise.
+     * @throws IllegalArgumentException If the dynamic range argument is not within the set
+     * returned by {@link #getSupportedDynamicRanges()}.
+     */
+    public boolean isExtraLatencyPresent(@NonNull DynamicRange dynamicRange) {
+        return mImpl.isExtraLatencyPresent(dynamicRange);
+    }
+
+    /**
+     * Returns a {@link DynamicRangesCompat} using the capabilities derived from the provided
+     * characteristics.
+     *
+     * @param characteristics the characteristics used to derive dynamic range information.
+     * @return a {@link DynamicRangesCompat} object.
+     */
+    @NonNull
+    public static DynamicRangesCompat fromCameraCharacteristics(
+            @NonNull CameraCharacteristicsCompat characteristics) {
+        DynamicRangesCompat rangesCompat = null;
+        if (Build.VERSION.SDK_INT >= 33) {
+            rangesCompat = toDynamicRangesCompat(characteristics.get(
+                    CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES));
+        }
+
+        return (rangesCompat == null) ? DynamicRangesCompatBaseImpl.COMPAT_INSTANCE : rangesCompat;
+    }
+
+    /**
+     * Creates an instance from a framework android.hardware.camera2.params.DynamicRangeProfiles
+     * object.
+     *
+     * @param dynamicRangeProfiles a {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     * @return an equivalent {@link DynamicRangesCompat} object.
+     */
+    @Nullable
+    @RequiresApi(33)
+    public static DynamicRangesCompat toDynamicRangesCompat(
+            @Nullable DynamicRangeProfiles dynamicRangeProfiles) {
+        if (dynamicRangeProfiles == null) {
+            return null;
+        }
+
+        Preconditions.checkState(Build.VERSION.SDK_INT >= 33, "DynamicRangeProfiles can only be "
+                + "converted to DynamicRangesCompat on API 33 or higher.");
+
+        return new DynamicRangesCompat(new DynamicRangesCompatApi33Impl(dynamicRangeProfiles));
+    }
+
+    /**
+     * Returns the underlying framework
+     * {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     *
+     * @return the underlying {@link android.hardware.camera2.params.DynamicRangeProfiles).
+     */
+    @NonNull
+    @RequiresApi(33)
+    public DynamicRangeProfiles toDynamicRangeProfiles() {
+        Preconditions.checkState(Build.VERSION.SDK_INT >= 33, "DynamicRangesCompat can only be "
+                + "converted to DynamicRangeProfiles on API 33 or higher.");
+        return Preconditions.checkNotNull(mImpl.unwrap());
+    }
+
+    interface DynamicRangeProfilesCompatImpl {
+        @NonNull
+        Set<DynamicRange> getDynamicRangeCaptureRequestConstraints(
+                @NonNull DynamicRange dynamicRange);
+
+        @NonNull
+        Set<DynamicRange> getSupportedDynamicRanges();
+
+        boolean isExtraLatencyPresent(@NonNull DynamicRange dynamicRange);
+
+        @Nullable
+        DynamicRangeProfiles unwrap();
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatApi33Impl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatApi33Impl.java
new file mode 100644
index 0000000..1c9a492
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatApi33Impl.java
@@ -0,0 +1,171 @@
+/*
+ * 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.camera.camera2.internal.compat.params;
+
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_10B_HDR_OEM;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_10B_HDR_OEM_PO;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_10B_HDR_REF;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_10B_HDR_REF_PO;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_8B_HDR_OEM;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_8B_HDR_OEM_PO;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_8B_HDR_REF;
+import static android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_8B_HDR_REF_PO;
+import static android.hardware.camera2.params.DynamicRangeProfiles.HDR10;
+import static android.hardware.camera2.params.DynamicRangeProfiles.HDR10_PLUS;
+import static android.hardware.camera2.params.DynamicRangeProfiles.HLG10;
+import static android.hardware.camera2.params.DynamicRangeProfiles.STANDARD;
+
+import android.hardware.camera2.params.DynamicRangeProfiles;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.DynamicRange;
+import androidx.core.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@RequiresApi(33)
+class DynamicRangesCompatApi33Impl implements DynamicRangesCompat.DynamicRangeProfilesCompatImpl {
+    private static final Map<Long, DynamicRange> PROFILE_TO_DR_MAP = new HashMap<>();
+    private static final Map<DynamicRange, List<Long>> DR_TO_PROFILE_MAP = new HashMap<>();
+
+    static {
+        // SDR
+        PROFILE_TO_DR_MAP.put(STANDARD, DynamicRange.SDR);
+        DR_TO_PROFILE_MAP.put(DynamicRange.SDR, Collections.singletonList(STANDARD));
+
+        // HLG
+        PROFILE_TO_DR_MAP.put(HLG10,
+                new DynamicRange(DynamicRange.FORMAT_HLG, DynamicRange.BIT_DEPTH_10_BIT));
+        DR_TO_PROFILE_MAP.put(PROFILE_TO_DR_MAP.get(HLG10), Collections.singletonList(HLG10));
+
+        // HDR10
+        DynamicRange hdr10 = new DynamicRange(DynamicRange.FORMAT_HDR10,
+                DynamicRange.BIT_DEPTH_10_BIT);
+        PROFILE_TO_DR_MAP.put(HDR10, hdr10);
+        DR_TO_PROFILE_MAP.put(hdr10, Collections.singletonList(HDR10));
+
+        // HDR10+
+        DynamicRange hdr10Plus = new DynamicRange(DynamicRange.FORMAT_HDR10_PLUS,
+                DynamicRange.BIT_DEPTH_10_BIT);
+        PROFILE_TO_DR_MAP.put(HDR10_PLUS, hdr10Plus);
+        DR_TO_PROFILE_MAP.put(hdr10Plus, Collections.singletonList(HDR10_PLUS));
+
+        // Dolby Vision 10-bit
+        DynamicRange dolbyVision10Bit = new DynamicRange(DynamicRange.FORMAT_DOLBY_VISION,
+                DynamicRange.BIT_DEPTH_10_BIT);
+        // A list of the Camera2 10-bit dolby vision profiles ordered by priority. Any API that
+        // takes a DynamicRange with dolby vision format will attempt to convert to these
+        // profiles in order, using the first one that is supported. We will need to add a
+        // mechanism for choosing between these
+        List<Long> dolbyVision10BitProfilesOrdered = Arrays.asList(DOLBY_VISION_10B_HDR_OEM,
+                DOLBY_VISION_10B_HDR_OEM_PO, DOLBY_VISION_10B_HDR_REF, DOLBY_VISION_10B_HDR_REF_PO);
+        for (Long profile : dolbyVision10BitProfilesOrdered) {
+            PROFILE_TO_DR_MAP.put(profile, dolbyVision10Bit);
+        }
+        DR_TO_PROFILE_MAP.put(dolbyVision10Bit, dolbyVision10BitProfilesOrdered);
+
+        // Dolby vision 8-bit
+        DynamicRange dolbyVision8Bit = new DynamicRange(DynamicRange.FORMAT_DOLBY_VISION,
+                DynamicRange.BIT_DEPTH_8_BIT);
+        List<Long> dolbyVision8BitProfilesOrdered = Arrays.asList(DOLBY_VISION_8B_HDR_OEM,
+                DOLBY_VISION_8B_HDR_OEM_PO, DOLBY_VISION_8B_HDR_REF, DOLBY_VISION_8B_HDR_REF_PO);
+        for (Long profile : dolbyVision8BitProfilesOrdered) {
+            PROFILE_TO_DR_MAP.put(profile, dolbyVision8Bit);
+        }
+        DR_TO_PROFILE_MAP.put(dolbyVision8Bit, dolbyVision8BitProfilesOrdered);
+    }
+
+    private final DynamicRangeProfiles mDynamicRangeProfiles;
+
+    DynamicRangesCompatApi33Impl(@NonNull Object dynamicRangeProfiles) {
+        mDynamicRangeProfiles = (DynamicRangeProfiles) dynamicRangeProfiles;
+    }
+
+    @NonNull
+    @Override
+    public Set<DynamicRange> getDynamicRangeCaptureRequestConstraints(
+            @NonNull DynamicRange dynamicRange) {
+        Long dynamicRangeProfile = dynamicRangeToFirstSupportedProfile(dynamicRange);
+        Preconditions.checkArgument(dynamicRangeProfile != null,
+                "DynamicRange is not supported: " + dynamicRange);
+        return profileSetToDynamicRangeSet(
+                mDynamicRangeProfiles.getProfileCaptureRequestConstraints(dynamicRangeProfile));
+    }
+
+    @NonNull
+    @Override
+    public Set<DynamicRange> getSupportedDynamicRanges() {
+        return profileSetToDynamicRangeSet(mDynamicRangeProfiles.getSupportedProfiles());
+    }
+
+    @Override
+    public boolean isExtraLatencyPresent(@NonNull DynamicRange dynamicRange) {
+        Long dynamicRangeProfile = dynamicRangeToFirstSupportedProfile(dynamicRange);
+        Preconditions.checkArgument(dynamicRangeProfile != null,
+                "DynamicRange is not supported: " + dynamicRange);
+        return mDynamicRangeProfiles.isExtraLatencyPresent(dynamicRangeProfile);
+    }
+
+    @Nullable
+    @Override
+    public DynamicRangeProfiles unwrap() {
+        return mDynamicRangeProfiles;
+    }
+
+    @NonNull
+    private static DynamicRange profileToDynamicRange(long profile) {
+        return Preconditions.checkNotNull(PROFILE_TO_DR_MAP.get(profile),
+                "Dynamic range profile cannot be converted to a DynamicRange object: " + profile);
+    }
+
+    @Nullable
+    private Long dynamicRangeToFirstSupportedProfile(@NonNull DynamicRange dynamicRange) {
+        List<Long> orderedProfiles =
+                Preconditions.checkNotNull(DR_TO_PROFILE_MAP.get(dynamicRange),
+                        "DynamicRange object does not have an associated camera2 profile: "
+                                + dynamicRange);
+        Set<Long> supportedList = mDynamicRangeProfiles.getSupportedProfiles();
+        for (Long profile : orderedProfiles) {
+            if (supportedList.contains(profile)) {
+                return profile;
+            }
+        }
+
+        // No profile supported
+        return null;
+    }
+
+    @NonNull
+    private static Set<DynamicRange> profileSetToDynamicRangeSet(@NonNull Set<Long> profileSet) {
+        if (profileSet.isEmpty()) {
+            return Collections.emptySet();
+        }
+        Set<DynamicRange> dynamicRangeSet = new HashSet<>(profileSet.size());
+        for (long profile : profileSet) {
+            dynamicRangeSet.add(profileToDynamicRange(profile));
+        }
+        return Collections.unmodifiableSet(dynamicRangeSet);
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatBaseImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatBaseImpl.java
new file mode 100644
index 0000000..312978f
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatBaseImpl.java
@@ -0,0 +1,64 @@
+/*
+ * 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.camera.camera2.internal.compat.params;
+
+import android.hardware.camera2.params.DynamicRangeProfiles;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.DynamicRange;
+import androidx.core.util.Preconditions;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RequiresApi(21)
+class DynamicRangesCompatBaseImpl implements DynamicRangesCompat.DynamicRangeProfilesCompatImpl {
+
+    static final DynamicRangesCompat COMPAT_INSTANCE =
+            new DynamicRangesCompat(new DynamicRangesCompatBaseImpl());
+
+    private static final Set<DynamicRange> SDR_ONLY = Collections.singleton(DynamicRange.SDR);
+    @NonNull
+    @Override
+    public Set<DynamicRange> getDynamicRangeCaptureRequestConstraints(
+            @NonNull DynamicRange dynamicRange) {
+        Preconditions.checkArgument(DynamicRange.SDR.equals(dynamicRange),
+                "DynamicRange is not supported: " + dynamicRange);
+        return SDR_ONLY;
+    }
+
+    @NonNull
+    @Override
+    public Set<DynamicRange> getSupportedDynamicRanges() {
+        return SDR_ONLY;
+    }
+
+    @Override
+    public boolean isExtraLatencyPresent(@NonNull DynamicRange dynamicRange) {
+        Preconditions.checkArgument(DynamicRange.SDR.equals(dynamicRange),
+                "DynamicRange is not supported: " + dynamicRange);
+        return false;
+    }
+
+    @Nullable
+    @Override
+    public DynamicRangeProfiles unwrap() {
+        return null;
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java
index 8505fdc..16d20ce 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinator.java
@@ -50,8 +50,8 @@
 
     @NonNull private final CameraManagerCompat mCameraManager;
     @NonNull private final List<ConcurrentCameraModeListener> mConcurrentCameraModeListeners;
-    @NonNull private final Map<String, String> mConcurrentCameraIdMap;
-    @NonNull private List<CameraSelector> mActiveConcurrentCameraSelectors;
+    @NonNull private final Map<String, List<String>> mConcurrentCameraIdMap;
+    @NonNull private List<CameraInfo> mActiveConcurrentCameraInfos;
     @NonNull private Set<Set<String>> mConcurrentCameraIds;
 
     @CameraOperatingMode private int mCameraOperatingMode = CAMERA_OPERATING_MODE_UNSPECIFIED;
@@ -61,7 +61,7 @@
         mConcurrentCameraIdMap = new HashMap<>();
         mConcurrentCameraIds = new HashSet<>();
         mConcurrentCameraModeListeners = new ArrayList<>();
-        mActiveConcurrentCameraSelectors = new ArrayList<>();
+        mActiveConcurrentCameraInfos = new ArrayList<>();
         retrieveConcurrentCameraIds();
     }
 
@@ -81,20 +81,28 @@
 
     @NonNull
     @Override
-    public List<CameraSelector> getActiveConcurrentCameraSelectors() {
-        return mActiveConcurrentCameraSelectors;
+    public List<CameraInfo> getActiveConcurrentCameraInfos() {
+        return mActiveConcurrentCameraInfos;
     }
 
     @Override
-    public void setActiveConcurrentCameraSelectors(@NonNull List<CameraSelector> cameraSelectors) {
-        mActiveConcurrentCameraSelectors = cameraSelectors;
+    public void setActiveConcurrentCameraInfos(@NonNull List<CameraInfo> cameraInfos) {
+        mActiveConcurrentCameraInfos = new ArrayList<>(cameraInfos);
     }
 
+    @OptIn(markerClass = ExperimentalCamera2Interop.class)
     @Nullable
     @Override
     public String getPairedConcurrentCameraId(@NonNull String cameraId) {
-        if (mConcurrentCameraIdMap.containsKey(cameraId)) {
-            return mConcurrentCameraIdMap.get(cameraId);
+        if (!mConcurrentCameraIdMap.containsKey(cameraId)) {
+            return null;
+        }
+        for (String pairedCameraId : mConcurrentCameraIdMap.get(cameraId)) {
+            for (CameraInfo cameraInfo : mActiveConcurrentCameraInfos) {
+                if (pairedCameraId.equals(Camera2CameraInfo.from(cameraInfo).getCameraId())) {
+                    return pairedCameraId;
+                }
+            }
         }
         return null;
     }
@@ -114,10 +122,10 @@
                         cameraOperatingMode);
             }
         }
-        // Clear the cached camera selectors if concurrent mode is off.
+        // Clear the cached active camera infos if concurrent mode is off.
         if (mCameraOperatingMode == CAMERA_OPERATING_MODE_CONCURRENT
                 && cameraOperatingMode != CAMERA_OPERATING_MODE_CONCURRENT) {
-            mActiveConcurrentCameraSelectors.clear();
+            mActiveConcurrentCameraInfos.clear();
         }
         mCameraOperatingMode = cameraOperatingMode;
     }
@@ -142,11 +150,17 @@
         for (Set<String> concurrentCameraIdList: mConcurrentCameraIds) {
             List<String> cameraIdList = new ArrayList<>(concurrentCameraIdList);
 
-            // TODO(b/268531569): enumerate concurrent camera ids and convert to a map for
-            //  paired camera id lookup.
             if (cameraIdList.size() >= 2) {
-                mConcurrentCameraIdMap.put(cameraIdList.get(0), cameraIdList.get(1));
-                mConcurrentCameraIdMap.put(cameraIdList.get(1), cameraIdList.get(0));
+                String cameraId1 = cameraIdList.get(0);
+                String cameraId2 = cameraIdList.get(1);
+                if (!mConcurrentCameraIdMap.containsKey(cameraId1)) {
+                    mConcurrentCameraIdMap.put(cameraId1, new ArrayList<>());
+                }
+                if (!mConcurrentCameraIdMap.containsKey(cameraId2)) {
+                    mConcurrentCameraIdMap.put(cameraId2, new ArrayList<>());
+                }
+                mConcurrentCameraIdMap.get(cameraIdList.get(0)).add(cameraIdList.get(1));
+                mConcurrentCameraIdMap.get(cameraIdList.get(1)).add(cameraIdList.get(0));
             }
         }
     }
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt
new file mode 100644
index 0000000..686debe
--- /dev/null
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/params/DynamicRangesCompatTest.kt
@@ -0,0 +1,360 @@
+/*
+ * 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.camera.camera2.internal.compat.params
+
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.params.DynamicRangeProfiles
+import android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_10B_HDR_OEM
+import android.hardware.camera2.params.DynamicRangeProfiles.DOLBY_VISION_8B_HDR_OEM
+import android.hardware.camera2.params.DynamicRangeProfiles.HDR10
+import android.hardware.camera2.params.DynamicRangeProfiles.HDR10_PLUS
+import android.hardware.camera2.params.DynamicRangeProfiles.HLG10
+import android.hardware.camera2.params.DynamicRangeProfiles.STANDARD
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat
+import androidx.camera.core.DynamicRange
+import androidx.camera.core.DynamicRange.BIT_DEPTH_10_BIT
+import androidx.camera.core.DynamicRange.BIT_DEPTH_8_BIT
+import androidx.camera.core.DynamicRange.FORMAT_DOLBY_VISION
+import androidx.camera.core.DynamicRange.FORMAT_HDR10
+import androidx.camera.core.DynamicRange.FORMAT_HDR10_PLUS
+import androidx.camera.core.DynamicRange.FORMAT_HLG
+import androidx.camera.core.DynamicRange.SDR
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadow.api.Shadow
+import org.robolectric.shadows.ShadowCameraCharacteristics
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class DynamicRangesCompatTest {
+
+    companion object {
+        val HLG10_UNCONSTRAINED by lazy {
+            DynamicRangeProfiles(longArrayOf(HLG10, 0, 0))
+        }
+
+        val HLG10_CONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, HLG10, LATENCY_NONE
+                )
+            )
+        }
+
+        val HLG10_SDR_CONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, HLG10 or STANDARD, LATENCY_NONE
+                )
+            )
+        }
+
+        val HLG10_HDR10_CONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, HLG10 or HDR10, LATENCY_NONE,
+                    HDR10, HDR10 or HLG10, LATENCY_NONE
+                )
+            )
+        }
+
+        val HDR10_UNCONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, CONSTRAINTS_NONE, LATENCY_NONE, // HLG is mandated
+                    HDR10, CONSTRAINTS_NONE, LATENCY_NONE
+                )
+            )
+        }
+
+        val HDR10_PLUS_UNCONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, CONSTRAINTS_NONE, LATENCY_NONE, // HLG is mandated
+                    HDR10_PLUS, CONSTRAINTS_NONE, LATENCY_NONE
+                )
+            )
+        }
+
+        val DOLBY_VISION_10B_UNCONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, CONSTRAINTS_NONE, LATENCY_NONE, // HLG is mandated
+                    DOLBY_VISION_10B_HDR_OEM, CONSTRAINTS_NONE, LATENCY_NONE
+                )
+            )
+        }
+
+        val DOLBY_VISION_10B_UNCONSTRAINED_SLOW by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    HLG10, CONSTRAINTS_NONE, LATENCY_NONE, // HLG is mandated
+                    DOLBY_VISION_10B_HDR_OEM, CONSTRAINTS_NONE, LATENCY_NON_ZERO
+                )
+            )
+        }
+
+        val DOLBY_VISION_8B_UNCONSTRAINED by lazy {
+            DynamicRangeProfiles(
+                longArrayOf(
+                    DOLBY_VISION_8B_HDR_OEM, CONSTRAINTS_NONE, LATENCY_NONE
+                )
+            )
+        }
+
+        private const val LATENCY_NONE = 0L
+        private const val LATENCY_NON_ZERO = 3L
+        private const val CONSTRAINTS_NONE = 0L
+
+        val DYNAMIC_RANGE_HLG10 = DynamicRange(FORMAT_HLG, BIT_DEPTH_10_BIT)
+        val DYNAMIC_RANGE_HDR10 = DynamicRange(FORMAT_HDR10, BIT_DEPTH_10_BIT)
+        val DYNAMIC_RANGE_HDR10_PLUS = DynamicRange(FORMAT_HDR10_PLUS, BIT_DEPTH_10_BIT)
+        val DYNAMIC_RANGE_DOLBY_VISION_10B = DynamicRange(FORMAT_DOLBY_VISION, BIT_DEPTH_10_BIT)
+        val DYNAMIC_RANGE_DOLBY_VISION_8B = DynamicRange(FORMAT_DOLBY_VISION, BIT_DEPTH_8_BIT)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canWrapAndUnwrapDynamicRangeProfiles() {
+        val dynamicRangesCompat = DynamicRangesCompat.toDynamicRangesCompat(HLG10_UNCONSTRAINED)
+
+        assertThat(dynamicRangesCompat).isNotNull()
+        assertThat(dynamicRangesCompat?.toDynamicRangeProfiles()).isEqualTo(HLG10_UNCONSTRAINED)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canSupportDynamicRangeFromHlg10Profile() {
+        val dynamicRangesCompat = DynamicRangesCompat.toDynamicRangesCompat(HLG10_UNCONSTRAINED)
+        assertThat(dynamicRangesCompat?.supportedDynamicRanges).contains(DYNAMIC_RANGE_HLG10)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canSupportDynamicRangeFromHdr10Profile() {
+        val dynamicRangesCompat = DynamicRangesCompat.toDynamicRangesCompat(HDR10_UNCONSTRAINED)
+        assertThat(dynamicRangesCompat?.supportedDynamicRanges).contains(DYNAMIC_RANGE_HDR10)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canSupportDynamicRangeFromHdr10PlusProfile() {
+        val dynamicRangesCompat =
+            DynamicRangesCompat.toDynamicRangesCompat(HDR10_PLUS_UNCONSTRAINED)
+        assertThat(dynamicRangesCompat?.supportedDynamicRanges).contains(DYNAMIC_RANGE_HDR10_PLUS)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canSupportDynamicRangeFromDolbyVision10bProfile() {
+        val dynamicRangesCompat =
+            DynamicRangesCompat.toDynamicRangesCompat(DOLBY_VISION_10B_UNCONSTRAINED)
+        assertThat(dynamicRangesCompat?.supportedDynamicRanges).contains(
+            DYNAMIC_RANGE_DOLBY_VISION_10B
+        )
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canSupportDynamicRangeFromDolbyVision8bProfile() {
+        val dynamicRangesCompat =
+            DynamicRangesCompat.toDynamicRangesCompat(DOLBY_VISION_8B_UNCONSTRAINED)
+        assertThat(dynamicRangesCompat?.supportedDynamicRanges).contains(
+            DYNAMIC_RANGE_DOLBY_VISION_8B
+        )
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canProduceConcurrentDynamicRangeConstraints() {
+        val hlg10ConstrainedWrapped = DynamicRangesCompat.toDynamicRangesCompat(HLG10_CONSTRAINED)
+        assertThat(
+            hlg10ConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(SDR)
+        ).containsExactly(SDR)
+        assertThat(
+            hlg10ConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(
+                DYNAMIC_RANGE_HLG10
+            )
+        ).containsExactly(DYNAMIC_RANGE_HLG10)
+
+        val hlg10SdrConstrainedWrapped =
+            DynamicRangesCompat.toDynamicRangesCompat(HLG10_SDR_CONSTRAINED)
+        assertThat(
+            hlg10SdrConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(SDR)
+        ).containsExactly(SDR, DYNAMIC_RANGE_HLG10)
+        assertThat(
+            hlg10SdrConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(
+                DYNAMIC_RANGE_HLG10
+            )
+        ).containsExactly(DYNAMIC_RANGE_HLG10, SDR)
+
+        val hlg10Hdr10ConstrainedWrapped =
+            DynamicRangesCompat.toDynamicRangesCompat(HLG10_HDR10_CONSTRAINED)
+        assertThat(
+            hlg10Hdr10ConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(SDR)
+        ).containsExactly(SDR)
+        assertThat(
+            hlg10Hdr10ConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(
+                DYNAMIC_RANGE_HLG10
+            )
+        ).containsExactly(DYNAMIC_RANGE_HLG10, DYNAMIC_RANGE_HDR10)
+        assertThat(
+            hlg10Hdr10ConstrainedWrapped?.getDynamicRangeCaptureRequestConstraints(
+                DYNAMIC_RANGE_HDR10
+            )
+        ).containsExactly(DYNAMIC_RANGE_HDR10, DYNAMIC_RANGE_HLG10)
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun producesDynamicRangeWithCorrectLatency() {
+        val dynamicRangesCompat =
+            DynamicRangesCompat.toDynamicRangesCompat(DOLBY_VISION_10B_UNCONSTRAINED_SLOW)
+        assertThat(dynamicRangesCompat?.isExtraLatencyPresent(SDR)).isFalse()
+        assertThat(
+            dynamicRangesCompat?.isExtraLatencyPresent(
+                DYNAMIC_RANGE_DOLBY_VISION_10B
+            )
+        ).isTrue()
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canProduceDynamicRangeWithoutConstraints() {
+        val dynamicRangesCompat = DynamicRangesCompat.toDynamicRangesCompat(HLG10_UNCONSTRAINED)
+        assertThat(
+            dynamicRangesCompat?.getDynamicRangeCaptureRequestConstraints(DYNAMIC_RANGE_HLG10)
+        ).isEmpty()
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.TIRAMISU)
+    @Test
+    fun canProduceDynamicRangesCompatFromCharacteristics() {
+        val characteristics = newCameraCharacteristicsCompat()
+        Shadow.extract<ShadowCameraCharacteristics>(
+            characteristics.toCameraCharacteristics()
+        ).addDynamicRangeProfiles(HLG10_CONSTRAINED)
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        assertThat(dynamicRangesCompat.toDynamicRangeProfiles()).isEqualTo(HLG10_CONSTRAINED)
+    }
+
+    @Test
+    fun alwaysSupportsOnlySdrWithoutDynamicRangeProfilesInCharacteristics() {
+        val characteristics = newCameraCharacteristicsCompat()
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        assertThat(dynamicRangesCompat.supportedDynamicRanges).containsExactly(SDR)
+        assertThat(
+            dynamicRangesCompat.getDynamicRangeCaptureRequestConstraints(SDR)
+        ).containsExactly(SDR)
+    }
+
+    @Test
+    fun unsupportedDynamicRangeAlwaysThrowsException() {
+        val characteristics = newCameraCharacteristicsCompat()
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            Shadow.extract<ShadowCameraCharacteristics>(
+                characteristics.toCameraCharacteristics()
+            ).addDynamicRangeProfiles(DOLBY_VISION_8B_UNCONSTRAINED)
+        }
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+            assertThat(dynamicRangesCompat.supportedDynamicRanges).containsExactly(SDR)
+        } else {
+            assertThat(dynamicRangesCompat.supportedDynamicRanges).containsExactly(
+                SDR, DYNAMIC_RANGE_DOLBY_VISION_8B
+            )
+        }
+
+        assertThrows(IllegalArgumentException::class.java) {
+            dynamicRangesCompat.getDynamicRangeCaptureRequestConstraints(
+                DYNAMIC_RANGE_DOLBY_VISION_10B
+            )
+        }
+
+        assertThrows(IllegalArgumentException::class.java) {
+            dynamicRangesCompat.isExtraLatencyPresent(
+                DYNAMIC_RANGE_DOLBY_VISION_10B
+            )
+        }
+    }
+
+    @Test
+    fun sdrHasNoExtraLatency() {
+        val characteristics = newCameraCharacteristicsCompat()
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            Shadow.extract<ShadowCameraCharacteristics>(
+                characteristics.toCameraCharacteristics()
+            ).addDynamicRangeProfiles(HLG10_CONSTRAINED)
+        }
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        assertThat(dynamicRangesCompat.isExtraLatencyPresent(SDR)).isFalse()
+    }
+
+    @Test
+    fun sdrHasSdrConstraint_whenConcurrentDynamicRangesNotSupported() {
+        val characteristics = newCameraCharacteristicsCompat()
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            Shadow.extract<ShadowCameraCharacteristics>(
+                characteristics.toCameraCharacteristics()
+            ).addDynamicRangeProfiles(HLG10_CONSTRAINED)
+        }
+
+        val dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(characteristics)
+
+        assertThat(dynamicRangesCompat.getDynamicRangeCaptureRequestConstraints(SDR))
+            .containsExactly(SDR)
+    }
+}
+
+private const val CAMERA_ID = "0"
+
+@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+fun newCameraCharacteristicsCompat(): CameraCharacteristicsCompat {
+    return CameraCharacteristicsCompat.toCameraCharacteristicsCompat(
+        ShadowCameraCharacteristics.newCameraCharacteristics(),
+        CAMERA_ID
+    )
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+fun ShadowCameraCharacteristics.addDynamicRangeProfiles(
+    dynamicRangeProfiles: DynamicRangeProfiles
+) {
+    set(
+        CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES,
+        dynamicRangeProfiles
+    )
+}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt
index c485a90..c526cd1 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/concurrent/Camera2CameraCoordinatorTest.kt
@@ -16,16 +16,20 @@
 
 package androidx.camera.camera2.internal.concurrent
 
+import android.content.Context
 import android.hardware.camera2.CameraCharacteristics
 import android.hardware.camera2.CameraDevice
 import android.hardware.camera2.CameraManager
 import android.os.Build
+import androidx.camera.camera2.internal.Camera2CameraInfoImpl
 import androidx.camera.camera2.internal.compat.CameraManagerCompat
+import androidx.camera.core.CameraSelector
 import androidx.camera.core.concurrent.CameraCoordinator
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_SINGLE
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_UNSPECIFIED
 import androidx.camera.core.impl.utils.MainThreadAsyncHandler
+import androidx.camera.testing.fakes.FakeCameraInfoInternal
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.Executor
@@ -41,6 +45,10 @@
 import org.robolectric.RobolectricTestRunner
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadow.api.Shadow
+
+import org.robolectric.shadows.ShadowCameraCharacteristics
+import org.robolectric.shadows.ShadowCameraManager
 
 @RunWith(RobolectricTestRunner::class)
 @DoNotInstrument
@@ -50,6 +58,8 @@
 )
 class Camera2CameraCoordinatorTest {
 
+    private val mContext = ApplicationProvider.getApplicationContext<Context>()
+
     private lateinit var cameraCoordinator: CameraCoordinator
 
     @Before
@@ -82,24 +92,45 @@
         // Concurrent -> Single
         cameraCoordinator.cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
         assertThat(cameraCoordinator.concurrentCameraSelectors).isNotEmpty()
-        cameraCoordinator.activeConcurrentCameraSelectors =
-            cameraCoordinator.concurrentCameraSelectors[0]
-        assertThat(cameraCoordinator.activeConcurrentCameraSelectors).isNotEmpty()
+        cameraCoordinator.activeConcurrentCameraInfos =
+            listOf(FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_BACK))
+        assertThat(cameraCoordinator.activeConcurrentCameraInfos).isNotEmpty()
 
         cameraCoordinator.cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
-        assertThat(cameraCoordinator.activeConcurrentCameraSelectors).isEmpty()
+        assertThat(cameraCoordinator.activeConcurrentCameraInfos).isEmpty()
 
         // Concurrent -> Unspecified
         cameraCoordinator.cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
-        cameraCoordinator.activeConcurrentCameraSelectors =
-            cameraCoordinator.concurrentCameraSelectors[0]
+        cameraCoordinator.activeConcurrentCameraInfos =
+            listOf(FakeCameraInfoInternal(0, CameraSelector.LENS_FACING_BACK))
 
         cameraCoordinator.cameraOperatingMode = CAMERA_OPERATING_MODE_UNSPECIFIED
-        assertThat(cameraCoordinator.activeConcurrentCameraSelectors).isEmpty()
+        assertThat(cameraCoordinator.activeConcurrentCameraInfos).isEmpty()
     }
 
     @Test
     fun getPairedCameraId() {
+        val characteristics0 = ShadowCameraCharacteristics.newCameraCharacteristics()
+        (Shadow.extract<Any>(
+            ApplicationProvider.getApplicationContext<Context>()
+                .getSystemService(Context.CAMERA_SERVICE)
+        ) as ShadowCameraManager)
+            .addCamera("0", characteristics0)
+        val characteristics1 = ShadowCameraCharacteristics.newCameraCharacteristics()
+        (Shadow.extract<Any>(
+            ApplicationProvider.getApplicationContext<Context>()
+                .getSystemService(Context.CAMERA_SERVICE)
+        ) as ShadowCameraManager)
+            .addCamera("1", characteristics1)
+
+        val mCameraManagerCompat =
+            CameraManagerCompat.from((ApplicationProvider.getApplicationContext() as Context))
+
+        cameraCoordinator.activeConcurrentCameraInfos = listOf(
+            Camera2CameraInfoImpl("0", mCameraManagerCompat),
+            Camera2CameraInfoImpl("1", mCameraManagerCompat)
+        )
+
         assertThat(cameraCoordinator.getPairedConcurrentCameraId("0")).isEqualTo("1")
         assertThat(cameraCoordinator.getPairedConcurrentCameraId("1")).isEqualTo("0")
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/DynamicRange.java b/camera/camera-core/src/main/java/androidx/camera/core/DynamicRange.java
new file mode 100644
index 0000000..62c1199
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/DynamicRange.java
@@ -0,0 +1,176 @@
+/*
+ * 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.camera.core;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** A representation of the dynamic range of an image. */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public final class DynamicRange {
+    /** Standard Dynamic Range (SDR) format. */
+    public static final int FORMAT_SDR = 0;
+
+    //------------------------------------------------------------------------------//
+    //                            HDR Formats                                       //
+    //------------------------------------------------------------------------------//
+    /**
+     * An unspecified High Dynamic Range (HDR) format which allows the device to determine the
+     * underlying dynamic range format.
+     */
+    public static final int FORMAT_HDR_UNSPECIFIED = 1;
+    /** Hybrid Log Gamma (HLG) dynamic range format. */
+    public static final int FORMAT_HLG = FORMAT_HDR_UNSPECIFIED + 1;
+    /** HDR10 dynamic range format. */
+    public static final int FORMAT_HDR10 = FORMAT_HDR_UNSPECIFIED + 2;
+    /** HDR10+ dynamic range format. */
+    public static final int FORMAT_HDR10_PLUS = FORMAT_HDR_UNSPECIFIED + 3;
+    /** Dolby Vision dynamic range format. */
+    public static final int FORMAT_DOLBY_VISION = FORMAT_HDR_UNSPECIFIED + 4;
+    //------------------------------------------------------------------------------//
+
+    /** Bit depth is unspecified and may be determined automatically by the device. */
+    public static final int BIT_DEPTH_UNSPECIFIED = 0;
+    /** Eight-bit bit depth. */
+    public static final int BIT_DEPTH_8_BIT = 8;
+    /** Ten-bit bit depth. */
+    public static final int BIT_DEPTH_10_BIT = 10;
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({FORMAT_SDR, FORMAT_HDR_UNSPECIFIED, FORMAT_HLG, FORMAT_HDR10, FORMAT_HDR10_PLUS,
+            FORMAT_DOLBY_VISION})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DynamicRangeFormat {
+    }
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({BIT_DEPTH_UNSPECIFIED, BIT_DEPTH_8_BIT, BIT_DEPTH_10_BIT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BitDepth {
+    }
+
+    /** A dynamic range representing 8-bit standard dynamic range (SDR). */
+    @NonNull
+    public static final DynamicRange SDR = new DynamicRange(FORMAT_SDR, BIT_DEPTH_8_BIT);
+
+    /**
+     * A dynamic range representing 10-bit high dynamic range (HDR) with unspecified format.
+     *
+     * <p>The HDR format is unspecified, and may defer to device defaults
+     * when used to select a dynamic range.
+     */
+    @NonNull
+    public static final DynamicRange HDR_UNSPECIFIED_10_BIT =
+            new DynamicRange(FORMAT_HDR_UNSPECIFIED, BIT_DEPTH_10_BIT);
+
+    private final @DynamicRangeFormat int mFormat;
+    private final @BitDepth int mBitDepth;
+
+    /**
+     * Creates a dynamic range representation from a format and bit depth.
+     *
+     * <p>This constructor is left public for testing purposes. It does not do any verification that
+     * the provided arguments are a valid combination of format and bit depth.
+     *
+     * @param format   The dynamic range format.
+     * @param bitDepth The bit depth.
+     */
+    public DynamicRange(
+            @DynamicRangeFormat int format,
+            @BitDepth int bitDepth) {
+        mFormat = format;
+        mBitDepth = bitDepth;
+    }
+
+    /**
+     * Returns the dynamic range format.
+     *
+     * @return The dynamic range format. Possible values are {@link #FORMAT_SDR},
+     * {@link #FORMAT_HLG}, {@link #FORMAT_HDR10}, {@link #FORMAT_HDR10_PLUS}, or
+     * {@link #FORMAT_DOLBY_VISION}.
+     */
+    @DynamicRangeFormat
+    public int getFormat() {
+        return mFormat;
+    }
+
+    /**
+     * Returns the bit depth used by this dynamic range configuration.
+     *
+     * <p>Common values are {@link #BIT_DEPTH_8_BIT}, such as for {@link #FORMAT_SDR} or
+     * {@link #BIT_DEPTH_10_BIT}, such as for {@link #FORMAT_HDR10}.
+     *
+     * @return The bit depth. Possible values are {@link #BIT_DEPTH_8_BIT},
+     * {@link #BIT_DEPTH_10_BIT}, or {@link #BIT_DEPTH_UNSPECIFIED}.
+     */
+    @BitDepth
+    public int getBitDepth() {
+        return mBitDepth;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "DynamicRange@" + Integer.toHexString(System.identityHashCode(this)) + "{"
+                + "format=" + getFormatLabel(mFormat) + ", "
+                + "bitDepth=" + mBitDepth
+                + "}";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o instanceof DynamicRange) {
+            DynamicRange that = (DynamicRange) o;
+            return this.mFormat == that.getFormat()
+                    && this.mBitDepth == that.getBitDepth();
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int hashCode = 1;
+        hashCode *= 1000003;
+        hashCode ^= mFormat;
+        hashCode *= 1000003;
+        hashCode ^= mBitDepth;
+        return hashCode;
+    }
+
+    @NonNull
+    private static String getFormatLabel(@DynamicRangeFormat int format) {
+        switch (format) {
+            case FORMAT_SDR: return "FORMAT_SDR";
+            case FORMAT_HDR_UNSPECIFIED: return "FORMAT_HDR_UNSPECIFIED";
+            case FORMAT_HLG: return "FORMAT_HLG";
+            case FORMAT_HDR10: return "FORMAT_HDR10";
+            case FORMAT_HDR10_PLUS: return "FORMAT_HDR10_PLUS";
+            case FORMAT_DOLBY_VISION: return "FORMAT_DOLBY_VISION";
+        }
+
+        return "<Unknown>";
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java b/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java
index d9a231e..60d6be3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/concurrent/CameraCoordinator.java
@@ -24,6 +24,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.camera.core.CameraInfo;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.impl.CameraStateRegistry;
 
@@ -70,19 +71,19 @@
     List<List<CameraSelector>> getConcurrentCameraSelectors();
 
     /**
-     * Gets active concurrent camera selectors.
+     * Gets active concurrent camera infos.
      *
-     * @return list of active concurrent camera selectors.
+     * @return list of active concurrent camera infos.
      */
     @NonNull
-    List<CameraSelector> getActiveConcurrentCameraSelectors();
+    List<CameraInfo> getActiveConcurrentCameraInfos();
 
     /**
-     * Sets active concurrent camera selectors.
+     * Sets active concurrent camera infos.
      *
-     * @param cameraSelectors list of active concurrent camera selectors.
+     * @param cameraInfos list of active concurrent camera infos.
      */
-    void setActiveConcurrentCameraSelectors(@NonNull List<CameraSelector> cameraSelectors);
+    void setActiveConcurrentCameraInfos(@NonNull List<CameraInfo> cameraInfos);
 
     /**
      * Returns paired camera id in concurrent mode.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
index 66ff1c9..f7ec5a0 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraInfoInternal.java
@@ -121,6 +121,7 @@
                     throw new IllegalStateException("Unable to find camera with id " + cameraId
                             + " from list of available cameras.");
                 })
+                .addCameraFilter(new LensFacingCameraFilter(getLensFacing()))
                 .build();
     }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/SupportedOutputSizesSorter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/SupportedOutputSizesSorter.java
index 3072d63..ad15a23 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/SupportedOutputSizesSorter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/SupportedOutputSizesSorter.java
@@ -52,14 +52,14 @@
  * A class used to sort the supported output sizes according to the use case configs
  */
 @RequiresApi(21)
-class SupportedOutputSizesSorter {
+public class SupportedOutputSizesSorter {
     private static final String TAG = "SupportedOutputSizesCollector";
     private final CameraInfoInternal mCameraInfoInternal;
     private final Rational mFullFovRatio;
     private final boolean mIsSensorLandscapeResolution;
     private final SupportedOutputSizesSorterLegacy mSupportedOutputSizesSorterLegacy;
 
-    SupportedOutputSizesSorter(@NonNull CameraInfoInternal cameraInfoInternal) {
+    public SupportedOutputSizesSorter(@NonNull CameraInfoInternal cameraInfoInternal) {
         mCameraInfoInternal = cameraInfoInternal;
         mFullFovRatio = calculateFullFovRatio(mCameraInfoInternal);
         // Determines the sensor resolution orientation info by the full FOV ratio.
@@ -87,7 +87,7 @@
     }
 
     @NonNull
-    List<Size> getSortedSupportedOutputSizes(@NonNull UseCaseConfig<?> useCaseConfig) {
+    public List<Size> getSortedSupportedOutputSizes(@NonNull UseCaseConfig<?> useCaseConfig) {
         ImageOutputConfig imageOutputConfig = (ImageOutputConfig) useCaseConfig;
         List<Size> customOrderedResolutions = imageOutputConfig.getCustomOrderedResolutions(null);
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ParentSizeComparator.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ParentSizeComparator.java
new file mode 100644
index 0000000..9b528b8
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ParentSizeComparator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.camera.core.streamsharing;
+
+import static androidx.camera.core.internal.utils.SizeUtil.getArea;
+
+import static java.util.Objects.requireNonNull;
+
+import android.os.Build;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A comparator for sorting the {@link StreamSharing} parent Surface sizes.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+class ParentSizeComparator implements Comparator<Size> {
+    final Map<Size, Map<Integer, Integer>> mScores;
+    final List<Integer> mSortedPriorities;
+
+    /**
+     * Creates a new instance of {@link ParentSizeComparator}.
+     *
+     * @param scores     parent/child scores, in the form of <parent size, <child priority,
+     *                   score>>. Lower score is preferred.
+     * @param priorities a collection of child priorities.
+     */
+    ParentSizeComparator(@NonNull Map<Size, Map<Integer, Integer>> scores,
+            @NonNull Collection<Integer> priorities) {
+        mScores = scores;
+        mSortedPriorities = new ArrayList<>(priorities);
+        Collections.sort(mSortedPriorities, (value1, value2) -> value2 - value1);
+    }
+
+    @Override
+    public int compare(@NonNull Size size1, @NonNull Size size2) {
+        // Get the scores for the 2 sizes. The score is in the form of Map<Priority, Score>.
+        Map<Integer, Integer> scores1 = requireNonNull(mScores.get(size1));
+        Map<Integer, Integer> scores2 = requireNonNull(mScores.get(size2));
+        boolean hasValidScore = false;
+
+        // Loop thru all priorities in order, and compare their scores.
+        for (int priority : mSortedPriorities) {
+            int score1 = getScore(scores1, priority);
+            int score2 = getScore(scores2, priority);
+            if (score1 != score2) {
+                // Return early if the scores are different. Otherwise, continue to compare the
+                // next priorities.
+                return score1 - score2;
+            }
+            hasValidScore = hasValidScore || score1 != Integer.MAX_VALUE;
+        }
+        if (!hasValidScore) {
+            // If no valid score is found, prefer larger size in case upscaling is needed.
+            return getArea(size2) - getArea(size1);
+        }
+        // If scores are valid and equal, compare them by size. The smaller size is preferred
+        // because it means less memory is used.
+        return getArea(size1) - getArea(size2);
+    }
+
+    private int getScore(@NonNull Map<Integer, Integer> scores, int priority) {
+        Integer score = scores.get(priority);
+        if (score == null) {
+            return Integer.MAX_VALUE;
+        } else {
+            return score;
+        }
+    }
+
+    @VisibleForTesting
+    @NonNull
+    List<Integer> getSortedPriorities() {
+        return mSortedPriorities;
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionMerger.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionMerger.java
new file mode 100644
index 0000000..2106084
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionMerger.java
@@ -0,0 +1,177 @@
+/*
+ * 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.camera.core.streamsharing;
+
+import static androidx.camera.core.impl.UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
+import static androidx.camera.core.impl.utils.TransformUtils.rectToSize;
+import static androidx.core.util.Preconditions.checkState;
+
+import static java.util.Objects.requireNonNull;
+
+import android.os.Build;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.CameraInternal;
+import androidx.camera.core.impl.ImageFormatConstants;
+import androidx.camera.core.impl.UseCaseConfig;
+import androidx.camera.core.internal.SupportedOutputSizesSorter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A class for calculating parent resolutions based on the children's configs.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+class ResolutionMerger {
+
+    @NonNull
+    private final Size mSensorSize;
+    @NonNull
+    private final SupportedOutputSizesSorter mChildSizeSorter;
+    @NonNull
+    private final List<Size> mParentSizes;
+
+    ResolutionMerger(@NonNull CameraInternal cameraInternal) {
+        this(rectToSize(cameraInternal.getCameraControlInternal().getSensorRect()),
+                cameraInternal.getCameraInfoInternal());
+    }
+
+    private ResolutionMerger(@NonNull Size sensorSize,
+            @NonNull CameraInfoInternal cameraInfoInternal) {
+        this(sensorSize, new SupportedOutputSizesSorter(cameraInfoInternal),
+                cameraInfoInternal.getSupportedResolutions(
+                        ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE));
+    }
+
+    ResolutionMerger(@NonNull Size sensorSize,
+            @NonNull SupportedOutputSizesSorter supportedOutputSizesSorter,
+            @NonNull List<Size> parentSizes) {
+        mSensorSize = sensorSize;
+        mChildSizeSorter = supportedOutputSizesSorter;
+        mParentSizes = parentSizes;
+    }
+
+    /**
+     * Returns a list of parent resolution sorted by preference.
+     *
+     * <p> This method calculates the resolution for the parent {@link StreamSharing} based on 1)
+     * the supported PRIV resolutions, 2) the sensor size and 3) the children's configs.
+     */
+    List<Size> getMergedResolutions(@NonNull Set<UseCaseConfig<?>> childrenConfigs) {
+        List<Size> parentSizes = new ArrayList<>(mParentSizes);
+        Set<Integer> priorities = new HashSet<>();
+        // Parent/child scores, in the form of <parent size, <child priority, score>>.
+        Map<Size, Map<Integer, Integer>> parentSizeScores = new HashMap<>();
+
+        for (UseCaseConfig<?> childConfig : childrenConfigs) {
+            // Get sorted child sizes.
+            List<Size> childrenSizes = mChildSizeSorter.getSortedSupportedOutputSizes(childConfig);
+
+            // Get child's Surface priority
+            int childPriority = requireNonNull(childConfig.retrieveOption(
+                    OPTION_SURFACE_OCCUPANCY_PRIORITY, null));
+            checkState(!priorities.contains(childPriority),
+                    "No 2 UseCases can have the same Surface priority.");
+            priorities.add(childPriority);
+
+            // Score parent sizes against this child.
+            for (Size parentSize : mParentSizes) {
+                int parentChildScore = scoreParentAgainstChild(
+                        parentSize, mSensorSize, childrenSizes);
+                if (!parentSizeScores.containsKey(parentSize)) {
+                    parentSizeScores.put(parentSize, new HashMap<>());
+                }
+                requireNonNull(parentSizeScores.get(parentSize))
+                        .put(childPriority, parentChildScore);
+            }
+        }
+
+        // Sort parent sizes by scores.
+        Collections.sort(parentSizes, new ParentSizeComparator(parentSizeScores, priorities));
+        return parentSizes;
+    }
+
+    /**
+     * Scores the given parent size given the child's sorted sizes.
+     *
+     * <p> The score is the index of the highest ranking child size that works with the parent
+     * size without upscaling or double cropping. If no child size works with the parent size, it
+     * returns {@link Integer#MAX_VALUE}.
+     */
+    static int scoreParentAgainstChild(@NonNull Size parentSize, @NonNull Size sensorSize,
+            @NonNull List<Size> childSizes) {
+        for (int i = 0; i < childSizes.size(); i++) {
+            Size childSize = childSizes.get(i);
+            if (hasUpscaling(childSize, parentSize)) {
+                continue;
+            }
+            if (isDoubleCropping(childSize, parentSize, sensorSize)) {
+                continue;
+            }
+            return i;
+        }
+        // The parent size does not work with any of the children sizes..
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * Whether the parent size needs upscaling to fill the child size.
+     */
+    private static boolean hasUpscaling(@NonNull Size childSize, @NonNull Size parentSize) {
+        // Upscaling is needed if child size is larger than the parent.
+        return childSize.getHeight() > parentSize.getHeight()
+                || childSize.getWidth() > parentSize.getWidth();
+    }
+
+    /**
+     * Whether there is double cropping, given the child size, parent size and sensor size.
+     */
+    static boolean isDoubleCropping(@NonNull Size child, @NonNull Size parent,
+            @NonNull Size sensor) {
+        // Crop the sensor size by the parent size.
+        Size afterCroppingParent = getCroppedSize(sensor, parent);
+        // Crop the result again by the child size.
+        Size afterCroppingChild = getCroppedSize(afterCroppingParent, child);
+        // If the result is smaller than the sensor in both width/height, then it's double cropping.
+        return afterCroppingChild.getWidth() < sensor.getWidth()
+                && afterCroppingChild.getHeight() < sensor.getHeight();
+    }
+
+    /**
+     * Returns the size after cropping the original size by the crop size.
+     */
+    static Size getCroppedSize(@NonNull Size original, @NonNull Size crop) {
+        float cropAspectRatio = (float) crop.getWidth() / crop.getHeight();
+        float originalAspectRatio = (float) original.getWidth() / original.getHeight();
+        if (originalAspectRatio > cropAspectRatio) {
+            return new Size(original.getHeight() * crop.getWidth() / crop.getHeight(),
+                    original.getHeight());
+        } else {
+            return new Size(original.getWidth(),
+                    original.getWidth() * crop.getHeight() / crop.getWidth());
+        }
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionUtils.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionUtils.java
deleted file mode 100644
index 7b93c0b..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/ResolutionUtils.java
+++ /dev/null
@@ -1,63 +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.camera.core.streamsharing;
-
-import static androidx.camera.core.impl.ImageOutputConfig.OPTION_CUSTOM_ORDERED_RESOLUTIONS;
-
-import android.os.Build;
-import android.util.Size;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.UseCaseConfig;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Utility methods for calculating resolutions.
- */
-@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-class ResolutionUtils {
-
-    private ResolutionUtils() {
-    }
-
-    /**
-     * Returns a list of {@link Surface} resolution sorted by priority.
-     *
-     * <p> This method calculates the resolution for the parent {@link StreamSharing} based on 1)
-     * the supported PRIV resolutions, 2) the sensor size and 3) the children's configs.
-     */
-    static List<Size> getMergedResolutions(
-            @NonNull List<Size> supportedResolutions,
-            @NonNull Size sensorSize,
-            @NonNull Set<UseCaseConfig<?>> useCaseConfigs) {
-        // TODO(b/264936115): This is a temporary placeholder solution that returns the config of
-        //  VideoCapture if it exists. Later we will update it to actually merge the children's
-        //  configs.
-        for (UseCaseConfig<?> useCaseConfig : useCaseConfigs) {
-            List<Size> customOrderedResolutions =
-                    useCaseConfig.retrieveOption(OPTION_CUSTOM_ORDERED_RESOLUTIONS, null);
-            if (customOrderedResolutions != null) {
-                return customOrderedResolutions;
-            }
-        }
-        return supportedResolutions;
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
index b652892..ea71c293 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
@@ -22,13 +22,11 @@
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
 import static androidx.camera.core.impl.utils.Threads.checkMainThread;
 import static androidx.camera.core.impl.utils.TransformUtils.rectToSize;
-import static androidx.camera.core.streamsharing.ResolutionUtils.getMergedResolutions;
 import static androidx.core.util.Preconditions.checkState;
 
 import static java.util.Objects.requireNonNull;
 
 import android.os.Build;
-import android.util.Size;
 
 import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
@@ -52,7 +50,6 @@
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -87,6 +84,8 @@
     // The callback that receives the parent camera's metadata.
     @NonNull
     private final CameraCaptureCallback mParentMetadataCallback = createCameraCaptureCallback();
+    @NonNull
+    private final ResolutionMerger mResolutionMerger;
 
     /**
      * @param parentCamera         the parent {@link CameraInternal} instance. For example, the
@@ -100,6 +99,7 @@
         mParentCamera = parentCamera;
         mUseCaseConfigFactory = useCaseConfigFactory;
         mChildren = children;
+        mResolutionMerger = new ResolutionMerger(parentCamera);
         // Set children state to inactive by default.
         for (UseCase child : children) {
             mChildrenActiveState.put(child, false);
@@ -116,13 +116,8 @@
         }
 
         // Merge resolution configs.
-        List<Size> supportedResolutions =
-                new ArrayList<>(mParentCamera.getCameraInfoInternal().getSupportedResolutions(
-                        INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE));
-        Size sensorSize = rectToSize(mParentCamera.getCameraControlInternal().getSensorRect());
         mutableConfig.insertOption(OPTION_CUSTOM_ORDERED_RESOLUTIONS,
-                getMergedResolutions(supportedResolutions, sensorSize,
-                        childrenConfigs));
+                mResolutionMerger.getMergedResolutions(childrenConfigs));
 
         // Merge Surface occupancy priority.
         mutableConfig.insertOption(OPTION_SURFACE_OCCUPANCY_PRIORITY,
@@ -357,8 +352,9 @@
             @NonNull CameraCaptureResult cameraCaptureResult,
             @NonNull SessionConfig sessionConfig) {
         for (CameraCaptureCallback callback : sessionConfig.getRepeatingCameraCaptureCallbacks()) {
-            callback.onCaptureCompleted(new VirtualCameraCaptureResult(cameraCaptureResult,
-                    sessionConfig.getRepeatingCaptureConfig().getTagBundle()));
+            callback.onCaptureCompleted(new VirtualCameraCaptureResult(
+                    sessionConfig.getRepeatingCaptureConfig().getTagBundle(),
+                    cameraCaptureResult));
         }
     }
 
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResult.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResult.java
index 3e96bc0..7f8a7dd 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResult.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResult.java
@@ -19,6 +19,7 @@
 import android.os.Build;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.camera.core.impl.CameraCaptureMetaData;
 import androidx.camera.core.impl.CameraCaptureResult;
@@ -31,20 +32,45 @@
 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public class VirtualCameraCaptureResult implements CameraCaptureResult {
 
-    @NonNull
+    private static final long INVALID_TIMESTAMP = -1;
+
+    @Nullable
     private final CameraCaptureResult mBaseCameraCaptureResult;
     @NonNull
     private final TagBundle mTagBundle;
+    private final long mTimestamp;
 
     /**
+     * Creates an instance based on another {@link CameraCaptureResult}.
+     *
      * @param baseCameraCaptureResult Most of the fields return the value of the base instance.
      * @param tagBundle               the overridden value for the {@link #getTagBundle()} field.
      */
-    VirtualCameraCaptureResult(
-            @NonNull CameraCaptureResult baseCameraCaptureResult,
-            @NonNull TagBundle tagBundle) {
+    public VirtualCameraCaptureResult(
+            @NonNull TagBundle tagBundle,
+            @Nullable CameraCaptureResult baseCameraCaptureResult) {
+        this(baseCameraCaptureResult, tagBundle, INVALID_TIMESTAMP);
+    }
+
+    /**
+     * Creates empty instance with timestamp overridden.
+     *
+     * @param tagBundle the overridden value for the {@link #getTagBundle()} field.
+     * @param timestamp the overridden value for the {@link #getTimestamp()} field.
+     */
+    public VirtualCameraCaptureResult(
+            @NonNull TagBundle tagBundle,
+            long timestamp) {
+        this(/*baseCameraCaptureResult*/null, tagBundle, timestamp);
+    }
+
+    private VirtualCameraCaptureResult(
+            @Nullable CameraCaptureResult baseCameraCaptureResult,
+            @NonNull TagBundle tagBundle,
+            long timestamp) {
         mBaseCameraCaptureResult = baseCameraCaptureResult;
         mTagBundle = tagBundle;
+        mTimestamp = timestamp;
     }
 
     @NonNull
@@ -57,35 +83,45 @@
     @NonNull
     @Override
     public CameraCaptureMetaData.AfMode getAfMode() {
-        return mBaseCameraCaptureResult.getAfMode();
+        return mBaseCameraCaptureResult != null ? mBaseCameraCaptureResult.getAfMode() :
+                CameraCaptureMetaData.AfMode.UNKNOWN;
     }
 
     @NonNull
     @Override
     public CameraCaptureMetaData.AfState getAfState() {
-        return mBaseCameraCaptureResult.getAfState();
+        return mBaseCameraCaptureResult != null ? mBaseCameraCaptureResult.getAfState() :
+                CameraCaptureMetaData.AfState.UNKNOWN;
     }
 
     @NonNull
     @Override
     public CameraCaptureMetaData.AeState getAeState() {
-        return mBaseCameraCaptureResult.getAeState();
+        return mBaseCameraCaptureResult != null ? mBaseCameraCaptureResult.getAeState() :
+                CameraCaptureMetaData.AeState.UNKNOWN;
     }
 
     @NonNull
     @Override
     public CameraCaptureMetaData.AwbState getAwbState() {
-        return mBaseCameraCaptureResult.getAwbState();
+        return mBaseCameraCaptureResult != null ? mBaseCameraCaptureResult.getAwbState() :
+                CameraCaptureMetaData.AwbState.UNKNOWN;
     }
 
     @NonNull
     @Override
     public CameraCaptureMetaData.FlashState getFlashState() {
-        return mBaseCameraCaptureResult.getFlashState();
+        return mBaseCameraCaptureResult != null ? mBaseCameraCaptureResult.getFlashState() :
+                CameraCaptureMetaData.FlashState.UNKNOWN;
     }
 
     @Override
     public long getTimestamp() {
-        return mBaseCameraCaptureResult.getTimestamp();
+        if (mBaseCameraCaptureResult != null) {
+            return mBaseCameraCaptureResult.getTimestamp();
+        } else if (mTimestamp != INVALID_TIMESTAMP) {
+            return mTimestamp;
+        }
+        throw new IllegalStateException("No timestamp is available.");
     }
 }
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/DynamicRangeTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/DynamicRangeTest.kt
new file mode 100644
index 0000000..c89e49a
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/DynamicRangeTest.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.camera.core
+
+import android.os.Build
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class DynamicRangeTest {
+
+    @Test
+    fun canCreateUnspecifiedDynamicRange() {
+        val dynamicRange = DynamicRange(
+            DynamicRange.FORMAT_HDR_UNSPECIFIED,
+            DynamicRange.BIT_DEPTH_UNSPECIFIED
+        )
+        assertThat(dynamicRange.format).isEqualTo(DynamicRange.FORMAT_HDR_UNSPECIFIED)
+        assertThat(dynamicRange.bitDepth).isEqualTo(DynamicRange.BIT_DEPTH_UNSPECIFIED)
+    }
+
+    @Test
+    fun sdrDynamicRange_is8Bit() {
+        assertThat(DynamicRange.SDR.format).isEqualTo(DynamicRange.FORMAT_SDR)
+        assertThat(DynamicRange.SDR.bitDepth).isEqualTo(DynamicRange.BIT_DEPTH_8_BIT)
+    }
+}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ParentSizeComparatorTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ParentSizeComparatorTest.kt
new file mode 100644
index 0000000..27ba866
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ParentSizeComparatorTest.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.camera.core.streamsharing
+
+import android.os.Build
+import android.util.Size
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+/**
+ * Unit tests for [ParentSizeComparator].
+ */
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class ParentSizeComparatorTest {
+
+    companion object {
+        const val PREVIEW_PRIORITY = 2
+        const val VIDEO_PRIORITY = 5
+        val SIZE_1600_900 = Size(1600, 900)
+        val SIZE_1800_900 = Size(1800, 900)
+        val SIZE_800_600 = Size(800, 600)
+        val SIZE_400_300 = Size(400, 300)
+        val SIZE_500_400 = Size(500, 400)
+        val SIZE_1024_768 = Size(1024, 768)
+        val SIZE_2048_1536 = Size(2048, 1536)
+        val SIZES = listOf(
+            SIZE_1800_900,
+            SIZE_1600_900,
+            SIZE_500_400,
+            SIZE_400_300,
+            SIZE_800_600,
+            SIZE_2048_1536,
+            SIZE_1024_768
+        )
+        val PRIORITIES = listOf(PREVIEW_PRIORITY, VIDEO_PRIORITY)
+    }
+
+    @Test
+    fun priorityIsSorted() {
+        val comparator = ParentSizeComparator(mapOf(), PRIORITIES)
+        assertThat(comparator.sortedPriorities).containsExactly(5, 2).inOrder()
+    }
+
+    @Test
+    fun sizeSortedByPriorityRankingAndSize() {
+        val map = mapOf(
+            // Video has higher priority so its ranking is the deciding factor.
+            Pair(SIZE_500_400, mapOf(Pair(VIDEO_PRIORITY, 0), Pair(PREVIEW_PRIORITY, 3))),
+            // When video ranking is the same, preview ranking is the deciding factor.
+            Pair(SIZE_1800_900, mapOf(Pair(VIDEO_PRIORITY, 1), Pair(PREVIEW_PRIORITY, 1))),
+            Pair(SIZE_1600_900, mapOf(Pair(VIDEO_PRIORITY, 1), Pair(PREVIEW_PRIORITY, 2))),
+            // When preview ranking is the same or missing, the size is the deciding factor.
+            Pair(SIZE_800_600, mapOf(Pair(VIDEO_PRIORITY, 2), Pair(PREVIEW_PRIORITY, 1))),
+            Pair(SIZE_400_300, mapOf(Pair(VIDEO_PRIORITY, 2), Pair(PREVIEW_PRIORITY, 1))),
+            Pair(SIZE_1024_768, mapOf()),
+            Pair(SIZE_2048_1536, mapOf()),
+        )
+        val result = SIZES.sortedWith(ParentSizeComparator(map, PRIORITIES))
+        assertThat(result).containsExactly(
+            SIZE_500_400,
+            SIZE_1800_900,
+            SIZE_1600_900,
+            SIZE_400_300,
+            SIZE_800_600,
+            SIZE_2048_1536,
+            SIZE_1024_768
+        ).inOrder()
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ResolutionMergerTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ResolutionMergerTest.kt
new file mode 100644
index 0000000..4700161
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/ResolutionMergerTest.kt
@@ -0,0 +1,178 @@
+/*
+ * 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.camera.core.streamsharing
+
+import android.os.Build
+import android.util.Size
+import androidx.camera.core.impl.UseCaseConfig
+import androidx.camera.core.streamsharing.ResolutionMerger.getCroppedSize
+import androidx.camera.core.streamsharing.ResolutionMerger.isDoubleCropping
+import androidx.camera.core.streamsharing.ResolutionMerger.scoreParentAgainstChild
+import androidx.camera.testing.fakes.FakeSupportedOutputSizesSorter
+import androidx.camera.testing.fakes.FakeUseCaseConfig
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+/**
+ * Unit tests for [ResolutionMerger].
+ */
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class ResolutionMergerTest {
+
+    companion object {
+        val SIZE_1600_900 = Size(1600, 900)
+        val SIZE_1800_900 = Size(1800, 900)
+        val SIZE_400_300 = Size(400, 300)
+        val SIZE_500_400 = Size(500, 400)
+        val SIZES = listOf(SIZE_1800_900, SIZE_1600_900, SIZE_500_400, SIZE_400_300)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun mergeChildrenWithSamePriority_throwsException() {
+        // Arrange: 2 children with same priority
+        val useCaseConfig1 = createUseCaseConfig(1)
+        val useCaseConfig2 = createUseCaseConfig(1)
+        val fakeSupportedOutputSizesSorter = FakeSupportedOutputSizesSorter(
+            mapOf(useCaseConfig1 to SIZES, useCaseConfig2 to SIZES)
+        )
+        val merger = ResolutionMerger(Size(1600, 900), fakeSupportedOutputSizesSorter, SIZES)
+        // Act.
+        merger.getMergedResolutions(setOf(useCaseConfig1, useCaseConfig2))
+    }
+
+    @Test
+    fun getMergedResolutions_prioritizesHighPriorityChild() {
+        // Arrange: 2 children with different priority.
+        val sensorSize = Size(1600, 900)
+        val useCaseConfig1 = createUseCaseConfig(1)
+        val useCaseSizes1 = listOf(SIZE_1800_900, SIZE_1600_900, SIZE_500_400, SIZE_400_300)
+        val useCaseConfig2 = createUseCaseConfig(2)
+        val useCaseSizes2 = listOf(SIZE_400_300, SIZE_500_400, SIZE_1800_900, SIZE_1600_900)
+        val fakeSupportedOutputSizesSorter = FakeSupportedOutputSizesSorter(
+            mapOf(useCaseConfig1 to useCaseSizes1, useCaseConfig2 to useCaseSizes2)
+        )
+        val merger = ResolutionMerger(sensorSize, fakeSupportedOutputSizesSorter, SIZES)
+
+        // Act.
+        val result = merger.getMergedResolutions(setOf(useCaseConfig1, useCaseConfig2))
+
+        // Assert:
+        assertThat(result).containsExactly(
+            SIZE_1600_900, // works for both children so it's the first.
+            SIZE_400_300, // 1st for the child2 but require upscaling for child1.
+            SIZE_500_400, // 2st for the child2 but require upscaling for child1
+            SIZE_1800_900 // 3rd for the child2 but require double cropping for child1
+        ).inOrder()
+    }
+
+    @Test
+    fun getCroppedSize_returnsTheLargestSize() {
+        // Arrange.
+        val parent = Size(16, 9)
+        val sensor = Size(1600, 1200)
+        // Act.
+        val croppedSize = getCroppedSize(sensor, parent)
+        // Assert.
+        assertThat(croppedSize).isEqualTo(SIZE_1600_900)
+    }
+
+    @Test
+    fun largeParentSize_matchesTheLargestChild() {
+        // Arrange.
+        val parent = Size(4000, 3000)
+        val sensor = Size(8000, 6000)
+        // Act.
+        val score = scoreParentAgainstChild(parent, sensor, SIZES)
+        // Assert: Score is the index of SIZE_1800_900.
+        assertThat(SIZES[score]).isEqualTo(SIZE_1800_900)
+    }
+
+    @Test
+    fun smallParentSize_matchesTheChildWithNoUpscaling() {
+        // Arrange.
+        val parent = Size(400, 300)
+        val sensor = Size(4000, 3000)
+        // Act.
+        val score = scoreParentAgainstChild(parent, sensor, SIZES)
+        // Assert: Score is the index of SIZE_400_300 because others requires upscaling.
+        assertThat(SIZES[score]).isEqualTo(SIZE_400_300)
+    }
+
+    @Test
+    fun squareParentSize_scoreIsMaxValue() {
+        // Arrange.
+        val parent = Size(1000, 1000)
+        val sensor = Size(4000, 3000)
+        // Act.
+        val score = scoreParentAgainstChild(parent, sensor, SIZES)
+        // Assert: Score is Integer.MAX_VALUE because all sizes require double cropping.
+        assertThat(score).isEqualTo(Integer.MAX_VALUE)
+    }
+
+    @Test
+    fun narrowerParentSize_skipsDoubleCropping() {
+        // Arrange.
+        val parent = Size(3800, 3000)
+        val sensor = Size(4000, 3000)
+        // Act.
+        val score = scoreParentAgainstChild(parent, sensor, SIZES)
+        // Assert: Score is SIZE_500_400 because all other require double cropping.
+        assertThat(SIZES[score]).isEqualTo(SIZE_500_400)
+    }
+
+    @Test
+    fun cropWiderThanOriginal() {
+        assertThat(getCroppedSize(SIZE_400_300, SIZE_1600_900)).isEqualTo(Size(400, 225))
+    }
+
+    @Test
+    fun cropNarrowerThanOriginal() {
+        assertThat(getCroppedSize(SIZE_1600_900, SIZE_400_300)).isEqualTo(Size(1200, 900))
+    }
+
+    @Test
+    fun parentEqualsSensor_noDoubleCropping() {
+        assertThat(isDoubleCropping(SIZE_400_300, SIZE_1600_900, SIZE_1600_900)).isFalse()
+    }
+
+    @Test
+    fun parentWiderThanSensor_childNarrowerThanSensor_isDoubleCropping() {
+        assertThat(isDoubleCropping(SIZE_1600_900, SIZE_500_400, SIZE_400_300)).isTrue()
+    }
+
+    @Test
+    fun childWiderThanSensor_parentNarrowerThanSensor_isDoubleCropping() {
+        assertThat(isDoubleCropping(SIZE_500_400, SIZE_1600_900, SIZE_400_300)).isTrue()
+    }
+
+    @Test
+    fun parentWiderThanSensorButNarrowerThanChild_noDoubleCropping() {
+        assertThat(isDoubleCropping(SIZE_1800_900, SIZE_1600_900, SIZE_400_300)).isFalse()
+    }
+
+    private fun createUseCaseConfig(priority: Int): UseCaseConfig<*> {
+        val config = FakeUseCaseConfig.Builder().mutableConfig
+        config.insertOption(UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY, priority)
+        return FakeUseCaseConfig.Builder(config).useCaseConfig
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResultTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResultTest.kt
new file mode 100644
index 0000000..ff0e72e
--- /dev/null
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraCaptureResultTest.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.camera.core.streamsharing
+
+import android.os.Build
+import android.util.Pair
+import androidx.camera.core.impl.CameraCaptureMetaData
+import androidx.camera.core.impl.TagBundle
+import androidx.camera.testing.fakes.FakeCameraCaptureResult
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+
+/**
+ * Unit tests for [VirtualCameraCaptureResult].
+ */
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class VirtualCameraCaptureResultTest {
+
+    companion object {
+        private const val KEY = "key"
+        private const val VALUE = "value"
+        private val TAG_BUNDLE = TagBundle.create(Pair(KEY, VALUE))
+    }
+
+    @Test
+    fun metadataWithTimestamp_overrideTimestamp() {
+        // Act.
+        val result = VirtualCameraCaptureResult(TAG_BUNDLE, 1L)
+        // Assert.
+        assertThat(result.timestamp).isEqualTo(1L)
+        assertThat(result.tagBundle).isEqualTo(TAG_BUNDLE)
+        assertThat(result.aeState).isEqualTo(CameraCaptureMetaData.AeState.UNKNOWN)
+        assertThat(result.afState).isEqualTo(CameraCaptureMetaData.AfState.UNKNOWN)
+        assertThat(result.awbState).isEqualTo(CameraCaptureMetaData.AwbState.UNKNOWN)
+        assertThat(result.flashState).isEqualTo(CameraCaptureMetaData.FlashState.UNKNOWN)
+        assertThat(result.afMode).isEqualTo(CameraCaptureMetaData.AfMode.UNKNOWN)
+    }
+
+    @Test
+    fun metadataWithBaseValue_returnBaseValue() {
+        // Arrange.
+        val baseCameraCaptureResult = FakeCameraCaptureResult().apply {
+            timestamp = 2L
+            aeState = CameraCaptureMetaData.AeState.CONVERGED
+            afState = CameraCaptureMetaData.AfState.LOCKED_FOCUSED
+            awbState = CameraCaptureMetaData.AwbState.CONVERGED
+            flashState = CameraCaptureMetaData.FlashState.FIRED
+            afMode = CameraCaptureMetaData.AfMode.ON_CONTINUOUS_AUTO
+        }
+        // Act.
+        val result = VirtualCameraCaptureResult(TAG_BUNDLE, baseCameraCaptureResult)
+        // Assert.
+        assertThat(result.timestamp).isEqualTo(baseCameraCaptureResult.timestamp)
+        assertThat(result.tagBundle).isEqualTo(TAG_BUNDLE)
+        assertThat(result.aeState).isEqualTo(baseCameraCaptureResult.aeState)
+        assertThat(result.afState).isEqualTo(baseCameraCaptureResult.afState)
+        assertThat(result.awbState).isEqualTo(baseCameraCaptureResult.awbState)
+        assertThat(result.flashState).isEqualTo(baseCameraCaptureResult.flashState)
+        assertThat(result.afMode).isEqualTo(baseCameraCaptureResult.afMode)
+    }
+}
\ No newline at end of file
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 88864f7..fdeb96f5 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
@@ -20,6 +20,7 @@
 import android.content.Context
 import android.content.ContextWrapper
 import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FEATURE_CAMERA_CONCURRENT
 import androidx.annotation.OptIn
 import androidx.annotation.RequiresApi
 import androidx.camera.core.CameraSelector
@@ -695,13 +696,19 @@
                 .setCameraConfigs(listOf(singleCameraConfig0, singleCameraConfig1))
                 .build()
 
-            val concurrentCamera = provider.bindToLifecycle(concurrentCameraConfig)
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                val concurrentCamera = provider.bindToLifecycle(concurrentCameraConfig)
 
-            assertThat(concurrentCamera).isNotNull()
-            assertThat(concurrentCamera.cameras.size).isEqualTo(2)
-            assertThat(provider.isBound(useCase0)).isTrue()
-            assertThat(provider.isBound(useCase1)).isTrue()
-            assertThat(provider.isConcurrentCameraModeOn).isTrue()
+                assertThat(concurrentCamera).isNotNull()
+                assertThat(concurrentCamera.cameras.size).isEqualTo(2)
+                assertThat(provider.isBound(useCase0)).isTrue()
+                assertThat(provider.isBound(useCase1)).isTrue()
+                assertThat(provider.isConcurrentCameraModeOn).isTrue()
+            } else {
+                assertThrows<UnsupportedOperationException> {
+                    provider.bindToLifecycle(concurrentCameraConfig)
+                }
+            }
         }
     }
 
@@ -742,25 +749,37 @@
                 .setCameraConfigs(listOf(singleCameraConfig0, singleCameraConfig1))
                 .build()
 
-            val concurrentCamera0 = provider.bindToLifecycle(concurrentCameraConfig0)
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                val concurrentCamera0 = provider.bindToLifecycle(concurrentCameraConfig0)
 
-            assertThat(concurrentCamera0).isNotNull()
-            assertThat(concurrentCamera0.cameras.size).isEqualTo(2)
-            assertThat(provider.isBound(useCase0)).isTrue()
-            assertThat(provider.isBound(useCase1)).isTrue()
-            assertThat(provider.isConcurrentCameraModeOn).isTrue()
+                assertThat(concurrentCamera0).isNotNull()
+                assertThat(concurrentCamera0.cameras.size).isEqualTo(2)
+                assertThat(provider.isBound(useCase0)).isTrue()
+                assertThat(provider.isBound(useCase1)).isTrue()
+                assertThat(provider.isConcurrentCameraModeOn).isTrue()
+            } else {
+                assertThrows<UnsupportedOperationException> {
+                    provider.bindToLifecycle(concurrentCameraConfig0)
+                }
+            }
 
             val concurrentCameraConfig1 = ConcurrentCameraConfig.Builder()
                 .setCameraConfigs(listOf(singleCameraConfig0, singleCameraConfig2))
                 .build()
 
-            val concurrentCamera1 = provider.bindToLifecycle(concurrentCameraConfig1)
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                val concurrentCamera1 = provider.bindToLifecycle(concurrentCameraConfig1)
 
-            assertThat(concurrentCamera1).isNotNull()
-            assertThat(concurrentCamera1.cameras.size).isEqualTo(2)
-            assertThat(provider.isBound(useCase0)).isTrue()
-            assertThat(provider.isBound(useCase2)).isTrue()
-            assertThat(provider.isConcurrentCameraModeOn).isTrue()
+                assertThat(concurrentCamera1).isNotNull()
+                assertThat(concurrentCamera1.cameras.size).isEqualTo(2)
+                assertThat(provider.isBound(useCase0)).isTrue()
+                assertThat(provider.isBound(useCase2)).isTrue()
+                assertThat(provider.isConcurrentCameraModeOn).isTrue()
+            } else {
+                assertThrows<UnsupportedOperationException> {
+                    provider.bindToLifecycle(concurrentCameraConfig0)
+                }
+            }
         }
     }
 
@@ -784,10 +803,16 @@
                 .setCameraConfigs(listOf(singleCameraConfig0))
                 .build()
 
-            assertThrows<IllegalArgumentException> {
-                provider.bindToLifecycle(concurrentCameraConfig)
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                assertThrows<IllegalArgumentException> {
+                    provider.bindToLifecycle(concurrentCameraConfig)
+                }
+                assertThat(provider.isConcurrentCameraModeOn).isFalse()
+            } else {
+                assertThrows<UnsupportedOperationException> {
+                    provider.bindToLifecycle(concurrentCameraConfig)
+                }
             }
-            assertThat(provider.isConcurrentCameraModeOn).isFalse()
         }
     }
 
@@ -830,10 +855,16 @@
                     singleCameraConfig2))
                 .build()
 
-            assertThrows<UnsupportedOperationException> {
-                provider.bindToLifecycle(concurrentCameraConfig)
+            if (context.packageManager.hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+                assertThrows<IllegalArgumentException> {
+                    provider.bindToLifecycle(concurrentCameraConfig)
+                }
+                assertThat(provider.isConcurrentCameraModeOn).isFalse()
+            } else {
+                assertThrows<java.lang.UnsupportedOperationException> {
+                    provider.bindToLifecycle(concurrentCameraConfig)
+                }
             }
-            assertThat(provider.isConcurrentCameraModeOn).isFalse()
         }
     }
 
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
index d7c7640..d56893e 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.lifecycle;
 
+import static android.content.pm.PackageManager.FEATURE_CAMERA_CONCURRENT;
+
 import static androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT;
 import static androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_SINGLE;
 import static androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_UNSPECIFIED;
@@ -26,6 +28,7 @@
 
 import android.app.Application;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 
 import androidx.annotation.GuardedBy;
@@ -415,14 +418,16 @@
      *
      * <p>The concurrent camera is only supporting two cameras currently. If the input
      * {@link ConcurrentCameraConfig} has less or more than two {@link SingleCameraConfig},
-     * {@link IllegalArgumentException} will be thrown.
+     * {@link IllegalArgumentException} will be thrown. If the device is not supporting
+     * {@link PackageManager#FEATURE_CAMERA_CONCURRENT} or cameras are already used by other
+     * {@link UseCase}s, {@link UnsupportedOperationException} will be thrown.
      *
      * @param concurrentCameraConfig input configuration for concurrent camera.
      * @return output concurrent camera instance.
      *
-     * @throws IllegalArgumentException If less than two camera configs are provided.
-     * @throws UnsupportedOperationException If more than two camera configs are provides or
-     * there is single camera already running.
+     * @throws IllegalArgumentException If less or more than two camera configs are provided.
+     * @throws UnsupportedOperationException If device is not supporting concurrent camera or
+     * cameras are already used by other {@link UseCase}s.
      *
      * @hide
      */
@@ -432,13 +437,9 @@
     @NonNull
     public ConcurrentCamera bindToLifecycle(
             @NonNull ConcurrentCameraConfig concurrentCameraConfig) {
-        if (concurrentCameraConfig.getSingleCameraConfigs().size() < 2) {
-            throw new IllegalArgumentException("Concurrent camera needs two camera configs");
-        }
-
-        if (concurrentCameraConfig.getSingleCameraConfigs().size() > 2) {
-            throw new UnsupportedOperationException("Concurrent camera is only supporting two  "
-                    + "cameras at maximum.");
+        if (!mContext.getPackageManager().hasSystemFeature(FEATURE_CAMERA_CONCURRENT)) {
+            throw new UnsupportedOperationException("Concurrent camera is not supported on the "
+                    + "device");
         }
 
         if (getCameraOperatingMode() == CAMERA_OPERATING_MODE_SINGLE) {
@@ -446,13 +447,30 @@
                     + "unbindAll() before binding more cameras");
         }
 
-        List<CameraSelector> cameraSelectorsToBind = new ArrayList<>();
-        cameraSelectorsToBind.add(
-                concurrentCameraConfig.getSingleCameraConfigs().get(0).getCameraSelector());
-        cameraSelectorsToBind.add(
-                concurrentCameraConfig.getSingleCameraConfigs().get(1).getCameraSelector());
-        if (!getActiveConcurrentCameraSelectors().isEmpty()
-                && !cameraSelectorsToBind.equals(getActiveConcurrentCameraSelectors())) {
+        if (concurrentCameraConfig.getSingleCameraConfigs().size() < 2) {
+            throw new IllegalArgumentException("Concurrent camera needs two camera configs");
+        }
+
+        if (concurrentCameraConfig.getSingleCameraConfigs().size() > 2) {
+            throw new IllegalArgumentException("Concurrent camera is only supporting two  "
+                    + "cameras at maximum.");
+        }
+
+        List<CameraInfo> cameraInfosToBind = new ArrayList<>();
+        List<CameraInfo> availableCameraInfos = getAvailableCameraInfos();
+        CameraInfo firstCameraInfo = getCameraInfoFromCameraSelector(
+                concurrentCameraConfig.getSingleCameraConfigs().get(0).getCameraSelector(),
+                availableCameraInfos);
+        CameraInfo secondCameraInfo = getCameraInfoFromCameraSelector(
+                concurrentCameraConfig.getSingleCameraConfigs().get(1).getCameraSelector(),
+                availableCameraInfos);
+        if (firstCameraInfo == null || secondCameraInfo == null) {
+            throw new IllegalArgumentException("Invalid camera selectors in camera configs");
+        }
+        cameraInfosToBind.add(firstCameraInfo);
+        cameraInfosToBind.add(secondCameraInfo);
+        if (!getActiveConcurrentCameraInfos().isEmpty()
+                && !cameraInfosToBind.equals(getActiveConcurrentCameraInfos())) {
             throw new UnsupportedOperationException("Cameras are already running, call "
                     + "unbindAll() before binding more cameras");
         }
@@ -468,7 +486,7 @@
                     config.getUseCaseGroup().getUseCases().toArray(new UseCase[0]));
             cameras.add(camera);
         }
-        setActiveConcurrentCameraSelectors(cameraSelectorsToBind);
+        setActiveConcurrentCameraInfos(cameraInfosToBind);
         return new ConcurrentCamera.Builder()
                 .setCameras(cameras)
                 .builder();
@@ -753,12 +771,10 @@
         for (final List<CameraSelector> cameraSelectors : concurrentCameraSelectorLists) {
             List<CameraInfo> cameraInfos = new ArrayList<>();
             for (CameraSelector cameraSelector : cameraSelectors) {
-                for (CameraInfo cameraInfo : availableCameraInfos) {
-                    if (cameraSelector.getLensFacing()
-                            == cameraInfo.getLensFacing()) {
-                        cameraInfos.add(cameraInfo);
-                        break;
-                    }
+                CameraInfo cameraInfo = getCameraInfoFromCameraSelector(cameraSelector,
+                        availableCameraInfos);
+                if (cameraInfo != null) {
+                    cameraInfos.add(cameraInfo);
                 }
             }
             availableConcurrentCameraInfos.add(cameraInfos);
@@ -794,20 +810,28 @@
     }
 
     @NonNull
-    private List<CameraSelector> getActiveConcurrentCameraSelectors() {
+    private List<CameraInfo> getActiveConcurrentCameraInfos() {
         if (mCameraX == null) {
             return new ArrayList<>();
         }
         return mCameraX.getCameraFactory().getCameraCoordinator()
-                .getActiveConcurrentCameraSelectors();
+                .getActiveConcurrentCameraInfos();
     }
 
-    private void setActiveConcurrentCameraSelectors(@NonNull List<CameraSelector> cameraSelectors) {
+    private void setActiveConcurrentCameraInfos(@NonNull List<CameraInfo> cameraInfos) {
         if (mCameraX == null) {
             return;
         }
         mCameraX.getCameraFactory().getCameraCoordinator()
-                .setActiveConcurrentCameraSelectors(cameraSelectors);
+                .setActiveConcurrentCameraInfos(cameraInfos);
+    }
+
+    @Nullable
+    private CameraInfo getCameraInfoFromCameraSelector(
+            @NonNull CameraSelector cameraSelector,
+            @NonNull List<CameraInfo> availableCameraInfos) {
+        List<CameraInfo> cameraInfos = cameraSelector.filter(availableCameraInfos);
+        return cameraInfos.isEmpty() ? null : cameraInfos.get(0);
     }
 
     private ProcessCameraProvider() {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraCoordinator.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraCoordinator.java
index 4f642bc..3281ec1 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraCoordinator.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraCoordinator.java
@@ -20,6 +20,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.camera.core.CameraInfo;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.concurrent.CameraCoordinator;
 
@@ -40,7 +41,7 @@
     @NonNull private Map<String, String> mConcurrentCameraIdMap;
     @NonNull private List<List<String>> mConcurrentCameraIds;
     @NonNull private List<List<CameraSelector>> mConcurrentCameraSelectors;
-    @NonNull private List<CameraSelector> mActiveConcurrentCameraSelectors;
+    @NonNull private List<CameraInfo> mActiveConcurrentCameraInfos;
     @NonNull private final List<ConcurrentCameraModeListener> mConcurrentCameraModeListeners;
 
     @CameraOperatingMode private int mCameraOperatingMode;
@@ -49,7 +50,7 @@
         mConcurrentCameraIdMap = new HashMap<>();
         mConcurrentCameraIds = new ArrayList<>();
         mConcurrentCameraSelectors = new ArrayList<>();
-        mActiveConcurrentCameraSelectors = new ArrayList<>();
+        mActiveConcurrentCameraInfos = new ArrayList<>();
         mConcurrentCameraModeListeners = new ArrayList<>();
     }
 
@@ -76,15 +77,15 @@
         return mConcurrentCameraSelectors;
     }
 
-    @Override
-    public void setActiveConcurrentCameraSelectors(@NonNull List<CameraSelector> cameraSelectors) {
-        mActiveConcurrentCameraSelectors = cameraSelectors;
-    }
-
     @NonNull
     @Override
-    public List<CameraSelector> getActiveConcurrentCameraSelectors() {
-        return mActiveConcurrentCameraSelectors;
+    public List<CameraInfo> getActiveConcurrentCameraInfos() {
+        return mActiveConcurrentCameraInfos;
+    }
+
+    @Override
+    public void setActiveConcurrentCameraInfos(@NonNull List<CameraInfo> cameraInfos) {
+        mActiveConcurrentCameraInfos = cameraInfos;
     }
 
     @Nullable
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSupportedOutputSizesSorter.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSupportedOutputSizesSorter.java
new file mode 100644
index 0000000..c96182f
--- /dev/null
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSupportedOutputSizesSorter.java
@@ -0,0 +1,57 @@
+/*
+ * 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.camera.testing.fakes;
+
+import static java.util.Objects.requireNonNull;
+
+import android.os.Build;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.UseCaseConfig;
+import androidx.camera.core.internal.SupportedOutputSizesSorter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A fake implementation of {@link SupportedOutputSizesSorter} for testing.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+public class FakeSupportedOutputSizesSorter extends SupportedOutputSizesSorter {
+
+    @NonNull
+    Map<UseCaseConfig<?>, List<Size>> mSupportedOutputSizes;
+
+    /**
+     * Creates a new instance of {@link FakeSupportedOutputSizesSorter}.
+     *
+     * @param supportedOutputSizes the supported output sizes for each use case config.
+     */
+    public FakeSupportedOutputSizesSorter(
+            @NonNull Map<UseCaseConfig<?>, List<Size>> supportedOutputSizes) {
+        super(new FakeCameraInfoInternal());
+        mSupportedOutputSizes = supportedOutputSizes;
+    }
+
+    @Override
+    @NonNull
+    public List<Size> getSortedSupportedOutputSizes(@NonNull UseCaseConfig<?> useCaseConfig) {
+        return requireNonNull(mSupportedOutputSizes.get(useCaseConfig));
+    }
+}
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 3963e6a..7dc5a90 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
@@ -159,7 +159,8 @@
     private static final String SURFACE_UPDATE_KEY =
             "androidx.camera.video.VideoCapture.streamUpdate";
     private static final Defaults DEFAULT_CONFIG = new Defaults();
-    private static final boolean ENABLE_SURFACE_PROCESSING_BY_QUIRK;
+    @VisibleForTesting
+    static boolean sEnableSurfaceProcessingByQuirk;
     private static final boolean USE_TEMPLATE_PREVIEW_BY_QUIRK;
 
     static {
@@ -175,7 +176,7 @@
                 DeviceQuirks.get(ExtraSupportedResolutionQuirk.class) != null;
         USE_TEMPLATE_PREVIEW_BY_QUIRK =
                 hasPreviewStretchQuirk || hasPreviewDelayQuirk || hasImageCaptureFailedQuirk;
-        ENABLE_SURFACE_PROCESSING_BY_QUIRK =
+        sEnableSurfaceProcessingByQuirk =
                 hasPreviewDelayQuirk || hasImageCaptureFailedQuirk
                         || hasVideoQualityQuirkAndWorkaroundBySurfaceProcessing
                         || hasExtraSupportedResolutionQuirk;
@@ -383,7 +384,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @SuppressWarnings("unchecked")
     @RestrictTo(Scope.LIBRARY_GROUP)
@@ -409,7 +409,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @Override
     @RestrictTo(Scope.LIBRARY_GROUP)
@@ -420,7 +419,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
@@ -447,7 +445,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @Override
@@ -468,7 +465,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
@@ -483,7 +479,6 @@
 
     /**
      * {@inheritDoc}
-     *
      */
     @NonNull
     @RestrictTo(Scope.LIBRARY_GROUP)
@@ -563,8 +558,7 @@
         VideoEncoderInfo videoEncoderInfo = getVideoEncoderInfo(config.getVideoEncoderInfoFinder(),
                 videoCapabilities, mediaSpec, resolution, targetFpsRange);
         mCropRect = calculateCropRect(resolution, videoEncoderInfo);
-        boolean shouldMirror = camera.getHasTransform() && isMirroringRequired(camera);
-        mNode = createNodeIfNeeded(isCropNeeded(mCropRect, resolution), shouldMirror);
+        mNode = createNodeIfNeeded(camera, mCropRect, resolution);
         // Choose Timebase based on the whether the buffer is copied.
         Timebase timebase;
         if (mNode != null || !camera.getHasTransform()) {
@@ -588,7 +582,7 @@
                     camera.getHasTransform(),
                     mCropRect,
                     getRelativeRotation(camera, isMirroringRequired(camera)),
-                    shouldMirror);
+                    shouldMirror(camera));
             cameraEdge.addOnInvalidatedListener(onSurfaceInvalidated);
             mCameraEdge = cameraEdge;
             SurfaceProcessorNode.OutConfig outConfig =
@@ -700,7 +694,6 @@
      *
      * <p>These values may be overridden by the implementation. They only provide a minimum set of
      * defaults that are implementation independent.
-     *
      */
     @RestrictTo(Scope.LIBRARY_GROUP)
     public static final class Defaults implements ConfigProvider<VideoCaptureConfig<?>> {
@@ -819,9 +812,13 @@
     }
 
     @Nullable
-    private SurfaceProcessorNode createNodeIfNeeded(boolean isCropNeeded, boolean mirroring) {
-        if (getEffect() != null || ENABLE_SURFACE_PROCESSING_BY_QUIRK || isCropNeeded
-                || mirroring) {
+    private SurfaceProcessorNode createNodeIfNeeded(@NonNull CameraInternal camera,
+            @NonNull Rect cropRect,
+            @NonNull Size resolution) {
+        if (getEffect() != null
+                || shouldEnableSurfaceProcessingByQuirk(camera)
+                || shouldCrop(cropRect, resolution)
+                || shouldMirror(camera)) {
             Logger.d(TAG, "Surface processing is enabled.");
             return new SurfaceProcessorNode(requireNonNull(getCamera()),
                     getEffect() != null ? getEffect().createSurfaceProcessorInternal() :
@@ -957,11 +954,23 @@
         }
     }
 
-    private static boolean isCropNeeded(@NonNull Rect cropRect, @NonNull Size resolution) {
+    private boolean shouldMirror(@NonNull CameraInternal camera) {
+        // Stream is always mirrored during buffer copy. If there has been a buffer copy, it
+        // means the input stream is already mirrored. Otherwise, mirror it as needed.
+        return camera.getHasTransform() && isMirroringRequired(camera);
+    }
+
+    private static boolean shouldCrop(@NonNull Rect cropRect, @NonNull Size resolution) {
         return resolution.getWidth() != cropRect.width()
                 || resolution.getHeight() != cropRect.height();
     }
 
+    private static boolean shouldEnableSurfaceProcessingByQuirk(@NonNull CameraInternal camera) {
+        // If there has been a buffer copy, it means the surface processing is already enabled on
+        // input stream. Otherwise, enable it as needed.
+        return camera.getHasTransform() && sEnableSurfaceProcessingByQuirk;
+    }
+
     private static int alignDown(int length, int alignment,
             @NonNull Range<Integer> supportedLength) {
         return align(true, length, alignment, supportedLength);
@@ -1300,7 +1309,6 @@
 
         /**
          * {@inheritDoc}
-         *
          */
         @RestrictTo(Scope.LIBRARY_GROUP)
         @Override
@@ -1311,7 +1319,6 @@
 
         /**
          * {@inheritDoc}
-         *
          */
         @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
@@ -1383,7 +1390,6 @@
          * setTargetAspectRatio is not supported on VideoCapture
          *
          * <p>To set aspect ratio, see {@link Recorder.Builder#setAspectRatio(int)}.
-         *
          */
         @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
@@ -1450,7 +1456,6 @@
          * setTargetResolution is not supported on VideoCapture
          *
          * <p>To set resolution, see {@link Recorder.Builder#setQualitySelector(QualitySelector)}.
-         *
          */
         @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
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 39694a7..c03128a 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
@@ -753,6 +753,42 @@
     }
 
     @Test
+    fun hasSurfaceProcessingQuirk_nodeIsNeeded() {
+        // Arrange.
+        VideoCapture.sEnableSurfaceProcessingByQuirk = true
+        setupCamera()
+        createCameraUseCaseAdapter()
+
+        // Act.
+        val videoCapture = createVideoCapture()
+        addAndAttachUseCases(videoCapture)
+
+        // Assert.
+        assertThat(videoCapture.node).isNotNull()
+
+        // Clean-up.
+        VideoCapture.sEnableSurfaceProcessingByQuirk = false
+    }
+
+    @Test
+    fun hasSurfaceProcessingQuirkButNoCameraTransform_nodeIsNotNeeded() {
+        // Arrange.
+        VideoCapture.sEnableSurfaceProcessingByQuirk = true
+        setupCamera(hasTransform = false)
+        createCameraUseCaseAdapter()
+
+        // Act.
+        val videoCapture = createVideoCapture()
+        addAndAttachUseCases(videoCapture)
+
+        // Assert.
+        assertThat(videoCapture.node).isNull()
+
+        // Clean-up.
+        VideoCapture.sEnableSurfaceProcessingByQuirk = false
+    }
+
+    @Test
     fun defaultMirrorModeIsOff() {
         val videoCapture = createVideoCapture()
         assertThat(videoCapture.mirrorMode).isEqualTo(MIRROR_MODE_OFF)
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/internal/audio/AudioSourceTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/internal/audio/AudioSourceTest.kt
index 72e1075..7f59988 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/internal/audio/AudioSourceTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/internal/audio/AudioSourceTest.kt
@@ -33,6 +33,7 @@
 import java.util.concurrent.Executor
 import java.util.concurrent.TimeUnit.NANOSECONDS
 import org.junit.After
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
@@ -198,6 +199,7 @@
         audioStream.verifyStopCall(CallTimes(1), COMMON_TIMEOUT_MS)
     }
 
+    @Ignore // b/273534749
     @Test
     fun canReceiveSilence() {
         // Arrange.
diff --git a/camera/camera-viewfinder/build.gradle b/camera/camera-viewfinder/build.gradle
index ea7bfde..39c752c 100644
--- a/camera/camera-viewfinder/build.gradle
+++ b/camera/camera-viewfinder/build.gradle
@@ -27,12 +27,14 @@
     api("androidx.annotation:annotation:1.2.0")
     implementation("androidx.annotation:annotation-experimental:1.1.0-rc01")
     implementation(libs.guavaListenableFuture)
-    implementation("androidx.core:core:1.3.2")
-    implementation("androidx.concurrent:concurrent-futures:1.0.0")
-    implementation(project(":concurrent:concurrent-futures-ktx"))
+    implementation("androidx.core:core:1.7.0")
+    implementation("androidx.concurrent:concurrent-futures:1.1.0")
+    implementation("androidx.concurrent:concurrent-futures-ktx:1.2.0-alpha01")
     implementation(libs.autoValueAnnotations)
     implementation("androidx.appcompat:appcompat:1.1.0")
     implementation("androidx.test.espresso:espresso-idling-resource:3.1.0")
+    implementation(libs.kotlinCoroutinesCore)
+    implementation(libs.kotlinCoroutinesAndroid)
 
     // Added for annotation-experimental
     compileOnly(libs.kotlinStdlib)
diff --git a/car/app/app-automotive/api/public_plus_experimental_current.txt b/car/app/app-automotive/api/public_plus_experimental_current.txt
index f0fc8af..71b454a 100644
--- a/car/app/app-automotive/api/public_plus_experimental_current.txt
+++ b/car/app/app-automotive/api/public_plus_experimental_current.txt
@@ -12,6 +12,10 @@
     ctor public CarAppActivity();
   }
 
+  @androidx.car.app.annotations.ExperimentalCarApi public final class LauncherActivity extends androidx.fragment.app.FragmentActivity implements androidx.lifecycle.LifecycleOwner {
+    ctor public LauncherActivity();
+  }
+
 }
 
 package androidx.car.app.activity.renderer.surface {
diff --git a/car/app/app-automotive/src/main/java/androidx/car/app/activity/LauncherActivity.java b/car/app/app-automotive/src/main/java/androidx/car/app/activity/LauncherActivity.java
new file mode 100644
index 0000000..942b59f
--- /dev/null
+++ b/car/app/app-automotive/src/main/java/androidx/car/app/activity/LauncherActivity.java
@@ -0,0 +1,99 @@
+/*
+ * 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.car.app.activity;
+
+import android.annotation.SuppressLint;
+import android.car.Car;
+import android.car.drivingstate.CarUxRestrictionsManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.car.app.annotations.ExperimentalCarApi;
+import androidx.fragment.app.FragmentActivity;
+
+/**
+ * <p> This class handles providing the right launcher activity when running native
+ * applications and Car App Library applications.
+ *
+ * If distraction optimized is mandated {@link CarAppActivity} will be launched.
+ * otherwise the activity with action {@link Intent#ACTION_MAIN} and category
+ * {@link Intent#CATEGORY_DEFAULT} will be launched.
+ */
+@SuppressLint({"ForbiddenSuperClass"})
+@ExperimentalCarApi
+public final class LauncherActivity extends FragmentActivity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (isDistractionOptimizedActivityRequired(this)) {
+            startActivity(getCarAppActivityIntent(this));
+        } else {
+            startActivity(getDefaultIntent(this));
+        }
+        finish();
+    }
+
+    @SuppressWarnings("deprecation")
+    @VisibleForTesting
+    static Intent getDefaultIntent(Context context) {
+        Intent intent =
+                new Intent(Intent.ACTION_MAIN).addCategory(
+                        Intent.CATEGORY_DEFAULT);
+        ResolveInfo resolveInfoList = context.getPackageManager().resolveActivity(intent,
+                PackageManager.MATCH_DEFAULT_ONLY);
+
+        if (resolveInfoList == null) {
+            throw new IllegalStateException("Application requires an intent with Action Main and"
+                    + " Category Default");
+        } else {
+            return new Intent().setComponent(new ComponentName(
+                    resolveInfoList.activityInfo.packageName,
+                    resolveInfoList.activityInfo.name));
+
+        }
+    }
+
+    @VisibleForTesting
+    static Intent getCarAppActivityIntent(Context context) {
+        return new Intent(context, CarAppActivity.class);
+    }
+
+    @VisibleForTesting
+    static boolean isDistractionOptimizedActivityRequired(Context context) {
+        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            return false;
+        }
+
+        Car car = Car.createCar(context);
+        boolean isDistractionOptimizedRequired = ((CarUxRestrictionsManager) car.getCarManager(
+                Car.CAR_UX_RESTRICTION_SERVICE))
+                .getCurrentCarUxRestrictions().
+                isRequiresDistractionOptimization();
+        car.disconnect();
+        car = null;
+        return isDistractionOptimizedRequired;
+    }
+
+}
diff --git a/car/app/app-automotive/src/test/java/androidx/car/app/activity/LauncherActivityTest.java b/car/app/app-automotive/src/test/java/androidx/car/app/activity/LauncherActivityTest.java
new file mode 100644
index 0000000..3a48634
--- /dev/null
+++ b/car/app/app-automotive/src/test/java/androidx/car/app/activity/LauncherActivityTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.car.app.activity;
+
+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.robolectric.Shadows.shadowOf;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.internal.DoNotInstrument;
+import org.robolectric.shadows.ShadowPackageManager;
+
+/** Tests for {@link LauncherActivity}. */
+@RunWith(RobolectricTestRunner.class)
+@DoNotInstrument
+public class LauncherActivityTest {
+    private final ComponentName defaultComponentName = new ComponentName(getApplicationContext(),
+            getClass().getName());
+    private final ComponentName launcherComponent = new ComponentName(getApplicationContext(),
+            "androidx.car.app.activity.LauncherActivity");
+    private final ComponentName carAppActivityComponentName = new ComponentName(
+            getApplicationContext(), "androidx.car.app.activity.CarAppActivity");
+
+    private ShadowPackageManager mShadowPackageManager;
+
+    @Before
+    public void setup() {
+        PackageManager packageManager = getApplicationContext().getPackageManager();
+        mShadowPackageManager = shadowOf(packageManager);
+
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
+        intentFilter.addCategory(Intent.CATEGORY_LAUNCHER);
+
+        mShadowPackageManager.addActivityIfNotPresent(launcherComponent);
+        mShadowPackageManager.addIntentFilterForActivity(launcherComponent,
+                intentFilter);
+    }
+
+    @Test
+    public void getCarAppActivityIntent_returnsCarAppActivityIntent() {
+        assertThat(
+                LauncherActivity.getCarAppActivityIntent(
+                        getApplicationContext()).getComponent()).isEqualTo(
+                carAppActivityComponentName);
+    }
+
+    @Test
+    public void getDefaultIntent_throwsIllegalStateException() {
+        assertThrows(IllegalStateException.class,
+                () -> LauncherActivity.getDefaultIntent(
+                        getApplicationContext()));
+    }
+
+    @Test
+    public void getDefaultIntent_returnsDefaultComponentName() {
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
+        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
+
+        mShadowPackageManager.addActivityIfNotPresent(defaultComponentName);
+        mShadowPackageManager.addActivityIfNotPresent(carAppActivityComponentName);
+        mShadowPackageManager.addIntentFilterForActivity(defaultComponentName,
+                intentFilter);
+        Intent defaultIntent = LauncherActivity.getDefaultIntent(
+                getApplicationContext());
+
+        assertThat(defaultIntent.getComponent()).isEqualTo(defaultComponentName);
+    }
+
+    @Test
+    public void isDistractionOptimizedActivityRequired_returnsFalse() {
+        mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
+
+        assertThat(LauncherActivity.isDistractionOptimizedActivityRequired(
+                getApplicationContext())).isFalse();
+    }
+
+}
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/ListTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/ListTemplateDemoScreen.java
index ef9ebce..d198248 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/ListTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/ListTemplateDemoScreen.java
@@ -27,6 +27,7 @@
 import androidx.car.app.model.Template;
 import androidx.car.app.sample.showcase.common.R;
 import androidx.car.app.sample.showcase.common.screens.templatelayouts.listtemplates.ContentProviderIconsDemoScreen;
+import androidx.car.app.sample.showcase.common.screens.templatelayouts.listtemplates.EmptyListDemoScreen;
 import androidx.car.app.sample.showcase.common.screens.templatelayouts.listtemplates.RadioButtonListDemoScreen;
 import androidx.car.app.sample.showcase.common.screens.templatelayouts.listtemplates.SecondaryActionsAndDecorationDemoScreen;
 import androidx.car.app.sample.showcase.common.screens.templatelayouts.listtemplates.SectionedItemListDemoScreen;
@@ -64,6 +65,16 @@
         listBuilder.addItem(buildRowForTemplate(
                 new SectionedItemListDemoScreen(getCarContext()),
                 R.string.sectioned_item_list_demo_title));
+
+        // ========================================================================
+        // WARNING: 6 demos have been added above, which is the max list size for some users/devs.
+        // Demos added below may be truncated from the list in certain regions.
+        // ========================================================================
+
+        listBuilder.addItem(buildRowForTemplate(
+                new EmptyListDemoScreen(getCarContext()),
+                R.string.empty_list_demo_title));
+
         return new ListTemplate.Builder()
                 .setSingleList(listBuilder.build())
                 .setTitle(getCarContext().getString(R.string.list_template_demo_title))
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/listtemplates/EmptyListDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/listtemplates/EmptyListDemoScreen.java
new file mode 100644
index 0000000..865dd17
--- /dev/null
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/listtemplates/EmptyListDemoScreen.java
@@ -0,0 +1,49 @@
+/*
+ * 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.car.app.sample.showcase.common.screens.templatelayouts.listtemplates;
+
+import static androidx.car.app.model.Action.BACK;
+
+import androidx.annotation.NonNull;
+import androidx.car.app.CarContext;
+import androidx.car.app.Screen;
+import androidx.car.app.model.ItemList;
+import androidx.car.app.model.ListTemplate;
+import androidx.car.app.model.Template;
+import androidx.car.app.sample.showcase.common.R;
+
+/** A screen demonstrating empty lists */
+public class EmptyListDemoScreen extends Screen {
+    public EmptyListDemoScreen(@NonNull CarContext carContext) {
+        super(carContext);
+    }
+
+    @NonNull
+    @Override
+    public Template onGetTemplate() {
+        return new ListTemplate.Builder()
+                .setSingleList(
+                        new ItemList.Builder()
+                                .setNoItemsMessage(
+                                        getCarContext().getString(R.string.empty_list_message)
+                                )
+                                .build()
+                )
+                .setHeaderAction(BACK)
+                .build();
+    }
+}
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-af/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-af/strings.xml
index 89d345f..6f2eb16 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-af/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-af/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lys 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lys 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subteks onder elke lys"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstrasies oor diverse template"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Stal demonstrasies uit"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrasie van templaatuitlegte"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
index 0226e81..c61b6f8 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ዝርዝር 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ዝርዝር 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ከእያንዳንዱ ዝርዝር ስር የግርጌ ጽሑፍ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"የተለያዩ ቅንብር ደንቦች ቅንጭብ ማሳያዎች"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"የመሳያ ቅንጭብ ማሳያ"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"የቅንብር ደንብ አቀማመጥ ቅንጭብ ማሳያዎች"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
index d347a04..5b93dea 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"القائمة 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"القائمة 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"نص فرعي تحت كل قائمة"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"إصدارات تجريبية لنموذج ميزات متنوّعة"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"عرض الإصدارات التجريبية"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"عروض توضيحية لتنسيقات النماذج"</string>
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 6014a5f..0936930 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
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"সূচী ১"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"সূচী ২"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"প্ৰতিখন সূচীৰ অন্তৰ্গত উপপাঠ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"সানমিহলি টেম্পলে’টৰ ডেম’"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ডেম’ দেখুৱাওক"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"টেমপ্লে’ট লে’আউটৰ ডেম’"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-az/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-az/strings.xml
index d02a701..6b6877d 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-az/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-az/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Siyahı 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Siyahı 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Hər siyahı üzrə alt mətn"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Digər Şablon Demoları"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Vitrin Demoları"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Şablon Düzən Demoları"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-b+sr+Latn/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-b+sr+Latn/strings.xml
index 63c19f3..d67bdfd 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-b+sr+Latn/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-b+sr+Latn/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Podtekst ispod svake liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstracije različitih šablona"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstracije prikazivanja"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstracije izgleda šablona"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-be/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-be/strings.xml
index a1cda80..f76b965 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-be/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-be/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Спіс 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Спіс 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Тэкст пад кожным спісам"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Дэманстрацыі розных шаблонаў"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Дэманстрацыі выбранага"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Дэманстрацыі макета шаблона"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-bg/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-bg/strings.xml
index e4844e6..37bb283 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-bg/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-bg/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Списък 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Списък 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Подтекст под всеки списък"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Демонстрации на разни шаблони"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Демонстрации на Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Демонстрации на оформления за шаблон"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-bn/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-bn/strings.xml
index cc25232..840713d 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-bn/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-bn/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"তালিকা ১"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"তালিকা ২"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"প্রতিটি তালিকায় থাকা সাবটেক্সট"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"অন্যান্য টেমপ্লেটের ডেমো"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ডেমো শোকেস করুন"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"টেমপ্লেট লেআউট সংক্রান্ত ডেমো"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-bs/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-bs/strings.xml
index 8f0caf4..403d3ea 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-bs/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-bs/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1. lista"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2. lista"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Podtekst ispod svake liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demo verzije raznih šablona"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demo verzije predstavljanja"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo verzije rasporeda predloška"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
index 0c95fc9..0619b4d 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ca/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Llista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Llista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext a sota de cada llista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demostracions de plantilles diverses"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demostracions de Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demostracions de dissenys de plantilles"</string>
@@ -334,7 +338,7 @@
     <string name="voice_access_demo_title" msgid="3825223890895361496">"Pantalla de demostració de Voice Access"</string>
     <string name="user_interactions_demo_title" msgid="1356952319161314986">"Interaccions dels usuaris"</string>
     <string name="request_permission_menu_demo_title" msgid="4796486779527427017">"Demostracions de sol·licitud de permisos"</string>
-    <string name="application_overflow_title" msgid="396427940886169325">"Validador del menú addicional de l\'aplicació"</string>
+    <string name="application_overflow_title" msgid="396427940886169325">"Validador del menú de desbordament de l\'aplicació"</string>
     <string name="application_overflow_subtitle1" msgid="7429415605726615529">"Prova les següents plantilles mentre canvies"</string>
     <string name="application_overflow_subtitle2" msgid="4385123036846369714">"el vehicle de l\'estat aparcat a mode de conducció"</string>
     <string name="perm_group" msgid="3834918337351876270">"Grup de permisos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-cs/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-cs/strings.xml
index 3c7db09..105a7f3 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-cs/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-cs/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Seznam 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Seznam 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Popis pod každým seznamem"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Ukázky různých šablon"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Ukázky Výběru"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Ukázky šablon rozvržení"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
index 4881ef8..4b085bc 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Tekst under hver liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstrationer af diverse skabeloner"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Vis demonstrationer"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demoer for skabelonlayout"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-de/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-de/strings.xml
index ea7398b..eee9115 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-de/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-de/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext unter jeder Liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demos der verschiedenen Vorlagen"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demos anzeigen"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo der Layoutvorlagen"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-el/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-el/strings.xml
index 6b7cf3d..7b786a4 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-el/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-el/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Λίστα 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Λίστα 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Δευτερεύον κείμενο κάτω από κάθε λίστα"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Διάφορες επιδείξεις προτύπων"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Προβολή επιδείξεων"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Επιδείξεις διάταξης προτύπου"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-en-rAU/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-en-rAU/strings.xml
index 00c576f..79f328f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-en-rAU/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-en-rAU/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"List 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"List 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext under each list"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Misc templates demos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase demos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Template layout demos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-en-rCA/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-en-rCA/strings.xml
index e74be41..c480307 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-en-rCA/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-en-rCA/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"List 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"List 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext under each list"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Misc Templates Demos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase Demos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Template Layout Demos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-en-rGB/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-en-rGB/strings.xml
index 00c576f..79f328f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-en-rGB/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-en-rGB/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"List 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"List 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext under each list"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Misc templates demos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase demos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Template layout demos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-en-rIN/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-en-rIN/strings.xml
index 00c576f..79f328f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-en-rIN/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-en-rIN/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"List 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"List 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext under each list"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Misc templates demos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase demos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Template layout demos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-en-rXC/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-en-rXC/strings.xml
index f2b3cc0..0772998 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-en-rXC/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-en-rXC/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎List 1‎‏‎‎‏‎"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎List 2‎‏‎‎‏‎"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎Subtext under each list‎‏‎‎‏‎"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‎‎Misc Templates Demos‎‏‎‎‏‎"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎Showcase Demos‎‏‎‎‏‎"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎Template Layout Demos‎‏‎‎‏‎"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-es-rUS/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-es-rUS/strings.xml
index d4b16a9..8b1159a 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-es-rUS/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-es-rUS/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtexto debajo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demostraciones de plantillas varias"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demostraciones de Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demostración de plantilla de diseño"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-es/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-es/strings.xml
index 35c6bec..066ffce 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-es/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-es/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtexto debajo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Otras demos de plantillas"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demos de Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demos de diseño de plantillas"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-et/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-et/strings.xml
index 7dcd4ca..97af232 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-et/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-et/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Loend 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Loend 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Iga loendi all olev alltekst"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Mitmesuguste mallide demod"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Esiletõstmise demod"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Malli paigutuse demod"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
index a39db4e..998cf08 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Zerrenda 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Zerrenda 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Zerrenda bakoitzaren beheko azpitestua"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Bestelako txantiloien demo-bertsioak"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Erakutsi demo-bertsioak"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Txantiloi-diseinuen demo-bertsioak"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
index 6b14091..f6d5c3e 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-fa/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"فهرست ۱"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"فهرست ۲"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"نوشتار فرعی زیر هر فهرست"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"الگوهای متفرقه نمونه"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"نمایش نمونه‌ها"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"نسخه‌های نمونه طرح‌بندی الگو"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-fi/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-fi/strings.xml
index 8ad1625..6e946f9 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-fi/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-fi/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Kunkin listan alla oleva alateksti"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Sekalaisten mallien esittelyt"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase-esittelyt"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Malliasettelujen esittelyt"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-fr-rCA/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-fr-rCA/strings.xml
index 76b6626..b66629f 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-fr-rCA/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-fr-rCA/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Sous-titre de chaque liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Démos de divers modèles"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Présenter les démos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Démos de mise en page du modèle"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-fr/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-fr/strings.xml
index 9e261b2..9f4e141 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-fr/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-fr/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Texte sous chaque liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Démos de divers modèles"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Présenter les démos"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Démos de mise en page du modèle"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-gl/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-gl/strings.xml
index 8086d0a..8f37e39 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-gl/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-gl/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Texto secundario debaixo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Outras demostracións de modelos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demostracións de Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demostracións de deseños de modelo"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-gu/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-gu/strings.xml
index f56e44e..5ee9626 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-gu/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-gu/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"સૂચિ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"સૂચિ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"દરેક સૂચિ હેઠળની પેટાટેક્સ્ટ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"વિવિધ નમૂનાઓના ડેમો"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ડેમો બતાવો"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"નમૂનાના લેઆઉટનો ડેમો"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-hi/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-hi/strings.xml
index d98d811..f7f13e7 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-hi/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-hi/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"सूची 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"सूची 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"हर सूची के नीचे सबटेक्स्ट"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"दूसरे टेंप्लेट के डेमो"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"डेमो दिखाएं"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"टेंप्लेट लेआउट के डेमो"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-hr/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-hr/strings.xml
index 56ea02e..8a98ffd 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-hr/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-hr/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Popis 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Popis 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Podtekst ispod svakog popisa"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Pokazne verzije raznih predložaka"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Prikaži pokazne verzije"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Pokazne verzije izgleda predloška"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-hu/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-hu/strings.xml
index 418ef42..3c53ca6 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-hu/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-hu/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1. lista"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2. lista"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Alszöveg az egyes listák alatt"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Egyéb sablonok – demók"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Kirakat – demók"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Sablonelrendezések bemutatói"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-hy/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-hy/strings.xml
index 2d43574..018dc15 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-hy/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-hy/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Ցանկ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Ցանկ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Նկարագրություն՝ յուրաքանչյուր ցանկի տակ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Այլ ձևանմուշների դեմոներ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Ցուցադրել դեմոները"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Ձևանմուշի դասավորության դեմոներ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-in/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-in/strings.xml
index efd56c4..d00daa8 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-in/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-in/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Daftar 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Daftar 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subteks dalam setiap daftar"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demo Template Lain-Lain"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demo Berita Pilihan"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo Tata Letak Template"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-is/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-is/strings.xml
index 06c9d74..4f0fbac 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-is/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-is/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Listi 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Listi 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Texti undir hverjum lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Sýnishorn ýmissa sniðmáta"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Prufuútgáfur Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Sýnishorn sniðmátsuppsetningar"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-it/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-it/strings.xml
index 418a52d..5ed5c82 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-it/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-it/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Elenco 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Elenco 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Sottotesto sotto ogni elenco"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demo modelli vari"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demo Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo Layout modello"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-iw/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-iw/strings.xml
index 7d6bc35..55a7840 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-iw/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-iw/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"רשימה 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"רשימה 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"טקסט משנה מתחת לכל רשימה"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"הדגמות של תבניות שונות"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"הדגמות תצוגה"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"הדגמות של אפשרויות פריסה של תבנית"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ja/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ja/strings.xml
index 1f5aa3c..a13389e 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ja/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ja/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"リスト 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"リスト 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"各リストのサブテキスト"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"その他のテンプレートのデモ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"デモを表示"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"テンプレート レイアウトのデモ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ka/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ka/strings.xml
index 872a4e0..30578fd 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ka/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ka/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"სია 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"სია 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ქვეტექსტი თითოეული სიის ქვეშ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"სხვადასხვა შაბლონური დემოები"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"დემოების ჩვენება"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"შაბლონის განლაგების დემო"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-kk/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-kk/strings.xml
index 317dfc35..952ea70 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-kk/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-kk/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1-тізім"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2-тізім"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Әр тізім астындағы түсініктеме мәтін"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"\"Басқалары\" үлгісінің демо нұсқасы"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Презентацияның демо нұсқасы"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Формат үлгісі (демо нұсқалары)"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-km/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-km/strings.xml
index 5164aa5..01b793d 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-km/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-km/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"បញ្ជីទី 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"បញ្ជីទី 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"អត្ថបទរងនៅក្រោមបញ្ជីនីមួយៗ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"គំរូបង្ហាញនៃ​ទម្រង់គំរូផ្សេងៗ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"គំរូបង្ហាញអំពីការតាំងរំលេច"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"គំរូបង្ហាញនៃប្លង់​ទម្រង់គំរូ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-kn/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-kn/strings.xml
index 153447c..49d7c2a 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-kn/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-kn/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ಪಟ್ಟಿ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ಪಟ್ಟಿ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ಪ್ರತಿ ಪಟ್ಟಿಯ ಅಡಿಯಲ್ಲಿ ಉಪಪಠ್ಯ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"ಇತರ ಟೆಂಪ್ಲೇಟ್‌ಗಳ ಡೆಮೋಗಳು"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase ಡೆಮೋಗಳು"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"ಟೆಂಪ್ಲೇಟ್ ಲೇಔಟ್ ಡೆಮೋಗಳು"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ko/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ko/strings.xml
index dab016f..c937e27 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ko/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ko/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"목록 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"목록 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"각 목록 아래 하위 텍스트"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"기타 템플릿 데모"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"쇼케이스 데모"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"템플릿 레이아웃 데모"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ky/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ky/strings.xml
index 2f22c34..3127575 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ky/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ky/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1-тизме"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2-тизме"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Ар бир тизмеге берилген кошумча текст"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Башка үлгүлөрдүн демолору"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase демолору"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Үлгү калыптарынын демолору"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-lo/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-lo/strings.xml
index 28e6f5e..2c73880 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-lo/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-lo/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ລາຍຊື່ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ລາຍຊື່ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ຂໍ້ຄວາມຍ່ອຍພາຍໃຕ້ແຕ່ລະລາຍຊື່"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"ເດໂມແມ່ແບບອື່ນໆ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ເດໂມ Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"ເດໂມໂຄງຮ່າງແມ່ແບບ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-lt/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-lt/strings.xml
index 8132540..1c08a5a 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-lt/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-lt/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1 sąrašas"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2 sąrašas"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Kiekvieno sąrašo paantraštė"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Įvairių šablonų demonstracinės versijos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Rodyti demonstracines versijas"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Šablonų išdėstymo demonstracinės versijos"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-lv/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-lv/strings.xml
index e7f6ba0..053d008 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-lv/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-lv/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1. saraksts"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2. saraksts"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Katra saraksta apakšteksts"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Dažādu veidņu demonstrācijas"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase demonstrācijas"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Veidņu izkārtojumu demonstrācijas"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-mk/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-mk/strings.xml
index 44e1a78..0a67f19 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-mk/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-mk/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Список 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Список 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Поттекст под секој список"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Разни демоа за шаблони"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Демоа за прикажување"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Демоа за распоред на шаблони"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ml/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ml/strings.xml
index 88e1f7e..268707c 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ml/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ml/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ലിസ്റ്റ് 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ലിസ്റ്റ് 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ഓരോ ലിസ്‌റ്റിന് കീഴിലും സബ്‌ടെക്‌സ്‌റ്റ്"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"പലവക ടെംപ്ലേറ്റ് ഡെമോകൾ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ഡെമോകൾ ഷോക്കേസ് ചെയ്യുക"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"ടെംപ്ലേറ്റ് ലേഔട്ട് ഡെമോകൾ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-mn/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-mn/strings.xml
index f2dc5c0..d76cf14 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-mn/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-mn/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1-р жагсаалт"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2-р жагсаалт"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Жагсаалт тус бүрийн доорх дэд текст"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Холимог загварын демо"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase-н демо"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Загварын бүдүүвч бүхий демо"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-mr/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-mr/strings.xml
index d5010fe..64a0af7 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-mr/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-mr/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"पहिली सूची"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"दुसरी सूची"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"प्रत्येक सूचीच्या खाली सबटेक्स्ट"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"इतर टेंप्लेटचे डेमो"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"डेमो दाखवा"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"टेंप्लेट लेआउट डेमो"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ms/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ms/strings.xml
index 6470ccc..e9d1ff4 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ms/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ms/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Senarai 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Senarai 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subteks dalam setiap senarai"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Pelbagai Demo Templat"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demo Wadah"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo Reka Letak Templat"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-my/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-my/strings.xml
index 1fe586c..ba145b8 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-my/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-my/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"စာရင်း ၁"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"စာရင်း ၂"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"စာရင်းတစ်ခုစီ၏အောက်ရှိ ရှင်းလင်းချက်"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"အထွေထွေ ပုံစံသရုပ်ပြချက်များ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase သရုပ်ပြချက်များ"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"နမူနာပုံစံ သရုပ်ပြချက်များ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-nb/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-nb/strings.xml
index e153193..34038c4 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-nb/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-nb/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Undertekst under hver liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demoer av diverse maler"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demoer i fokus"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demoer av mallayout"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ne/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ne/strings.xml
index 1b4389e..4ed9249 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ne/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ne/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"सूची १"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"सूची २"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"प्रत्येक सूचीको मुनि रहेको सबटेक्स्ट"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"टेम्प्लेटका विविध डेमोहरू"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"सोकेसहरूको डेमो"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"टेम्प्लेट लेआउटका डेमोहरू"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-nl/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-nl/strings.xml
index 72e7ec8..addb6a7 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-nl/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-nl/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lijst 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lijst 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtekst onder elke lijst"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Diverse templatedemo\'s"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demo\'s laten zien"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo\'s voor opmaaktemplate"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-or/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-or/strings.xml
index e9f4767..24f2749 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-or/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-or/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ତାଲିକା 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ତାଲିକା 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ପ୍ରତ୍ୟେକ ତାଲିକା ତଳେ ସବଟେକ୍ସଟ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"ବିବିଧ ଟେମ୍ପଲେଟର ଡେମୋ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Showcase ଡେମୋ"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"ଟେମ୍ପଲେଟ ଲେଆଉଟର ଡେମୋଗୁଡ଼ିକ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-pa/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-pa/strings.xml
index 66be396..3813de1 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-pa/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-pa/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ਸੂਚੀ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ਸੂਚੀ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ਹਰੇਕ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਸਬਟੈਕਸਟ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"ਫੁਟਕਲ ਟੈਮਪਲੇਟਾਂ ਦੇ ਡੈਮੋ"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ਸ਼ੋਅਕੇਸ ਦੇ ਡੈਮੋ"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"ਟੈਮਪਲੇਟ ਖਾਕੇ ਦੇ ਡੈਮੋ"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-pl/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-pl/strings.xml
index c737a55..4fd9cb2 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-pl/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-pl/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Tekst pod każdą listą"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Wersje demonstracyjne różnych szablonów"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Wersje demonstracyjne do prezentacji"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Wersje demonstracyjne szablonów układu"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-pt-rBR/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-pt-rBR/strings.xml
index cf867f8..216e4ae 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-pt-rBR/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-pt-rBR/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtexto abaixo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstração de modelos diversos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstrações em destaque"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrações de modelos de layout"</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 b79330d..b893094 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
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtexto abaixo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstrações de modelos diversos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstrações de destaque"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrações do esquema do modelo"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-pt/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-pt/strings.xml
index cf867f8..216e4ae 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-pt/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-pt/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtexto abaixo de cada lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstração de modelos diversos"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstrações em destaque"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrações de modelos de layout"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ro/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ro/strings.xml
index 4fe39dc..9771d11a6 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ro/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ro/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtextul de sub fiecare listă"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstrații diverse cu șabloane"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstrații pentru Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrații cu aspecte de șablon"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ru/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ru/strings.xml
index e1791af..baa9fec 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ru/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ru/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Список 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Список 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Описание под каждым списком"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Демонстрации прочих шаблонов"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Демонстрации Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Макет шаблона (режим демонстрации)"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-si/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-si/strings.xml
index e2af18a..d94570c 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-si/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-si/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"ලැයිස්තුව 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"ලැයිස්තුව 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"එක් එක් ලැයිස්තුව යටතේ උප පෙළ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"විවිධ අච්චු ආදර්ශන"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ප්‍රකාශක තේරූ ආදර්ශන"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"අච්චු පිරිසැලසුම් ආදර්ශන"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sk/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sk/strings.xml
index 14f88e9..1b0fa4a 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sk/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sk/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"1. zoznam"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"2. zoznam"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Podtext pod každým zoznamom"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Rôzne šablóny – demá"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Výber – demá"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demo rozložení šablóny"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sl/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sl/strings.xml
index aefe212..0c3f219 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sl/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sl/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Seznam 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Seznam 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Podbesedilo pod posameznim seznamom"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Predstavitvene različice različnih predlog"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Predstavitvene različice izpostavljenih stvari"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Predstavitvene različice postavitev predlog"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sq/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sq/strings.xml
index 301e3ec..baeea6b 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sq/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sq/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Nënteksti poshtë çdo liste"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demonstrime shabllonesh të ndryshme"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Demonstrime të prezantimit"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demonstrimet e strukturës së shabllonit"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sr/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sr/strings.xml
index 4c63418..0404678 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sr/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sr/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Листа 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Листа 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Подтекст испод сваке листе"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Демонстрације различитих шаблона"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Демонстрације приказивања"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Демонстрације изгледа шаблона"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sv/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sv/strings.xml
index 0ffb8d6..1149f31 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sv/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sv/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Lista 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Lista 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Undertext under varje lista"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Demor för övriga mallar"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Visa demor"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Demor för mallayouter"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-sw/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-sw/strings.xml
index 2fb1bb3..50db23a 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-sw/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-sw/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Orodha ya 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Orodha ya 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Dokezo chini ya kila orodha"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Maonyesho ya Violezo Anuwai"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Maonyesho ya Kuangazia"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Maonyesho ya Kiolezo cha Muundo"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ta/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ta/strings.xml
index cf9a242..b7f5d81 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ta/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ta/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"பட்டியல் 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"பட்டியல் 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ஒவ்வொரு பட்டியலுக்கும் கீழுள்ள சுருக்க விவரம்"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"மற்ற டெம்ப்ளேட்டுகளின் டெமோக்கள்"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ஷோகேஸின் டெமோக்கள்"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"டெம்ப்ளேட் தளவமைப்பின் டெமோக்கள்"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-te/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-te/strings.xml
index 48c2552..a9a98cd3 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-te/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-te/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"లిస్ట్ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"లిస్ట్ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ప్రతి లిస్ట్ కింద సబ్‌టెక్స్ట్"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"ఇతర టెంప్లేట్‌ల డెమోలు"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"డెమోలను ప్రదర్శించండి"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"టెంప్లేట్ లేఅవుట్ డెమోలు"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-th/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-th/strings.xml
index b2d06cb..1ae2b69 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-th/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-th/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"รายการที่ 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"รายการที่ 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ข้อความย่อยข้างใต้แต่ละรายการ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"การสาธิตเทมเพลตเบ็ดเตล็ด"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"การสาธิต Showcase"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"การสาธิตเลย์เอาต์เทมเพลต"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-tl/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-tl/strings.xml
index d7db66f..92db494 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-tl/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-tl/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Listahan 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Listahan 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Subtext sa ilalim ng bawat listahan"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Iba Pang Demo ng Mga Template"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Itampok ang Mga Demo"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Mga Demo ng Layout ng Template"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-tr/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-tr/strings.xml
index 4c965fb..13ee781 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-tr/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-tr/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Liste 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Liste 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Her listenin altında alt metin"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Çeşitli Şablon Demoları"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Öne Çıkan Demoları"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Şablon Düzeni Demoları"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-uk/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-uk/strings.xml
index 3e7b486..8343201 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-uk/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-uk/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Список 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Список 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Додатковий текст під кожним списком"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Демонстрації інших шаблонів"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Увімкнути демонстрації"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Демонстрації макетів шаблонів"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ur/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ur/strings.xml
index 438c100..604daef 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ur/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ur/strings.xml
@@ -331,6 +331,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"فہرست 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"فہرست 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"ہر فہرست کے نیچے ذیلی ٹیکسٹ"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"متفرق تمثیلات کے ڈیموز"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"ڈیموز دکھائیں"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"تمثیل کے لے آؤٹ کے ڈیموز"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-uz/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-uz/strings.xml
index 491d966..bfbeafb 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-uz/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-uz/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Roʻyxat 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Roʻyxat 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Har bir roʻyxat ostida quyi matn"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Aralash andozalar demolari"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Namoyish demolari"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Andoza dizayni demolari"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-vi/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-vi/strings.xml
index e386507..05e2525 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-vi/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-vi/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Danh sách 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Danh sách 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Nội dung phụ dưới mỗi danh sách"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Bản demo biểu mẫu Misc"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Bản demo nổi bật"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Bản minh hoạ bố cục mẫu"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-zh-rCN/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-zh-rCN/strings.xml
index a5ecad9..fa21cfb 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-zh-rCN/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-zh-rCN/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"列表 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"列表 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"每个列表下的辅助文本"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"其他模板演示"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"展示演示"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"模板布局演示"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
index 0a10a88..3a4feb8 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-zh-rHK/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"清單 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"清單 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"每個清單的說明文字"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"其他範本示範"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"展示示範"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"「範本版面配置」示範"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-zh-rTW/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-zh-rTW/strings.xml
index a91421b..8b0d2ef 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-zh-rTW/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-zh-rTW/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"清單 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"清單 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"每個清單底下的子文字"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"其他範本示範"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"「展示」示範"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"「範本版面配置」示範"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-zu/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-zu/strings.xml
index b0147da..d2523a1 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-zu/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-zu/strings.xml
@@ -327,6 +327,10 @@
     <string name="sectioned_item_list_one_title" msgid="6594204350307263338">"Uhlu 1"</string>
     <string name="sectioned_item_list_two_title" msgid="4941545381743022833">"Uhlu 2"</string>
     <string name="sectioned_item_list_subtext" msgid="2963927693547537519">"Umbhalo ongaphansi kohlu ngalunye"</string>
+    <!-- no translation found for empty_list_demo_title (5989013634820902455) -->
+    <skip />
+    <!-- no translation found for empty_list_message (5331395517560728138) -->
+    <skip />
     <string name="misc_templates_demos_title" msgid="6077169010255928114">"Amademo Ezifanekiso Ezixubile"</string>
     <string name="showcase_demos_title" msgid="1542092687878113304">"Bonisa Amademo"</string>
     <string name="template_layouts_demo_title" msgid="788249269446087847">"Ama-demo Esakhiwo Sesifanekiso"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
index 64644f3..f9592f7 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
@@ -418,6 +418,10 @@
   <string name="sectioned_item_list_two_title">List 2</string>
   <string name="sectioned_item_list_subtext">Subtext under each list</string>
 
+  <!-- EmptyListDemoScreen -->
+  <string name="empty_list_demo_title">Empty List Demo</string>
+  <string name="empty_list_message">The list is empty</string>
+
   <!-- StartScreen -->
   <string name="misc_templates_demos_title">Misc Templates Demos</string>
   <string name="cal_api_level_prefix" translatable="false">CAL API Level: %d</string>
diff --git a/cardview/OWNERS b/cardview/OWNERS
index bc07458..83166ee 100644
--- a/cardview/OWNERS
+++ b/cardview/OWNERS
@@ -1,2 +1,4 @@
 # Bug component: 461354
-alanv@google.com
\ No newline at end of file
+alanv@google.com
+aelias@google.com
+ryanmentley@google.com
diff --git a/collection/OWNERS b/collection/OWNERS
index 1c323f5..1ffdba3 100644
--- a/collection/OWNERS
+++ b/collection/OWNERS
@@ -2,3 +2,5 @@
 lukhnos@google.com
 dustinlam@google.com
 yboyar@google.com
+aelias@google.com
+ryanmentley@google.com
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
index dd33cd1..3829597 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
@@ -6206,4 +6206,85 @@
             }
         """
     )
+
+    fun testNothingBody() = verifyComposeIrTransform(
+        source = """
+        import androidx.compose.runtime.*
+
+        val test1: @Composable () -> Unit = TODO()
+
+        @Composable
+        fun Test2(): Unit = TODO()
+
+        @Composable
+        fun Test3() {
+            Wrapper {
+                TODO()
+            }
+        }
+        """,
+        extra = """
+        import androidx.compose.runtime.*
+
+        @Composable
+        fun Wrapper(content: @Composable () -> Unit) = content()
+        """,
+        expectedTransformed = """
+        val test1: Function2<Composer, Int, Unit> = TODO()
+        @Composable
+        fun Test2(%composer: Composer?, %changed: Int) {
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(Test2):Test.kt")
+          if (%changed !== 0 || !%composer.skipping) {
+            if (isTraceInProgress()) {
+              traceEventStart(<>, %changed, -1, <>)
+            }
+            TODO()
+            if (isTraceInProgress()) {
+              traceEventEnd()
+            }
+          } else {
+            %composer.skipToGroupEnd()
+          }
+          %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
+            Test2(%composer, updateChangedFlags(%changed or 0b0001))
+          }
+        }
+        @Composable
+        fun Test3(%composer: Composer?, %changed: Int) {
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(Test3)<Wrappe...>:Test.kt")
+          if (%changed !== 0 || !%composer.skipping) {
+            if (isTraceInProgress()) {
+              traceEventStart(<>, %changed, -1, <>)
+            }
+            Wrapper(ComposableSingletons%TestKt.lambda-1, %composer, 0b0110)
+            if (isTraceInProgress()) {
+              traceEventEnd()
+            }
+          } else {
+            %composer.skipToGroupEnd()
+          }
+          %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
+            Test3(%composer, updateChangedFlags(%changed or 0b0001))
+          }
+        }
+        internal object ComposableSingletons%TestKt {
+          val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+            sourceInformation(%composer, "C:Test.kt")
+            if (%changed and 0b1011 !== 0b0010 || !%composer.skipping) {
+              if (isTraceInProgress()) {
+                traceEventStart(<>, %changed, -1, <>)
+              }
+              TODO()
+              if (isTraceInProgress()) {
+                traceEventEnd()
+              }
+            } else {
+              %composer.skipToGroupEnd()
+            }
+          }
+        }
+        """
+    )
 }
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableCheckerTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableCheckerTests.kt
index 1cdc4f6..5dcbf04 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableCheckerTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableCheckerTests.kt
@@ -1298,4 +1298,24 @@
             }
     """
     )
+
+    @Test
+    fun testNothingAsAValidComposableFunctionBody() = check("""
+        import androidx.compose.runtime.*
+
+        val test1: @Composable () -> Unit = TODO()
+
+        @Composable
+        fun Test2(): Unit = TODO()
+
+        @Composable
+        fun Wrapper(content: @Composable () -> Unit) = content()
+
+        @Composable
+        fun Test3() {
+            Wrapper {
+                TODO()
+            }
+        }
+    """)
 }
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableCallChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableCallChecker.kt
index 0b888d9..4b18ff3 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableCallChecker.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableCallChecker.kt
@@ -65,6 +65,7 @@
 import org.jetbrains.kotlin.types.lowerIfFlexible
 import org.jetbrains.kotlin.types.typeUtil.builtIns
 import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
+import org.jetbrains.kotlin.types.typeUtil.isNothing
 import org.jetbrains.kotlin.types.upperIfFlexible
 import org.jetbrains.kotlin.util.OperatorNameConventions
 
@@ -319,6 +320,7 @@
         c: ResolutionContext<*>
     ) {
         val bindingContext = c.trace.bindingContext
+        if (expressionType.isNothing()) return
         val expectedType = c.expectedType
         if (expectedType === TypeUtils.NO_EXPECTED_TYPE) return
         if (expectedType === TypeUtils.UNIT_EXPECTED_TYPE) return
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
index 3c67d9f..49ba87ca 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
@@ -108,6 +108,7 @@
             9500 to "1.4.0-beta01",
             9600 to "1.4.0-beta02",
             9700 to "1.4.0-rc01",
+            9701 to "1.4.0-rc02",
             9701 to "1.5.0-alpha01",
         )
 
@@ -121,7 +122,7 @@
          * The maven version string of this compiler. This string should be updated before/after every
          * release.
          */
-        const val compilerVersion: String = "1.4.3"
+        const val compilerVersion: String = "1.4.4"
         private val minimumRuntimeVersion: String
             get() = runtimeVersionToMavenVersionTable[minimumRuntimeVersionInt] ?: "unknown"
     }
diff --git a/compose/foundation/foundation-newtext/OWNERS b/compose/foundation/foundation-newtext/OWNERS
deleted file mode 100644
index 9b493db..0000000
--- a/compose/foundation/foundation-newtext/OWNERS
+++ /dev/null
@@ -1,13 +0,0 @@
-# Bug component: 856887
-andreykulikov@google.com
-malkov@google.com
-lpf@google.com
-tianliu@google.com
-soboleva@google.com
-ashikov@google.com
-
-# Text
-include /TEXT_OWNERS
-
-# AdapterList
-ryanmentley@google.com
diff --git a/compose/foundation/foundation-newtext/build.gradle b/compose/foundation/foundation-newtext/build.gradle
deleted file mode 100644
index 85d210a..0000000
--- a/compose/foundation/foundation-newtext/build.gradle
+++ /dev/null
@@ -1,152 +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.
- */
-
-
-import androidx.build.AndroidXComposePlugin
-import androidx.build.LibraryType
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-plugins {
-    id("AndroidXPlugin")
-    id("com.android.library")
-    id("AndroidXComposePlugin")
-}
-
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project)
-
-dependencies {
-
-    if(!AndroidXComposePlugin.isMultiplatformEnabled(project)) {
-        /*
-         * When updating dependencies, make sure to make the an an analogous update in the
-         * corresponding block above
-         */
-        api("androidx.annotation:annotation:1.1.0")
-        api("androidx.compose.animation:animation:1.2.1")
-        api("androidx.compose.runtime:runtime:1.3.1")
-        api(project(":compose:ui:ui"))
-
-        implementation(libs.kotlinStdlibCommon)
-        implementation(project(':compose:foundation:foundation'))
-        implementation(project(":compose:foundation:foundation-layout"))
-        implementation(project(":emoji2:emoji2"))
-
-        implementation("androidx.compose.ui:ui-text:1.2.1")
-        implementation("androidx.compose.ui:ui-util:1.2.1")
-
-        lintChecks(project(":compose:foundation:foundation-lint"))
-        lintPublish(project(":compose:foundation:foundation-lint"))
-
-        testImplementation(project(":compose:test-utils"))
-        testImplementation(libs.testRules)
-        testImplementation(libs.testRunner)
-        testImplementation(libs.junit)
-        testImplementation(libs.truth)
-        testImplementation(libs.kotlinTest)
-        testImplementation(libs.mockitoCore4)
-        testImplementation(libs.mockitoKotlin4)
-
-        androidTestImplementation(project(":compose:test-utils"))
-        androidTestImplementation(project(":internal-testutils-fonts"))
-        androidTestImplementation(project(":internal-testutils-runtime"))
-        androidTestImplementation(libs.testRules)
-        androidTestImplementation(libs.testRunner)
-        androidTestImplementation(libs.testMonitor)
-        androidTestImplementation(libs.junit)
-        androidTestImplementation(libs.kotlinTest)
-        androidTestImplementation(libs.truth)
-        androidTestImplementation(libs.dexmakerMockito)
-        androidTestImplementation(libs.mockitoCore)
-        androidTestImplementation(libs.mockitoKotlin)
-    }
-}
-
-if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
-    androidXComposeMultiplatform {
-        android()
-        desktop()
-    }
-
-    kotlin {
-        /*
-         * When updating dependencies, make sure to make the an an analogous update in the
-         * corresponding block above
-         */
-        sourceSets {
-            commonMain.dependencies {
-                implementation(libs.kotlinStdlibCommon)
-                api(project(':compose:animation:animation'))
-                api(project(':compose:runtime:runtime'))
-                api(project(':compose:ui:ui'))
-
-                implementation(project(":compose:ui:ui-text"))
-                implementation(project(":compose:ui:ui-util"))
-
-                implementation(project(':compose:foundation:foundation'))
-                implementation(project(':compose:foundation:foundation-layout'))
-            }
-            androidMain.dependencies {
-                api("androidx.annotation:annotation:1.1.0")
-                implementation(project(":emoji2:emoji2"))
-            }
-
-            desktopMain.dependencies {
-                implementation(libs.kotlinStdlib)
-            }
-
-            androidTest.dependencies {
-                implementation(libs.testRules)
-                implementation(libs.testRunner)
-                implementation(libs.junit)
-                implementation(libs.mockitoCore4)
-                implementation(libs.truth)
-                implementation(libs.kotlinReflect)
-                implementation(libs.mockitoKotlin4)
-            }
-
-            commonTest.dependencies {
-                implementation(libs.kotlinTest)
-                implementation(libs.kotlinCoroutinesTest)
-            }
-
-            androidAndroidTest.dependencies {
-                implementation(project(":compose:test-utils"))
-                implementation(project(":internal-testutils-fonts"))
-                implementation(project(":internal-testutils-runtime"))
-
-                implementation(libs.testRules)
-                implementation(libs.testRunner)
-                implementation(libs.testMonitor)
-                implementation(libs.junit)
-                implementation(libs.truth)
-                implementation(libs.dexmakerMockito)
-                implementation(libs.mockitoCore)
-                implementation(libs.mockitoKotlin)
-            }
-        }
-    }
-}
-
-android {
-    namespace "androidx.compose.foundation.newtext"
-}
-
-androidx {
-    name = "Compose Foundation NewText"
-    type = LibraryType.UNSET /* This module will never be published */
-    inceptionYear = "2022"
-    description = "Working module for developing Text modifier"
-}
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/CoreTextInlineContentTest.kt b/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/CoreTextInlineContentTest.kt
deleted file mode 100644
index 9adc7cd..0000000
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/CoreTextInlineContentTest.kt
+++ /dev/null
@@ -1,240 +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.newtext.text
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.text.InlineTextContent
-import androidx.compose.foundation.text.appendInlineContent
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.LocalDensity
-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.text.ExperimentalTextApi
-import androidx.compose.ui.text.Placeholder
-import androidx.compose.ui.text.PlaceholderVerticalAlign
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.buildAnnotatedString
-import androidx.compose.ui.text.style.TextDirection
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.sp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import com.google.common.truth.Truth.assertThat
-import com.nhaarman.mockitokotlin2.mock
-import com.nhaarman.mockitokotlin2.verify
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class CoreTextInlineContentTest {
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    private val fontSize = 10
-
-    private val textStyle = TextStyle(fontSize = fontSize.sp, fontFamily = TEST_FONT_FAMILY)
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    fun placeholder_changeSize_updateInlineContentSize() {
-        // Callback to monitor the size changes of a composable.
-        val onSizeChanged: (IntSize) -> Unit = mock()
-        var size by mutableStateOf(IntSize(50, 50))
-
-        rule.setContent {
-            val inlineTextContent = InlineTextContent(
-                placeholder = Placeholder(
-                    size.width.sp,
-                    size.height.sp,
-                    PlaceholderVerticalAlign.AboveBaseline
-                )
-            ) {
-                Box(modifier = Modifier.fillMaxSize().onSizeChanged(onSizeChanged))
-            }
-
-            CompositionLocalProvider(
-                LocalDensity provides Density(density = 1f, fontScale = 1f)
-            ) {
-                TextUsingModifier(
-                    text = buildAnnotatedString {
-                        append("Hello")
-                        appendInlineContent("box")
-                        append("World")
-                    },
-                    style = TextStyle(fontSize = 100.sp),
-                    inlineContent = mapOf("box" to inlineTextContent),
-                    maxLines = Int.MAX_VALUE,
-                    onTextLayout = {},
-                    overflow = TextOverflow.Clip,
-                    softWrap = true
-                )
-            }
-        }
-
-        rule.runOnIdle {
-            // Verify that the initial size is (50, 50).
-            verify(onSizeChanged).invoke(IntSize(50, 50))
-            size = IntSize(100, 100)
-        }
-        rule.waitForIdle()
-        // Verify that the size has been updated to (100, 100).
-        verify(onSizeChanged).invoke(IntSize(100, 100))
-    }
-
-    @Test
-    fun rtlLayout_inlineContent_placement() {
-        rule.setContent {
-            CompositionLocalProvider(
-                LocalLayoutDirection provides LayoutDirection.Ltr,
-            ) {
-                // LTR character, supported by sample_font
-                TestContent(
-                    predicate = "\u0061\u0061\u0061\u0061\u0061",
-                    suffix = "\u0061\u0061\u0061"
-                )
-            }
-        }
-
-        // Expected text layout; "a" is LTR, "b" is RTL"
-        // Text[aaaaa[inline-content]aaa]
-        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
-    }
-
-    @Test
-    fun rtlTextContent_inlineContent_placement() {
-        rule.setContent {
-            // RTL character, supported by sample_font
-            TestContent(
-                predicate = "\u05D1\u05D1\u05D1\u05D1\u05D1",
-                suffix = "\u05D1\u05D1\u05D1"
-            )
-        }
-
-        // Expected text layout; "a" is LTR, "b" is RTL"
-        // Text[bbb[inline-content]bbbbb]
-        expectInlineContentPosition(left = fontSize * 3, right = fontSize * 5)
-    }
-
-    @Test
-    fun rtlTextDirection_inlineContent_placement() {
-        rule.setContent {
-            // LTR character, supported by sample_font
-            TestContent(
-                predicate = "\u0061\u0061\u0061\u0061\u0061",
-                suffix = "\u0061\u0061\u0061",
-                textStyle = textStyle.copy(textDirection = TextDirection.Rtl)
-            )
-        }
-
-        // Expected text layout; "a" is LTR, "b" is RTL"
-        // Text[aaaaa[inline-content]aaa]
-        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
-    }
-
-    @Test
-    fun bidiText_inlineContent_placement() {
-        rule.setContent {
-            // RTL and LTR characters, supported by sample_font
-            TestContent(
-                predicate = "\u05D1\u05D1\u05D1\u0061\u0061",
-                suffix = "\u0061\u0061\u0061"
-            )
-        }
-
-        // Expected text layout; "a" is LTR, "b" is RTL"
-        // Text[bbbaa[inline-content]aaa]
-        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
-    }
-
-    @Test
-    fun bidiText_2_inlineContent_placement() {
-        rule.setContent {
-            // RTL and LTR characters, supported by sample_font
-            TestContent(
-                predicate = "\u0061\u0061\u0061\u05D1\u05D1",
-                suffix = "\u05D1\u05D1\u05D1"
-            )
-        }
-
-        // Expected text layout; "a" is LTR, "b" is RTL"
-        // Text[aaabbb[inline-content]bb]
-        expectInlineContentPosition(left = fontSize * 6, right = fontSize * 2)
-    }
-
-    @OptIn(ExperimentalTextApi::class)
-    @Composable
-    private fun TestContent(
-        predicate: String,
-        suffix: String,
-        textStyle: TextStyle = this.textStyle
-    ) {
-        CompositionLocalProvider(
-            LocalDensity provides Density(density = 1f, fontScale = 1f)
-        ) {
-            val inlineTextContent = InlineTextContent(
-                placeholder = Placeholder(
-                    fontSize.sp,
-                    fontSize.sp,
-                    PlaceholderVerticalAlign.AboveBaseline
-                )
-            ) {
-                Box(modifier = Modifier.fillMaxSize().testTag("box"))
-            }
-
-            TextUsingModifier(
-                text = buildAnnotatedString {
-                    append(predicate)
-                    appendInlineContent("box")
-                    append(suffix)
-                },
-                modifier = Modifier.testTag("text"),
-                style = textStyle,
-                inlineContent = mapOf("box" to inlineTextContent),
-                maxLines = 1
-            )
-        }
-    }
-
-    private fun expectInlineContentPosition(left: Int, right: Int) {
-        val (boxLeft, boxRight) = with(rule.onNodeWithTag("box").fetchSemanticsNode()) {
-            Pair(positionInRoot.x, positionInRoot.x + size.width)
-        }
-        val (textLeft, textRight) = with(rule.onNodeWithTag("text").fetchSemanticsNode()) {
-            Pair(positionInRoot.x, positionInRoot.x + size.width)
-        }
-
-        rule.waitForIdle()
-
-        assertThat(boxLeft - textLeft).isEqualTo(left)
-        assertThat(textRight - boxRight).isEqualTo(right)
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextLayoutTest.kt b/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextLayoutTest.kt
deleted file mode 100644
index 235fe0f..0000000
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextLayoutTest.kt
+++ /dev/null
@@ -1,250 +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.newtext.text
-
-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.layout.FirstBaseline
-import androidx.compose.ui.layout.IntrinsicMeasurable
-import androidx.compose.ui.layout.IntrinsicMeasureScope
-import androidx.compose.ui.layout.LastBaseline
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.Measurable
-import androidx.compose.ui.layout.MeasurePolicy
-import androidx.compose.ui.layout.MeasureResult
-import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.node.Ref
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.IntSize
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@MediumTest
-class TextLayoutTest {
-    @get:Rule
-    val rule = createComposeRule()
-
-    @Test
-    fun textLayout() {
-        val textSize = Ref<IntSize>()
-        val doubleTextSize = Ref<IntSize>()
-        rule.setContent {
-            TestingText(
-                "aa",
-                modifier = Modifier.onGloballyPositioned { coordinates ->
-                    textSize.value = coordinates.size
-                }
-            )
-            TestingText(
-                "aaaa",
-                modifier = Modifier.onGloballyPositioned { coordinates ->
-                    doubleTextSize.value = coordinates.size
-                }
-            )
-        }
-
-        rule.runOnIdle {
-            assertThat(textSize.value).isNotNull()
-            assertThat(doubleTextSize.value).isNotNull()
-            assertThat(textSize.value!!.width).isGreaterThan(0)
-            assertThat(textSize.value!!.height).isGreaterThan(0)
-            assertThat(textSize.value!!.width * 2).isEqualTo(doubleTextSize.value!!.width)
-            assertThat(textSize.value!!.height).isEqualTo(doubleTextSize.value!!.height)
-        }
-    }
-
-    @Test
-    fun textLayout_intrinsicMeasurements() {
-        val textSize = Ref<IntSize>()
-        val doubleTextSize = Ref<IntSize>()
-        var textMeasurable by mutableStateOf<Measurable?>(null)
-
-        rule.setContent {
-            TestingText(
-                "aa ",
-                modifier = Modifier.onSizeChanged { textSize.value = it }
-            )
-            TestingText(
-                "aa aa ",
-                modifier = Modifier.onSizeChanged { doubleTextSize.value = it }
-            )
-
-            Layout(
-                content = {
-                    TestingText("aa aa ")
-                },
-                measurePolicy = object : MeasurePolicy {
-                    override fun MeasureScope.measure(
-                        measurables: List<Measurable>,
-                        constraints: Constraints
-                    ): MeasureResult {
-                        measurables.forEach {
-                            it.measure(constraints)
-                        }
-                        textMeasurable = measurables.first()
-                        return layout(0, 0) {}
-                    }
-
-                    override fun IntrinsicMeasureScope.minIntrinsicWidth(
-                        measurables: List<IntrinsicMeasurable>,
-                        height: Int
-                    ) = 0
-
-                    override fun IntrinsicMeasureScope.minIntrinsicHeight(
-                        measurables: List<IntrinsicMeasurable>,
-                        width: Int
-                    ) = 0
-
-                    override fun IntrinsicMeasureScope.maxIntrinsicWidth(
-                        measurables: List<IntrinsicMeasurable>,
-                        height: Int
-                    ) = 0
-
-                    override fun IntrinsicMeasureScope.maxIntrinsicHeight(
-                        measurables: List<IntrinsicMeasurable>,
-                        width: Int
-                    ) = 0
-                }
-            )
-        }
-
-        rule.runOnIdle {
-            val textWidth = textSize.value!!.width
-            val textHeight = textSize.value!!.height
-            val doubleTextWidth = doubleTextSize.value!!.width
-
-            textMeasurable!!.let { textMeasurable ->
-                // Min width.
-                assertThat(textWidth).isEqualTo(textMeasurable.minIntrinsicWidth(0))
-                // Min height.
-                assertThat(textMeasurable.minIntrinsicHeight(textWidth))
-                    .isGreaterThan(textHeight)
-                assertThat(textHeight)
-                    .isEqualTo(textMeasurable.minIntrinsicHeight(doubleTextWidth))
-                assertThat(textHeight)
-                    .isEqualTo(textMeasurable.minIntrinsicHeight(Constraints.Infinity))
-
-                // Max width.
-                assertThat(doubleTextWidth).isEqualTo(textMeasurable.maxIntrinsicWidth(0))
-                // Max height.
-                assertThat(textMeasurable.maxIntrinsicHeight(textWidth))
-                    .isGreaterThan(textHeight)
-                assertThat(textHeight)
-                    .isEqualTo(textMeasurable.maxIntrinsicHeight(doubleTextWidth))
-                assertThat(textHeight)
-                    .isEqualTo(textMeasurable.maxIntrinsicHeight(Constraints.Infinity))
-            }
-        }
-    }
-
-    @Test
-    fun textLayout_providesBaselines_whenUnconstrained() {
-        var firstBaseline by mutableStateOf(-1)
-        var lastBaseline by mutableStateOf(-1)
-
-        rule.setContent {
-            Layout({
-                TestingText("aa")
-            }) { measurables, _ ->
-                val placeable = measurables.first().measure(Constraints())
-                firstBaseline = placeable[FirstBaseline]
-                lastBaseline = placeable[LastBaseline]
-                layout(0, 0) {}
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(firstBaseline).isGreaterThan(-1)
-            assertThat(lastBaseline).isGreaterThan(-1)
-            assertThat(firstBaseline).isEqualTo(lastBaseline)
-        }
-    }
-
-    @Test
-    fun textLayout_providesBaselines_whenZeroMaxWidth() {
-        var firstBaseline by mutableStateOf(-1)
-        var lastBaseline by mutableStateOf(-1)
-
-        rule.setContent {
-            Layout({
-                TestingText("aa")
-            }) { measurables, _ ->
-                val placeable = measurables.first().measure(Constraints(maxWidth = 0))
-                firstBaseline = placeable[FirstBaseline]
-                lastBaseline = placeable[LastBaseline]
-                layout(0, 0) {}
-            }
-        }
-
-        rule.runOnIdle {
-            assertThat(firstBaseline).isGreaterThan(-1)
-            assertThat(lastBaseline).isGreaterThan(-1)
-            assertThat(firstBaseline).isLessThan(lastBaseline)
-        }
-    }
-
-    @Test
-    fun textLayout_OnTextLayoutCallback() {
-        val resultsFromCallback = mutableListOf<TextLayoutResult>()
-        rule.setContent {
-            TestingText("aa", onTextLayout = { resultsFromCallback += it })
-        }
-
-        rule.runOnIdle {
-            assertThat(resultsFromCallback).hasSize(1)
-        }
-    }
-}
-
-@OptIn(ExperimentalTextApi::class)
-@Composable
-private fun TestingText(
-    text: String,
-    modifier: Modifier = Modifier,
-    onTextLayout: (TextLayoutResult) -> Unit = {}
-) {
-    val textStyle = remember {
-        TextStyle(fontFamily = TEST_FONT_FAMILY)
-    }
-    TextUsingModifier(
-        AnnotatedString(text),
-        style = textStyle,
-        modifier = modifier,
-        softWrap = true,
-        maxLines = Int.MAX_VALUE,
-        overflow = TextOverflow.Clip,
-        inlineContent = mapOf(),
-        onTextLayout = onTextLayout
-    )
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextOverflowTest.kt b/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextOverflowTest.kt
deleted file mode 100644
index 40f0959..0000000
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextOverflowTest.kt
+++ /dev/null
@@ -1,163 +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.newtext.text
-
-import android.graphics.Bitmap
-import android.os.Build
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.heightIn
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.testutils.assertContainsColor
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asAndroidBitmap
-import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalFontFamilyResolver
-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.ExperimentalTextApi
-import androidx.compose.ui.text.ParagraphStyle
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.buildAnnotatedString
-import androidx.compose.ui.text.font.createFontFamilyResolver
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.text.withStyle
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.LargeTest
-import androidx.test.filters.SdkSuppress
-import androidx.test.platform.app.InstrumentationRegistry
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class TextOverflowTest {
-    @get:Rule
-    val rule = createComposeRule()
-
-    private val density = Density(1f)
-    private val fontFamilyResolver =
-        createFontFamilyResolver(InstrumentationRegistry.getInstrumentation().context)
-    private val fontFamily = TEST_FONT_FAMILY
-
-    private val BoxTag = "wrapping box"
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    fun paint_singleParagraph_withVisibleOverflow() {
-        val text = "Hello\nHello\nHello\nHello"
-
-        val lineHeight = 20
-        val boxHeight = 100
-        val boxWidth = 200
-
-        rule.setContent {
-            CompositionLocalProvider(
-                LocalDensity provides density,
-                LocalFontFamilyResolver provides fontFamilyResolver
-            ) {
-                Box(Modifier.testTag(BoxTag).size(boxWidth.dp, boxHeight.dp)) {
-                    TextUsingModifier(
-                        text = text,
-                        modifier = Modifier
-                            .fillMaxWidth()
-                            .heightIn(max = (2 * lineHeight).dp)
-                            .padding(bottom = lineHeight.dp),
-                        style = TextStyle(
-                            fontSize = 20.sp,
-                            fontFamily = fontFamily,
-                            color = Color.Red,
-                            lineHeight = 20.sp
-                        ),
-                        overflow = TextOverflow.Visible
-                    )
-                }
-            }
-        }
-
-        val boxBitmap = rule.onNodeWithTag(BoxTag).captureToImage().asAndroidBitmap()
-        val croppedBoxBitmap = Bitmap.createBitmap(
-            boxBitmap,
-            0,
-            2 * lineHeight,
-            boxWidth,
-            boxHeight - 2 * lineHeight
-        )
-        croppedBoxBitmap.asImageBitmap().assertContainsColor(Color.Red)
-    }
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    fun paint_multiParagraph_withVisibleOverflow() {
-        val text = buildAnnotatedString {
-            append("Hello\nHello")
-            withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
-                append("Hello\nHello")
-            }
-        }
-        val lineHeight = 20
-        val boxHeight = 100
-        val boxWidth = 200
-
-        rule.setContent {
-            CompositionLocalProvider(
-                LocalDensity provides density,
-                LocalFontFamilyResolver provides fontFamilyResolver
-            ) {
-                Box(Modifier.testTag(BoxTag).size(boxWidth.dp, boxHeight.dp)) {
-                    TextUsingModifier(
-                        text = text,
-                        modifier = Modifier
-                            .fillMaxWidth()
-                            .heightIn(max = (2 * lineHeight).dp)
-                            .padding(bottom = lineHeight.dp),
-                        style = TextStyle(
-                            fontSize = 20.sp,
-                            fontFamily = fontFamily,
-                            color = Color.Red,
-                            lineHeight = 20.sp
-                        ),
-                        overflow = TextOverflow.Visible
-                    )
-                }
-            }
-        }
-
-        val boxBitmap = rule.onNodeWithTag(BoxTag).captureToImage().asAndroidBitmap()
-        val croppedBoxBitmap = Bitmap.createBitmap(
-            boxBitmap,
-            0,
-            2 * lineHeight,
-            boxWidth,
-            boxHeight - 2 * lineHeight
-        )
-        croppedBoxBitmap.asImageBitmap().assertContainsColor(Color.Red)
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextStyleInvalidationTest.kt b/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextStyleInvalidationTest.kt
deleted file mode 100644
index ed1996f..0000000
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextStyleInvalidationTest.kt
+++ /dev/null
@@ -1,349 +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.newtext.text
-
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.graphics.Brush
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.graphics.drawscope.Stroke
-import androidx.compose.ui.layout.layout
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.PlatformTextStyle
-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.FontWeight
-import androidx.compose.ui.text.intl.LocaleList
-import androidx.compose.ui.text.style.BaselineShift
-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.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.IntOffset
-import androidx.compose.ui.unit.sp
-import androidx.test.filters.MediumTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-import org.junit.runners.Parameterized.Parameters
-
-@Suppress("DEPRECATION")
-@RunWith(Parameterized::class)
-@MediumTest
-class TextStyleInvalidationTest(private val config: Config) {
-
-    class Config(
-        private val description: String,
-        val updateStyle: (TextStyle) -> TextStyle,
-        val initializeStyle: (TextStyle) -> TextStyle = { it },
-        val invalidatesMeasure: Boolean = false,
-        val invalidatesPlacement: Boolean = false,
-        val invalidatesDraw: Boolean = false,
-    ) {
-        override fun toString(): String = buildString {
-            append(description)
-            listOfNotNull(
-                "measure".takeIf { invalidatesMeasure },
-                "placement".takeIf { invalidatesPlacement },
-                "draw".takeIf { invalidatesDraw },
-            ).joinTo(this, prefix = " ", separator = ", ") { "invalidates $it" }
-        }
-    }
-
-    @OptIn(ExperimentalTextApi::class)
-    companion object {
-        @Parameters(name = "{0}")
-        @JvmStatic
-        fun parameters() = arrayOf(
-            Config("nothing", { it }),
-            Config(
-                "color",
-                { it.copy(color = Color.Blue) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "to brush",
-                { it.copy(brush = Brush.verticalGradient(0f to Color.Blue, 1f to Color.Magenta)) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "from brush to brush",
-                initializeStyle = {
-                    it.copy(brush = Brush.verticalGradient(0f to Color.Black, 1f to Color.Magenta))
-                },
-                updateStyle = {
-                    it.copy(brush = Brush.verticalGradient(0f to Color.Blue, 1f to Color.Magenta))
-                },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "alpha",
-                initializeStyle = {
-                    it.copy(
-                        alpha = 1f,
-                        brush = Brush.verticalGradient(0f to Color.Blue, 1f to Color.Magenta)
-                    )
-                },
-                updateStyle = { it.copy(alpha = 0.5f, brush = it.brush) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "fontSize",
-                { it.copy(fontSize = it.fontSize * 2) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "fontWeight",
-                { it.copy(fontWeight = FontWeight(it.fontWeight!!.weight * 2)) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "fontStyle",
-                { it.copy(fontStyle = FontStyle.Italic) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true
-            ),
-            Config(
-                "fontSynthesis",
-                { it.copy(fontSynthesis = FontSynthesis.All) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "fontFamily",
-                { it.copy(fontFamily = FontFamily.Cursive) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "fontFeatureSettings",
-                initializeStyle = { it.copy(fontFeatureSettings = "a") },
-                updateStyle = { it.copy(fontFeatureSettings = "b") },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "letterSpacing",
-                { it.copy(letterSpacing = it.letterSpacing * 2) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "baselineShift",
-                { it.copy(baselineShift = BaselineShift.Superscript) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "textGeometricTransform",
-                { it.copy(textGeometricTransform = TextGeometricTransform(scaleX = 2f)) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "localeList",
-                initializeStyle = { it.copy(localeList = LocaleList("en-US")) },
-                updateStyle = { it.copy(localeList = LocaleList("en-GB")) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "background",
-                { it.copy(background = Color.Blue) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "textDecoration",
-                { it.copy(textDecoration = TextDecoration.LineThrough) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "to shadow",
-                { it.copy(shadow = Shadow(Color.Black, blurRadius = 4f)) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "from shadow to shadow",
-                initializeStyle = { it.copy(shadow = Shadow(Color.Black, blurRadius = 1f)) },
-                updateStyle = { it.copy(shadow = Shadow(Color.Black, blurRadius = 4f)) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "to drawStyle",
-                { it.copy(drawStyle = Stroke(width = 1f)) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "from drawStyle to drawStyle",
-                initializeStyle = { it.copy(drawStyle = Stroke(width = 0f)) },
-                updateStyle = { it.copy(drawStyle = Stroke(width = 1f)) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "textAlign",
-                { it.copy(textAlign = TextAlign.Justify) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "textDirection",
-                { it.copy(textDirection = TextDirection.Rtl) },
-                invalidatesDraw = true,
-            ),
-            Config(
-                "lineHeight",
-                { it.copy(lineHeight = it.lineHeight * 2) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "textIndent",
-                { it.copy(textIndent = TextIndent(firstLine = 5.sp)) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "platformStyle",
-                initializeStyle = {
-                    it.copy(platformStyle = PlatformTextStyle(includeFontPadding = true))
-                },
-                updateStyle = {
-                    it.copy(platformStyle = PlatformTextStyle(includeFontPadding = false))
-                },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "lineHeightStyle",
-                {
-                    it.copy(
-                        lineHeightStyle = LineHeightStyle(
-                            alignment = LineHeightStyle.Alignment.Center,
-                            trim = LineHeightStyle.Trim.FirstLineTop
-                        )
-                    )
-                },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "lineBreak",
-                { it.copy(lineBreak = LineBreak.Heading) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-            Config(
-                "hyphens",
-                { it.copy(hyphens = Hyphens.Auto) },
-                invalidatesMeasure = true,
-                invalidatesDraw = true,
-            ),
-        )
-    }
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    @OptIn(ExperimentalTextApi::class)
-    @Test
-    fun changing() {
-        // Don't leave any TextUnits Unspecified so test cases can double them to invalidate.
-        var style by mutableStateOf(
-            TextStyle(
-                color = Color.Black,
-                fontSize = 12.sp,
-                fontWeight = FontWeight.Normal,
-                fontStyle = null,
-                fontSynthesis = null,
-                fontFamily = TEST_FONT_FAMILY,
-                fontFeatureSettings = null,
-                letterSpacing = 12.sp,
-                baselineShift = null,
-                textGeometricTransform = null,
-                localeList = null,
-                background = Color.White,
-                textDecoration = null,
-                shadow = null,
-                textAlign = TextAlign.Start,
-                textDirection = TextDirection.Ltr,
-                lineHeight = 12.sp,
-                textIndent = null,
-            ).let(config.initializeStyle)
-        )
-        var measures = 0
-        var placements = 0
-        var draws = 0
-
-        rule.setContent {
-            TextUsingModifier(
-                "a",
-                style = style,
-                modifier = Modifier
-                    .layout { measurable, constraints ->
-                        measures++
-                        val placeable = measurable.measure(constraints)
-                        layout(placeable.width, placeable.height) {
-                            placements++
-                            placeable.place(IntOffset.Zero)
-                        }
-                    }
-                    .drawBehind {
-                        draws++
-                    }
-            )
-        }
-
-        rule.waitForIdle()
-        val initialMeasures = measures
-        val initialPlacements = placements
-        val initialDraws = draws
-
-        style = config.updateStyle(style)
-
-        rule.runOnIdle {
-            if (config.invalidatesMeasure) {
-                assertThat(measures).isGreaterThan(initialMeasures)
-            }
-            if (config.invalidatesPlacement) {
-                assertThat(placements).isGreaterThan(initialPlacements)
-
-                // If measure is invalidated, placement will also always be invalidated, so ensure
-                // that placement was also invalidated separately from measurement.
-                if (config.invalidatesMeasure) {
-                    assertThat(placements).isGreaterThan(measures)
-                }
-            }
-            if (config.invalidatesDraw) {
-                assertThat(draws).isGreaterThan(initialDraws)
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextTestExtensions.kt b/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextTestExtensions.kt
deleted file mode 100644
index a5d9af5..0000000
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextTestExtensions.kt
+++ /dev/null
@@ -1,34 +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.newtext.text
-
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.font.toFontFamily
-import androidx.testutils.fonts.R
-import kotlin.math.ceil
-import kotlin.math.roundToInt
-
-fun Float.toIntPx(): Int = ceil(this).roundToInt()
-
-val TEST_FONT = Font(
-    resId = R.font.sample_font,
-    weight = FontWeight.Normal,
-    style = FontStyle.Normal
-)
-
-val TEST_FONT_FAMILY = TEST_FONT.toFontFamily()
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.android.kt b/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.android.kt
deleted file mode 100644
index f907321..0000000
--- a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.android.kt
+++ /dev/null
@@ -1,28 +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.newtext.text.copypasta
-
-import androidx.compose.foundation.newtext.text.copypasta.selection.SelectionManager
-import androidx.compose.runtime.Composable
-
-@Composable
-internal actual fun ContextMenuArea(
-    manager: SelectionManager,
-    content: @Composable () -> Unit
-) {
-    content()
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.android.kt b/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.android.kt
deleted file mode 100644
index 92cb068..0000000
--- a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.android.kt
+++ /dev/null
@@ -1,44 +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.newtext.text.copypasta
-
-import androidx.emoji2.text.EmojiCompat
-import java.text.BreakIterator
-
-internal actual fun String.findPrecedingBreak(index: Int): Int {
-    val emojiBreak =
-        getEmojiCompatIfLoaded()?.getEmojiStart(this, maxOf(0, index - 1))?.takeUnless { it == -1 }
-    if (emojiBreak != null) return emojiBreak
-
-    val it = BreakIterator.getCharacterInstance()
-    it.setText(this)
-    return it.preceding(index)
-}
-
-internal actual fun String.findFollowingBreak(index: Int): Int {
-    val emojiBreak = getEmojiCompatIfLoaded()?.getEmojiEnd(this, index)?.takeUnless { it == -1 }
-    if (emojiBreak != null) return emojiBreak
-
-    val it = BreakIterator.getCharacterInstance()
-    it.setText(this)
-    return it.following(index)
-}
-
-private fun getEmojiCompatIfLoaded(): EmojiCompat? =
-    if (EmojiCompat.isConfigured())
-        EmojiCompat.get().takeIf { it.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED }
-    else null
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.android.kt b/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.android.kt
deleted file mode 100644
index 6645638..0000000
--- a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.android.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.newtext.text.copypasta
-
-import androidx.compose.ui.input.pointer.PointerIcon
-
-internal actual val textPointerIcon: PointerIcon =
-    PointerIcon(android.view.PointerIcon.TYPE_TEXT)
diff --git a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/AndroidSelectionHandles.android.kt b/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/AndroidSelectionHandles.android.kt
deleted file mode 100644
index 50a2e51..0000000
--- a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/AndroidSelectionHandles.android.kt
+++ /dev/null
@@ -1,326 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.newtext.text.copypasta.selection.HandleReferencePoint.TopLeft
-import androidx.compose.foundation.newtext.text.copypasta.selection.HandleReferencePoint.TopMiddle
-import androidx.compose.foundation.newtext.text.copypasta.selection.HandleReferencePoint.TopRight
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.draw.CacheDrawScope
-import androidx.compose.ui.draw.drawWithCache
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.graphics.BlendMode
-import androidx.compose.ui.graphics.Canvas
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorFilter
-import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.ImageBitmapConfig
-import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
-import androidx.compose.ui.graphics.drawscope.scale
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.text.style.ResolvedTextDirection
-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 androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.PopupProperties
-import kotlin.math.ceil
-import kotlin.math.roundToInt
-
-@Composable
-internal actual fun SelectionHandle(
-    position: Offset,
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean,
-    modifier: Modifier,
-    content: @Composable (() -> Unit)?
-) {
-    val isLeft = isLeft(isStartHandle, direction, handlesCrossed)
-    // The left selection handle's top right is placed at the given position, and vice versa.
-    val handleReferencePoint = if (isLeft) {
-        TopRight
-    } else {
-        TopLeft
-    }
-
-    HandlePopup(position = position, handleReferencePoint = handleReferencePoint) {
-        if (content == null) {
-            DefaultSelectionHandle(
-                modifier = modifier
-                    .semantics {
-                        this[SelectionHandleInfoKey] = SelectionHandleInfo(
-                            position = position
-                        )
-                    },
-                isStartHandle = isStartHandle,
-                direction = direction,
-                handlesCrossed = handlesCrossed
-            )
-        } else {
-            content()
-        }
-    }
-}
-
-@Composable
-/*@VisibleForTesting*/
-internal fun DefaultSelectionHandle(
-    modifier: Modifier,
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean
-) {
-    Spacer(
-        modifier.size(
-            HandleWidth,
-            HandleHeight
-        )
-            .drawSelectionHandle(isStartHandle, direction, handlesCrossed)
-    )
-}
-
-internal fun Modifier.drawSelectionHandle(
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean
-) = composed {
-    val handleColor = LocalTextSelectionColors.current.handleColor
-    this.then(
-        Modifier.drawWithCache {
-            val radius = size.width / 2f
-            val handleImage = createHandleImage(radius)
-            val colorFilter = ColorFilter.tint(handleColor)
-            onDrawWithContent {
-                drawContent()
-                val isLeft = isLeft(isStartHandle, direction, handlesCrossed)
-                if (isLeft) {
-                    // Flip the selection handle horizontally.
-                    scale(scaleX = -1f, scaleY = 1f) {
-                        drawImage(
-                            image = handleImage,
-                            colorFilter = colorFilter
-                        )
-                    }
-                } else {
-                    drawImage(
-                        image = handleImage,
-                        colorFilter = colorFilter
-                    )
-                }
-            }
-        }
-    )
-}
-
-/**
- * The cache for the image mask created to draw selection/cursor handle, so that we don't need to
- * recreate them.
- */
-private object HandleImageCache {
-    var imageBitmap: ImageBitmap? = null
-    var canvas: Canvas? = null
-    var canvasDrawScope: CanvasDrawScope? = null
-}
-
-/**
- * Create an image bitmap for the basic shape of a selection handle or cursor handle. It is an
- * circle with a rectangle covering its left top part.
- *
- * To draw the right selection handle, directly draw this image bitmap.
- * To draw the left selection handle, mirror the canvas first and then draw this image bitmap.
- * To draw the cursor handle, translate and rotated the canvas 45 degrees, then draw this image
- * bitmap.
- *
- * @param radius the radius of circle in selection/cursor handle.
- * CanvasDrawScope objects so that we only recreate them when necessary.
- */
-internal fun CacheDrawScope.createHandleImage(radius: Float): ImageBitmap {
-    // The edge length of the square bounding box of the selection/cursor handle. This is also
-    // the size of the bitmap needed for the bitmap mask.
-    val edge = ceil(radius).toInt() * 2
-
-    var imageBitmap = HandleImageCache.imageBitmap
-    var canvas = HandleImageCache.canvas
-    var drawScope = HandleImageCache.canvasDrawScope
-
-    // If the cached bitmap is null or too small, we need to create new bitmap.
-    if (
-        imageBitmap == null ||
-        canvas == null ||
-        edge > imageBitmap.width ||
-        edge > imageBitmap.height
-    ) {
-        imageBitmap = ImageBitmap(
-            width = edge,
-            height = edge,
-            config = ImageBitmapConfig.Alpha8
-        )
-        HandleImageCache.imageBitmap = imageBitmap
-        canvas = Canvas(imageBitmap)
-        HandleImageCache.canvas = canvas
-    }
-    if (drawScope == null) {
-        drawScope = CanvasDrawScope()
-        HandleImageCache.canvasDrawScope = drawScope
-    }
-
-    drawScope.draw(
-        this,
-        layoutDirection,
-        canvas,
-        Size(imageBitmap.width.toFloat(), imageBitmap.height.toFloat())
-    ) {
-        // Clear the previously rendered portion within this ImageBitmap as we could
-        // be re-using it
-        drawRect(
-            color = Color.Black,
-            size = size,
-            blendMode = BlendMode.Clear
-        )
-
-        // Draw the rectangle at top left.
-        drawRect(
-            color = Color(0xFF000000),
-            topLeft = Offset.Zero,
-            size = Size(radius, radius)
-        )
-        // Draw the circle
-        drawCircle(
-            color = Color(0xFF000000),
-            radius = radius,
-            center = Offset(radius, radius)
-        )
-    }
-    return imageBitmap
-}
-
-@Composable
-internal fun HandlePopup(
-    position: Offset,
-    handleReferencePoint: HandleReferencePoint,
-    content: @Composable () -> Unit
-) {
-    val intOffset = IntOffset(position.x.roundToInt(), position.y.roundToInt())
-
-    val popupPositioner = remember(handleReferencePoint, intOffset) {
-        HandlePositionProvider(handleReferencePoint, intOffset)
-    }
-
-    Popup(
-        popupPositionProvider = popupPositioner,
-        properties = PopupProperties(
-            excludeFromSystemGesture = true,
-            clippingEnabled = false
-        ),
-        content = content
-    )
-}
-
-/**
- * The enum that specifies how a selection/cursor handle is placed to its given position.
- * When this value is [TopLeft], the top left corner of the handle will be placed at the
- * given position.
- * When this value is [TopRight], the top right corner of the handle will be placed at the
- * given position.
- * When this value is [TopMiddle], the handle top edge's middle point will be placed at the given
- * position.
- */
-internal enum class HandleReferencePoint {
-    TopLeft,
-    TopRight,
-    TopMiddle
-}
-
-/**
- * This [PopupPositionProvider] for [HandlePopup]. It will position the selection handle
- * to the [offset] in its anchor layout.
- *
- * @see HandleReferencePoint
- */
-/*@VisibleForTesting*/
-internal class HandlePositionProvider(
-    private val handleReferencePoint: HandleReferencePoint,
-    private val offset: IntOffset
-) : PopupPositionProvider {
-    override fun calculatePosition(
-        anchorBounds: IntRect,
-        windowSize: IntSize,
-        layoutDirection: LayoutDirection,
-        popupContentSize: IntSize
-    ): IntOffset {
-        return when (handleReferencePoint) {
-            TopLeft ->
-                IntOffset(
-                    x = anchorBounds.left + offset.x,
-                    y = anchorBounds.top + offset.y
-                )
-            TopRight ->
-                IntOffset(
-                    x = anchorBounds.left + offset.x - popupContentSize.width,
-                    y = anchorBounds.top + offset.y
-                )
-            TopMiddle ->
-                IntOffset(
-                    x = anchorBounds.left + offset.x - popupContentSize.width / 2,
-                    y = anchorBounds.top + offset.y
-                )
-        }
-    }
-}
-
-/**
- * Computes whether the handle's appearance should be left-pointing or right-pointing.
- */
-private fun isLeft(
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean
-): Boolean {
-    return if (isStartHandle) {
-        isHandleLtrDirection(direction, handlesCrossed)
-    } else {
-        !isHandleLtrDirection(direction, handlesCrossed)
-    }
-}
-
-/**
- * This method is to check if the selection handles should use the natural Ltr pointing
- * direction.
- * If the context is Ltr and the handles are not crossed, or if the context is Rtl and the handles
- * are crossed, return true.
- *
- * In Ltr context, the start handle should point to the left, and the end handle should point to
- * the right. However, in Rtl context or when handles are crossed, the start handle should point to
- * the right, and the end handle should point to left.
- */
-/*@VisibleForTesting*/
-internal fun isHandleLtrDirection(
-    direction: ResolvedTextDirection,
-    areHandlesCrossed: Boolean
-): Boolean {
-    return direction == ResolvedTextDirection.Ltr && !areHandlesCrossed ||
-        direction == ResolvedTextDirection.Rtl && areHandlesCrossed
-}
diff --git a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.android.kt b/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.android.kt
deleted file mode 100644
index fa0d056..0000000
--- a/compose/foundation/foundation-newtext/src/androidMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.android.kt
+++ /dev/null
@@ -1,69 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.MagnifierStyle
-import androidx.compose.foundation.magnifier
-
-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.composed
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.unit.IntSize
-
-// TODO(b/139322105) Implement for Android when hardware keyboard is implemented
-internal actual fun isCopyKeyEvent(keyEvent: KeyEvent) = false
-
-// We use composed{} to read a local, but don't provide inspector info because the underlying
-// magnifier modifier provides more meaningful inspector info.
-@OptIn(ExperimentalFoundationApi::class)
-internal actual fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier {
-    // Avoid tracking animation state on older Android versions that don't support magnifiers.
-    if (!MagnifierStyle.TextDefault.isSupported) {
-        return this
-    }
-
-    return composed {
-        val density = LocalDensity.current
-        var magnifierSize by remember { mutableStateOf(IntSize.Zero) }
-        animatedSelectionMagnifier(
-            magnifierCenter = {
-                calculateSelectionMagnifierCenterAndroid(
-                    manager,
-                    magnifierSize
-                )
-            },
-            platformMagnifier = { center ->
-                Modifier
-                    .magnifier(
-                        sourceCenter = { center() },
-                        onSizeChanged = { size ->
-                            magnifierSize = with(density) {
-                                IntSize(size.width.roundToPx(), size.height.roundToPx())
-                            }
-                        },
-                        style = MagnifierStyle.TextDefault
-                    )
-            }
-        )
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/Helpers.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/Helpers.kt
deleted file mode 100644
index c6ce37f..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/Helpers.kt
+++ /dev/null
@@ -1,40 +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.newtext.text
-
-import androidx.compose.ui.util.fastForEachIndexed
-import kotlin.contracts.ExperimentalContracts
-import kotlin.contracts.contract
-import kotlin.math.ceil
-import kotlin.math.roundToInt
-
-@OptIn(ExperimentalContracts::class)
-@Suppress("BanInlineOptIn") // Treat Kotlin Contracts as non-experimental.
-internal inline fun <T, R> List<T>.fastMapIndexedNotNull(
-    transform: (index: Int, T) -> R?
-): List<R> {
-    contract { callsInPlace(transform) }
-    val target = ArrayList<R>(size)
-    fastForEachIndexed { index, e ->
-        transform(index, e)?.let { target += it }
-    }
-    return target
-}
-
-internal fun Float.ceilToIntPx(): Int = ceil(this).roundToInt()
-
-internal const val DefaultMinLines = 1
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.kt
deleted file mode 100644
index b42ab4e..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.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.newtext.text.copypasta
-
-import androidx.compose.foundation.newtext.text.copypasta.selection.SelectionManager
-import androidx.compose.runtime.Composable
-
-@Composable
-internal expect fun ContextMenuArea(
-    manager: SelectionManager,
-    content: @Composable () -> Unit
-)
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/Expect.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/Expect.kt
deleted file mode 100644
index ea9d587..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/Expect.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-// ktlint-disable filename
-
-/*
- * 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.newtext.text.copypasta
-
-expect class AtomicLong(value: Long) {
-    fun get(): Long
-    fun set(value: Long)
-    fun getAndIncrement(): Long
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/LongPressTextDragObserver.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/LongPressTextDragObserver.kt
deleted file mode 100644
index 934fa91..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/LongPressTextDragObserver.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.foundation.newtext.text.copypasta
-
-import androidx.compose.foundation.gestures.awaitFirstDown
-import androidx.compose.foundation.gestures.detectDragGestures
-import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.pointer.PointerInputScope
-import androidx.compose.ui.util.fastAny
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-
-internal interface TextDragObserver {
-    /**
-     * Called as soon as a down event is received. If the pointer eventually moves while remaining
-     * down, a drag gesture may be started. After this method:
-     * - [onUp] will always be called eventually, once the pointer is released.
-     * - [onStart] _may_ be called, if there is a drag that exceeds touch slop.
-     *
-     * This method will not be called before [onStart] in the case when a down event happens that
-     * may not result in a drag, e.g. on the down before a long-press that starts a selection.
-     */
-    fun onDown(point: Offset)
-
-    /**
-     * Called after [onDown] if an up event is received without dragging.
-     */
-    fun onUp()
-
-    /**
-     * Called once a drag gesture has started, which means touch slop has been exceeded.
-     * [onDown] _may_ be called before this method if the down event could not have
-     * started a different gesture.
-     */
-    fun onStart(startPoint: Offset)
-
-    fun onDrag(delta: Offset)
-
-    fun onStop()
-
-    fun onCancel()
-}
-
-internal suspend fun PointerInputScope.detectDragGesturesAfterLongPressWithObserver(
-    observer: TextDragObserver
-) = detectDragGesturesAfterLongPress(
-    onDragEnd = { observer.onStop() },
-    onDrag = { _, offset ->
-        observer.onDrag(offset)
-    },
-    onDragStart = {
-        observer.onStart(it)
-    },
-    onDragCancel = { observer.onCancel() }
-)
-
-/**
- * Detects gesture events for a [TextDragObserver], including both initial down events and drag
- * events.
- */
-internal suspend fun PointerInputScope.detectDownAndDragGesturesWithObserver(
-    observer: TextDragObserver
-) {
-    coroutineScope {
-        launch {
-            detectPreDragGesturesWithObserver(observer)
-        }
-        launch {
-            detectDragGesturesWithObserver(observer)
-        }
-    }
-}
-
-/**
- * Detects initial down events and calls [TextDragObserver.onDown] and
- * [TextDragObserver.onUp].
- */
-private suspend fun PointerInputScope.detectPreDragGesturesWithObserver(
-    observer: TextDragObserver
-) {
-    awaitEachGesture {
-        val down = awaitFirstDown()
-        observer.onDown(down.position)
-        // Wait for that pointer to come up.
-        do {
-            val event = awaitPointerEvent()
-        } while (event.changes.fastAny { it.id == down.id && it.pressed })
-        observer.onUp()
-    }
-}
-
-/**
- * Detects drag gestures for a [TextDragObserver].
- */
-private suspend fun PointerInputScope.detectDragGesturesWithObserver(
-    observer: TextDragObserver
-) {
-    detectDragGestures(
-        onDragEnd = { observer.onStop() },
-        onDrag = { _, offset ->
-            observer.onDrag(offset)
-        },
-        onDragStart = {
-            observer.onStart(it)
-        },
-        onDragCancel = { observer.onCancel() }
-    )
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.kt
deleted file mode 100644
index a63f8bf..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.kt
+++ /dev/null
@@ -1,57 +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.newtext.text.copypasta
-
-import androidx.compose.ui.text.TextRange
-
-/**
- * Returns the index of the character break preceding [index].
- */
-internal expect fun String.findPrecedingBreak(index: Int): Int
-
-/**
- * Returns the index of the character break following [index]. Returns -1 if there are no more
- * breaks before the end of the string.
- */
-internal expect fun String.findFollowingBreak(index: Int): Int
-
-internal fun CharSequence.findParagraphStart(startIndex: Int): Int {
-    for (index in startIndex - 1 downTo 1) {
-        if (this[index - 1] == '\n') {
-            return index
-        }
-    }
-    return 0
-}
-
-internal fun CharSequence.findParagraphEnd(startIndex: Int): Int {
-    for (index in startIndex + 1 until this.length) {
-        if (this[index] == '\n') {
-            return index
-        }
-    }
-    return this.length
-}
-
-/**
- * Returns the text range of the paragraph at the given character offset.
- *
- * Paragraphs are separated by Line Feed character (\n).
- */
-internal fun CharSequence.getParagraphBoundary(index: Int): TextRange {
-    return TextRange(findParagraphStart(index), findParagraphEnd(index))
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextLayoutResultProxy.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextLayoutResultProxy.kt
deleted file mode 100644
index 36d962b..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextLayoutResultProxy.kt
+++ /dev/null
@@ -1,125 +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.newtext.text.copypasta
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.text.TextLayoutResult
-
-internal class TextLayoutResultProxy(val value: TextLayoutResult) {
-    // TextLayoutResult methods
-    /**
-     * Translates the position of the touch on the screen to the position in text. Because touch
-     * is relative to the decoration box, we need to translate it to the inner text field's
-     * coordinates first before calculating position of the symbol in text.
-     *
-     * @param position original position of the gesture relative to the decoration box
-     * @param coerceInVisibleBounds if true and original [position] is outside visible bounds
-     * of the inner text field, the [position] will be shifted to the closest edge of the inner
-     * text field's visible bounds. This is useful when you have a decoration box
-     * bigger than the inner text field, so when user touches to the decoration box area, the cursor
-     * goes to the beginning or the end of the visible inner text field; otherwise if we put the
-     * cursor under the touch in the invisible part of the inner text field, it would scroll to
-     * make the cursor visible. This behavior is not needed, and therefore
-     * [coerceInVisibleBounds] should be set to false, when the user drags outside visible bounds
-     * to make a selection.
-     */
-    fun getOffsetForPosition(position: Offset, coerceInVisibleBounds: Boolean = true): Int {
-        val relativePosition = position
-            .let { if (coerceInVisibleBounds) it.coercedInVisibleBoundsOfInputText() else it }
-            .relativeToInputText()
-        return value.getOffsetForPosition(relativePosition)
-    }
-
-    fun getLineForVerticalPosition(vertical: Float): Int {
-        val relativeVertical = Offset(0f, vertical)
-            .coercedInVisibleBoundsOfInputText()
-            .relativeToInputText().y
-        return value.getLineForVerticalPosition(relativeVertical)
-    }
-
-    fun getLineEnd(lineIndex: Int, visibleEnd: Boolean = false): Int =
-        value.getLineEnd(lineIndex, visibleEnd)
-
-    /** Returns true if the screen coordinates position (x,y) corresponds to a character displayed
-     * in the view. Returns false when the position is in the empty space of left/right of text.
-     */
-    fun isPositionOnText(offset: Offset): Boolean {
-        val relativeOffset = offset.coercedInVisibleBoundsOfInputText().relativeToInputText()
-        val line = value.getLineForVerticalPosition(relativeOffset.y)
-        return relativeOffset.x >= value.getLineLeft(line) &&
-            relativeOffset.x <= value.getLineRight(line)
-    }
-
-    // Shift offset
-    /** Measured bounds of the decoration box and inner text field. Together used to
-     * calculate the relative touch offset. Because touches are applied on the decoration box, we
-     * need to translate it to the inner text field coordinates.
-     */
-    var innerTextFieldCoordinates: LayoutCoordinates? = null
-    var decorationBoxCoordinates: LayoutCoordinates? = null
-
-    /**
-     * Translates the click happened on the decoration box to the position in the inner text
-     * field coordinates. This relative position is then used to determine symbol position in
-     * text using TextLayoutResult object.
-     */
-    private fun Offset.relativeToInputText(): Offset {
-        // Translates touch to the inner text field coordinates
-        return innerTextFieldCoordinates?.let { innerTextFieldCoordinates ->
-            decorationBoxCoordinates?.let { decorationBoxCoordinates ->
-                if (innerTextFieldCoordinates.isAttached && decorationBoxCoordinates.isAttached) {
-                    innerTextFieldCoordinates.localPositionOf(decorationBoxCoordinates, this)
-                } else {
-                    this
-                }
-            }
-        } ?: this
-    }
-
-    /**
-     * If click on the decoration box happens outside visible inner text field, coerce the click
-     * position to the visible edges of the inner text field.
-     */
-    private fun Offset.coercedInVisibleBoundsOfInputText(): Offset {
-        // If offset is outside visible bounds of the inner text field, use visible bounds edges
-        val visibleInnerTextFieldRect =
-            innerTextFieldCoordinates?.let { innerTextFieldCoordinates ->
-                if (innerTextFieldCoordinates.isAttached) {
-                    decorationBoxCoordinates?.localBoundingBoxOf(innerTextFieldCoordinates)
-                } else {
-                    Rect.Zero
-                }
-            } ?: Rect.Zero
-        return this.coerceIn(visibleInnerTextFieldRect)
-    }
-}
-
-private fun Offset.coerceIn(rect: Rect): Offset {
-    val xOffset = when {
-        x < rect.left -> rect.left
-        x > rect.right -> rect.right
-        else -> x
-    }
-    val yOffset = when {
-        y < rect.top -> rect.top
-        y > rect.bottom -> rect.bottom
-        else -> y
-    }
-    return Offset(xOffset, yOffset)
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/MultiWidgetSelectionDelegate.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/MultiWidgetSelectionDelegate.kt
deleted file mode 100644
index b234d34..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/MultiWidgetSelectionDelegate.kt
+++ /dev/null
@@ -1,255 +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.newtext.text.copypasta.selection
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextRange
-import kotlin.math.max
-
-internal class MultiWidgetSelectionDelegate(
-    override val selectableId: Long,
-    private val coordinatesCallback: () -> LayoutCoordinates?,
-    private val layoutResultCallback: () -> TextLayoutResult?
-) : Selectable {
-
-    override fun updateSelection(
-        startHandlePosition: Offset,
-        endHandlePosition: Offset,
-        previousHandlePosition: Offset?,
-        isStartHandle: Boolean,
-        containerLayoutCoordinates: LayoutCoordinates,
-        adjustment: SelectionAdjustment,
-        previousSelection: Selection?
-    ): Pair<Selection?, Boolean> {
-        require(
-            previousSelection == null || (
-                selectableId == previousSelection.start.selectableId &&
-                    selectableId == previousSelection.end.selectableId
-                )
-        ) {
-            "The given previousSelection doesn't belong to this selectable."
-        }
-        val layoutCoordinates = getLayoutCoordinates() ?: return Pair(null, false)
-        val textLayoutResult = layoutResultCallback() ?: return Pair(null, false)
-
-        val relativePosition = containerLayoutCoordinates.localPositionOf(
-            layoutCoordinates, Offset.Zero
-        )
-        val localStartPosition = startHandlePosition - relativePosition
-        val localEndPosition = endHandlePosition - relativePosition
-        val localPreviousHandlePosition = previousHandlePosition?.let { it - relativePosition }
-
-        return getTextSelectionInfo(
-            textLayoutResult = textLayoutResult,
-            startHandlePosition = localStartPosition,
-            endHandlePosition = localEndPosition,
-            previousHandlePosition = localPreviousHandlePosition,
-            selectableId = selectableId,
-            adjustment = adjustment,
-            previousSelection = previousSelection,
-            isStartHandle = isStartHandle
-        )
-    }
-
-    override fun getSelectAllSelection(): Selection? {
-        val textLayoutResult = layoutResultCallback() ?: return null
-        val newSelectionRange = TextRange(0, textLayoutResult.layoutInput.text.length)
-
-        return getAssembledSelectionInfo(
-            newSelectionRange = newSelectionRange,
-            handlesCrossed = false,
-            selectableId = selectableId,
-            textLayoutResult = textLayoutResult
-        )
-    }
-
-    override fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset {
-        // Check if the selection handle's selectable is the current selectable.
-        if (isStartHandle && selection.start.selectableId != this.selectableId ||
-            !isStartHandle && selection.end.selectableId != this.selectableId
-        ) {
-            return Offset.Zero
-        }
-
-        if (getLayoutCoordinates() == null) return Offset.Zero
-
-        val textLayoutResult = layoutResultCallback() ?: return Offset.Zero
-        return getSelectionHandleCoordinates(
-            textLayoutResult = textLayoutResult,
-            offset = if (isStartHandle) selection.start.offset else selection.end.offset,
-            isStart = isStartHandle,
-            areHandlesCrossed = selection.handlesCrossed
-        )
-    }
-
-    override fun getLayoutCoordinates(): LayoutCoordinates? {
-        val layoutCoordinates = coordinatesCallback()
-        if (layoutCoordinates == null || !layoutCoordinates.isAttached) return null
-        return layoutCoordinates
-    }
-
-    override fun getText(): AnnotatedString {
-        val textLayoutResult = layoutResultCallback() ?: return AnnotatedString("")
-        return textLayoutResult.layoutInput.text
-    }
-
-    override fun getBoundingBox(offset: Int): Rect {
-        val textLayoutResult = layoutResultCallback() ?: return Rect.Zero
-        val textLength = textLayoutResult.layoutInput.text.length
-        if (textLength < 1) return Rect.Zero
-        return textLayoutResult.getBoundingBox(
-            offset.coerceIn(0, textLength - 1)
-        )
-    }
-
-    override fun getRangeOfLineContaining(offset: Int): TextRange {
-        val textLayoutResult = layoutResultCallback() ?: return TextRange.Zero
-        val textLength = textLayoutResult.layoutInput.text.length
-        if (textLength < 1) return TextRange.Zero
-        val line = textLayoutResult.getLineForOffset(offset.coerceIn(0, textLength - 1))
-        return TextRange(
-            start = textLayoutResult.getLineStart(line),
-            end = textLayoutResult.getLineEnd(line, visibleEnd = true)
-        )
-    }
-}
-
-/**
- * Return information about the current selection in the Text.
- *
- * @param textLayoutResult a result of the text layout.
- * @param startHandlePosition The new positions of the moving selection handle.
- * @param previousHandlePosition The old position of the moving selection handle since the last update.
- * @param endHandlePosition the position of the selection handle that is not moving.
- * @param selectableId the id of this [Selectable].
- * @param adjustment the [SelectionAdjustment] used to process the raw selection range.
- * @param previousSelection the previous text selection.
- * @param isStartHandle whether the moving selection is the start selection handle.
- *
- * @return a pair consistent of updated [Selection] and a boolean representing whether the
- * movement is consumed.
- */
-internal fun getTextSelectionInfo(
-    textLayoutResult: TextLayoutResult,
-    startHandlePosition: Offset,
-    endHandlePosition: Offset,
-    previousHandlePosition: Offset?,
-    selectableId: Long,
-    adjustment: SelectionAdjustment,
-    previousSelection: Selection? = null,
-    isStartHandle: Boolean = true
-): Pair<Selection?, Boolean> {
-
-    val bounds = Rect(
-        0.0f,
-        0.0f,
-        textLayoutResult.size.width.toFloat(),
-        textLayoutResult.size.height.toFloat()
-    )
-
-    val isSelected =
-        SelectionMode.Vertical.isSelected(bounds, startHandlePosition, endHandlePosition)
-
-    if (!isSelected) {
-        return Pair(null, false)
-    }
-
-    val rawStartHandleOffset = getOffsetForPosition(textLayoutResult, bounds, startHandlePosition)
-    val rawEndHandleOffset = getOffsetForPosition(textLayoutResult, bounds, endHandlePosition)
-    val rawPreviousHandleOffset = previousHandlePosition?.let {
-        getOffsetForPosition(textLayoutResult, bounds, it)
-    } ?: -1
-
-    val adjustedTextRange = adjustment.adjust(
-        textLayoutResult = textLayoutResult,
-        newRawSelectionRange = TextRange(rawStartHandleOffset, rawEndHandleOffset),
-        previousHandleOffset = rawPreviousHandleOffset,
-        isStartHandle = isStartHandle,
-        previousSelectionRange = previousSelection?.toTextRange()
-    )
-    val newSelection = getAssembledSelectionInfo(
-        newSelectionRange = adjustedTextRange,
-        handlesCrossed = adjustedTextRange.reversed,
-        selectableId = selectableId,
-        textLayoutResult = textLayoutResult
-    )
-
-    // Determine whether the movement is consumed by this Selectable.
-    // If the selection has  changed, the movement is consumed.
-    // And there are also cases where the selection stays the same but selection handle raw
-    // offset has changed.(Usually this happen because of adjustment like SelectionAdjustment.Word)
-    // In this case we also consider the movement being consumed.
-    val selectionUpdated = newSelection != previousSelection
-    val handleUpdated = if (isStartHandle) {
-        rawStartHandleOffset != rawPreviousHandleOffset
-    } else {
-        rawEndHandleOffset != rawPreviousHandleOffset
-    }
-    val consumed = handleUpdated || selectionUpdated
-    return Pair(newSelection, consumed)
-}
-
-internal fun getOffsetForPosition(
-    textLayoutResult: TextLayoutResult,
-    bounds: Rect,
-    position: Offset
-): Int {
-    val length = textLayoutResult.layoutInput.text.length
-    return if (bounds.contains(position)) {
-        textLayoutResult.getOffsetForPosition(position).coerceIn(0, length)
-    } else {
-        val value = SelectionMode.Vertical.compare(position, bounds)
-        if (value < 0) 0 else length
-    }
-}
-
-/**
- * [Selection] contains a lot of parameters. It looks more clean to assemble an object of this
- * class in a separate method.
- *
- * @param newSelectionRange the final new selection text range.
- * @param handlesCrossed true if the selection handles are crossed
- * @param selectableId the id of the current [Selectable] for which the [Selection] is being
- * calculated
- * @param textLayoutResult a result of the text layout.
- *
- * @return an assembled object of [Selection] using the offered selection info.
- */
-private fun getAssembledSelectionInfo(
-    newSelectionRange: TextRange,
-    handlesCrossed: Boolean,
-    selectableId: Long,
-    textLayoutResult: TextLayoutResult
-): Selection {
-    return Selection(
-        start = Selection.AnchorInfo(
-            direction = textLayoutResult.getBidiRunDirection(newSelectionRange.start),
-            offset = newSelectionRange.start,
-            selectableId = selectableId
-        ),
-        end = Selection.AnchorInfo(
-            direction = textLayoutResult.getBidiRunDirection(max(newSelectionRange.end - 1, 0)),
-            offset = newSelectionRange.end,
-            selectableId = selectableId
-        ),
-        handlesCrossed = handlesCrossed
-    )
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selectable.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selectable.kt
deleted file mode 100644
index c921a2d..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selectable.kt
+++ /dev/null
@@ -1,122 +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.newtext.text.copypasta.selection
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.TextRange
-
-/**
- * Provides [Selection] information for a composable to SelectionContainer. Composables who can
- * be selected should subscribe to [SelectionRegistrar] using this interface.
- */
-
-internal interface Selectable {
-    /**
-     * An ID used by [SelectionRegistrar] to identify this [Selectable]. This value should not be
-     * [SelectionRegistrar.InvalidSelectableId].
-     * When a [Selectable] is created, it can request an ID from [SelectionRegistrar] by
-     * calling [SelectionRegistrar.nextSelectableId].
-     * @see SelectionRegistrar.nextSelectableId
-     */
-    val selectableId: Long
-
-    /**
-     * Updates the [Selection] information after a selection handle being moved. This method is
-     * expected to be called consecutively during the selection handle position update.
-     *
-     * @param startHandlePosition graphical position of the start selection handle
-     * @param endHandlePosition graphical position of the end selection handle
-     * @param previousHandlePosition the previous position of the moving selection handle
-     * @param containerLayoutCoordinates [LayoutCoordinates] of the composable
-     * @param adjustment [Selection] range is adjusted according to this param
-     * @param previousSelection previous selection result on this [Selectable]
-     * @param isStartHandle whether the moving selection handle is the start selection handle
-     *
-     * @throws IllegalStateException when the given [previousSelection] doesn't belong to this
-     * selectable. In other words, one of the [Selection.AnchorInfo] in the given
-     * [previousSelection] has a selectableId that doesn't match to the [selectableId] of this
-     * selectable.
-     * @return a pair consisting of the updated [Selection] and a boolean value representing
-     * whether the movement is consumed.
-     */
-    fun updateSelection(
-        startHandlePosition: Offset,
-        endHandlePosition: Offset,
-        previousHandlePosition: Offset?,
-        isStartHandle: Boolean = true,
-        containerLayoutCoordinates: LayoutCoordinates,
-        adjustment: SelectionAdjustment,
-        previousSelection: Selection? = null
-    ): Pair<Selection?, Boolean>
-
-    /**
-     * Returns selectAll [Selection] information for a selectable composable. If no selection can be
-     * provided null should be returned.
-     *
-     * @return selectAll [Selection] information for a selectable composable. If no selection can be
-     * provided null should be returned.
-     */
-    fun getSelectAllSelection(): Selection?
-
-    /**
-     * Return the [Offset] of a [SelectionHandle].
-     *
-     * @param selection [Selection] contains the [SelectionHandle]
-     * @param isStartHandle true if it's the start handle, false if it's the end handle.
-     *
-     * @return [Offset] of this handle, based on which the [SelectionHandle] will be drawn.
-     */
-    fun getHandlePosition(selection: Selection, isStartHandle: Boolean): Offset
-
-    /**
-     * Return the [LayoutCoordinates] of the [Selectable].
-     *
-     * @return [LayoutCoordinates] of the [Selectable]. This could be null if called before
-     * composing.
-     */
-    fun getLayoutCoordinates(): LayoutCoordinates?
-
-    /**
-     * Return the [AnnotatedString] of the [Selectable].
-     *
-     * @return text content as [AnnotatedString] of the [Selectable].
-     */
-    fun getText(): AnnotatedString
-
-    /**
-     * Return the bounding box of the character for given character offset. This is currently for
-     * text.
-     * In future when we implemented other selectable Composables, we can return the bounding box of
-     * the wanted rectangle. For example, for an image selectable, this should return the
-     * bounding box of the image.
-     *
-     * @param offset a character offset
-     * @return the bounding box for the character in [Rect], or [Rect.Zero] if the selectable is
-     * empty.
-     */
-    fun getBoundingBox(offset: Int): Rect
-
-    /**
-     * Return the offsets of the start and end of the line containing [offset], or [TextRange.Zero]
-     * if the selectable is empty. These offsets are in the same "coordinate space" as
-     * [getBoundingBox], and despite being returned in a [TextRange], may not refer to offsets in
-     * actual text if the selectable contains other types of content.
-     */
-    fun getRangeOfLineContaining(offset: Int): TextRange
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selection.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selection.kt
deleted file mode 100644
index 5cedac2..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/Selection.kt
+++ /dev/null
@@ -1,89 +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.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.Immutable
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.style.ResolvedTextDirection
-
-/**
- * Information about the current Selection.
- */
-@Immutable
-internal data class Selection(
-    /**
-     * Information about the start of the selection.
-     */
-    val start: AnchorInfo,
-
-    /**
-     * Information about the end of the selection.
-     */
-    val end: AnchorInfo,
-    /**
-     * The flag to show that the selection handles are dragged across each other. After selection
-     * is initialized, if user drags one handle to cross the other handle, this is true, otherwise
-     * it's false.
-     */
-    // If selection happens in single widget, checking [TextRange.start] > [TextRange.end] is
-    // enough.
-    // But when selection happens across multiple widgets, this value needs more complicated
-    // calculation. To avoid repeated calculation, making it as a flag is cheaper.
-    val handlesCrossed: Boolean = false
-) {
-    /**
-     * Contains information about an anchor (start/end) of selection.
-     */
-    @Immutable
-    internal data class AnchorInfo(
-        /**
-         * Text direction of the character in selection edge.
-         */
-        val direction: ResolvedTextDirection,
-
-        /**
-         * Character offset for the selection edge. This offset is within individual child text
-         * composable.
-         */
-        val offset: Int,
-
-        /**
-         * The id of the [Selectable] which contains this [Selection] Anchor.
-         */
-        val selectableId: Long
-    )
-
-    fun merge(other: Selection?): Selection {
-        if (other == null) return this
-
-        var selection = this
-        selection = if (handlesCrossed) {
-            selection.copy(start = other.start)
-        } else {
-            selection.copy(end = other.end)
-        }
-
-        return selection
-    }
-
-    /**
-     * Returns the selection offset information as a [TextRange]
-     */
-    fun toTextRange(): TextRange {
-        return TextRange(start.offset, end.offset)
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionAdjustment.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionAdjustment.kt
deleted file mode 100644
index c53cf0a..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionAdjustment.kt
+++ /dev/null
@@ -1,466 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.newtext.text.copypasta.getParagraphBoundary
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextRange
-
-/**
- * Selection can be adjusted depends on context. For example, in touch mode dragging after a long
- * press adjusts selection by word. But selection by dragging handles is character precise
- * without adjustments. With a mouse, double-click selects by words and triple-clicks by paragraph.
- * @see [SelectionRegistrar.notifySelectionUpdate]
- */
-internal interface SelectionAdjustment {
-
-    /**
-     * The callback function that is called once a new selection arrives, the return value of
-     * this function will be the final selection range on the corresponding [Selectable].
-     *
-     * @param textLayoutResult the [TextLayoutResult] of the involved [Selectable].
-     * @param newRawSelectionRange the new selection range computed from the selection handle
-     * position on screen.
-     * @param previousHandleOffset the previous offset of the moving handle. When isStartHandle is
-     * true, it's the previous offset of the start handle before the movement, and vice versa.
-     * When there isn't a valid previousHandleOffset, previousHandleOffset should be -1.
-     * @param isStartHandle whether the moving handle is the start handle.
-     * @param previousSelectionRange the previous selection range, or the selection range to be
-     * updated.
-     */
-    fun adjust(
-        textLayoutResult: TextLayoutResult,
-        newRawSelectionRange: TextRange,
-        previousHandleOffset: Int,
-        isStartHandle: Boolean,
-        previousSelectionRange: TextRange?
-    ): TextRange
-
-    companion object {
-        /**
-         * The selection adjustment that does nothing and directly return the input raw
-         * selection range.
-         */
-        val None = object : SelectionAdjustment {
-            override fun adjust(
-                textLayoutResult: TextLayoutResult,
-                newRawSelectionRange: TextRange,
-                previousHandleOffset: Int,
-                isStartHandle: Boolean,
-                previousSelectionRange: TextRange?
-            ): TextRange = newRawSelectionRange
-        }
-
-        /**
-         * The character based selection. It normally won't change the raw selection range except
-         * when the input raw selection range is collapsed. In this case, it will always make
-         * sure at least one character is selected.
-         * When the given raw selection range is collapsed:
-         * a) it will always try to adjust the changing selection boundary(base on the value of
-         * isStartHandle) and makes sure the other boundary remains the same after the adjustment
-         * b) if the previous selection range is reversed, it will try to make the adjusted
-         * selection range reversed as well, and vice versa.
-         */
-        val Character = object : SelectionAdjustment {
-            override fun adjust(
-                textLayoutResult: TextLayoutResult,
-                newRawSelectionRange: TextRange,
-                previousHandleOffset: Int,
-                isStartHandle: Boolean,
-                previousSelectionRange: TextRange?
-            ): TextRange {
-                return if (newRawSelectionRange.collapsed) {
-                    // If there isn't any selection before, we assume handles are not crossed.
-                    val previousHandlesCrossed = previousSelectionRange?.reversed ?: false
-                    ensureAtLeastOneChar(
-                        offset = newRawSelectionRange.start,
-                        lastOffset = textLayoutResult.layoutInput.text.lastIndex,
-                        isStartHandle = isStartHandle,
-                        previousHandlesCrossed = previousHandlesCrossed
-                    )
-                } else {
-                    newRawSelectionRange
-                }
-            }
-        }
-
-        /**
-         * The word based selection adjustment. It will adjust the raw input selection such that
-         * the selection boundary snap to the word boundary. It will always expand the raw input
-         * selection range to the closest word boundary. If the raw selection is reversed, it
-         * will always return a reversed selection, and vice versa.
-         */
-        val Word = object : SelectionAdjustment {
-            override fun adjust(
-                textLayoutResult: TextLayoutResult,
-                newRawSelectionRange: TextRange,
-                previousHandleOffset: Int,
-                isStartHandle: Boolean,
-                previousSelectionRange: TextRange?
-            ): TextRange {
-                return adjustByBoundary(
-                    textLayoutResult = textLayoutResult,
-                    newRawSelection = newRawSelectionRange,
-                    boundaryFun = textLayoutResult::getWordBoundary
-                )
-            }
-        }
-
-        /**
-         * The paragraph based selection adjustment. It will adjust the raw input selection such
-         * that the selection boundary snap to the paragraph boundary. It will always expand the
-         * raw input selection range to the closest paragraph boundary. If the raw selection is
-         * reversed, it will always return a reversed selection, and vice versa.
-         */
-        val Paragraph = object : SelectionAdjustment {
-            override fun adjust(
-                textLayoutResult: TextLayoutResult,
-                newRawSelectionRange: TextRange,
-                previousHandleOffset: Int,
-                isStartHandle: Boolean,
-                previousSelectionRange: TextRange?
-            ): TextRange {
-                val boundaryFun = textLayoutResult.layoutInput.text::getParagraphBoundary
-                return adjustByBoundary(
-                    textLayoutResult = textLayoutResult,
-                    newRawSelection = newRawSelectionRange,
-                    boundaryFun = boundaryFun
-                )
-            }
-        }
-
-        private fun adjustByBoundary(
-            textLayoutResult: TextLayoutResult,
-            newRawSelection: TextRange,
-            boundaryFun: (Int) -> TextRange
-        ): TextRange {
-            if (textLayoutResult.layoutInput.text.isEmpty()) {
-                return TextRange.Zero
-            }
-            val maxOffset = textLayoutResult.layoutInput.text.lastIndex
-            val startBoundary = boundaryFun(newRawSelection.start.coerceIn(0, maxOffset))
-            val endBoundary = boundaryFun(newRawSelection.end.coerceIn(0, maxOffset))
-
-            // If handles are not crossed, start should be snapped to the start of the word
-            // containing the start offset, and end should be snapped to the end of the word
-            // containing the end offset. If handles are crossed, start should be snapped to the
-            // end of the word containing the start offset, and end should be snapped to the start
-            // of the word containing the end offset.
-            val start = if (newRawSelection.reversed) startBoundary.end else startBoundary.start
-            val end = if (newRawSelection.reversed) endBoundary.start else endBoundary.end
-            return TextRange(start, end)
-        }
-
-        /**
-         * A special version of character based selection that accelerates the selection update
-         * with word based selection. In short, it expands by word and shrinks by character.
-         * Here is more details of the behavior:
-         * 1. When previous selection is null, it will use word based selection.
-         * 2. When the start/end offset has moved to a different line, it will use word
-         * based selection.
-         * 3. When the selection is shrinking, it behave same as the character based selection.
-         * Shrinking means that the start/end offset is moving in the direction that makes
-         * selected text shorter.
-         * 4. The selection boundary is expanding,
-         *  a.if the previous start/end offset is not a word boundary, use character based
-         * selection.
-         *  b.if the previous start/end offset is a word boundary, use word based selection.
-         *
-         *  Notice that this selection adjustment assumes that when isStartHandle is true, only
-         *  start handle is moving(or unchanged), and vice versa.
-         */
-        val CharacterWithWordAccelerate = object : SelectionAdjustment {
-            override fun adjust(
-                textLayoutResult: TextLayoutResult,
-                newRawSelectionRange: TextRange,
-                previousHandleOffset: Int,
-                isStartHandle: Boolean,
-                previousSelectionRange: TextRange?
-            ): TextRange {
-                // Previous selection is null. We start a word based selection.
-                if (previousSelectionRange == null) {
-                    return Word.adjust(
-                        textLayoutResult = textLayoutResult,
-                        newRawSelectionRange = newRawSelectionRange,
-                        previousHandleOffset = previousHandleOffset,
-                        isStartHandle = isStartHandle,
-                        previousSelectionRange = previousSelectionRange
-                    )
-                }
-
-                // The new selection is collapsed, ensure at least one char is selected.
-                if (newRawSelectionRange.collapsed) {
-                    return ensureAtLeastOneChar(
-                        offset = newRawSelectionRange.start,
-                        lastOffset = textLayoutResult.layoutInput.text.lastIndex,
-                        isStartHandle = isStartHandle,
-                        previousHandlesCrossed = previousSelectionRange.reversed
-                    )
-                }
-
-                val start: Int
-                val end: Int
-                if (isStartHandle) {
-                    start = updateSelectionBoundary(
-                        textLayoutResult = textLayoutResult,
-                        newRawOffset = newRawSelectionRange.start,
-                        previousRawOffset = previousHandleOffset,
-                        previousAdjustedOffset = previousSelectionRange.start,
-                        otherBoundaryOffset = newRawSelectionRange.end,
-                        isStart = true,
-                        isReversed = newRawSelectionRange.reversed
-                    )
-                    end = newRawSelectionRange.end
-                } else {
-                    start = newRawSelectionRange.start
-                    end = updateSelectionBoundary(
-                        textLayoutResult = textLayoutResult,
-                        newRawOffset = newRawSelectionRange.end,
-                        previousRawOffset = previousHandleOffset,
-                        previousAdjustedOffset = previousSelectionRange.end,
-                        otherBoundaryOffset = newRawSelectionRange.start,
-                        isStart = false,
-                        isReversed = newRawSelectionRange.reversed
-                    )
-                }
-                return TextRange(start, end)
-            }
-
-            /**
-             * Helper function that updates start or end boundary of the selection. It implements
-             * the "expand by word and shrink by character behavior".
-             *
-             * @param textLayoutResult the text layout result
-             * @param newRawOffset the new raw offset of the selection boundary after the movement.
-             * @param previousRawOffset the raw offset of the updated selection boundary before the
-             * movement. In the case where previousRawOffset invalid(when selection update is
-             * triggered by long-press or click) pass -1 for this parameter.
-             * @param previousAdjustedOffset the previous final/adjusted offset. It's the current
-             * @param otherBoundaryOffset the offset of the other selection boundary. It is used
-             * to avoid empty selection in word based selection mode.
-             * selection boundary.
-             * @param isStart whether it's updating the selection start or end boundary.
-             * @param isReversed whether the selection is reversed or not. We use
-             * this information to determine if the selection is expanding or shrinking.
-             */
-            private fun updateSelectionBoundary(
-                textLayoutResult: TextLayoutResult,
-                newRawOffset: Int,
-                previousRawOffset: Int,
-                previousAdjustedOffset: Int,
-                otherBoundaryOffset: Int,
-                isStart: Boolean,
-                isReversed: Boolean
-            ): Int {
-                // The raw offset didn't change, directly return the previous adjusted start offset.
-                if (newRawOffset == previousRawOffset) {
-                    return previousAdjustedOffset
-                }
-
-                val currentLine = textLayoutResult.getLineForOffset(newRawOffset)
-                val previousLine = textLayoutResult.getLineForOffset(previousAdjustedOffset)
-
-                // The updating selection boundary has crossed a line, use word based selection.
-                if (currentLine != previousLine) {
-                    return snapToWordBoundary(
-                        textLayoutResult = textLayoutResult,
-                        newRawOffset = newRawOffset,
-                        currentLine = currentLine,
-                        otherBoundaryOffset = otherBoundaryOffset,
-                        isStart = isStart,
-                        isReversed = isReversed
-                    )
-                }
-
-                // Check if the start or end selection boundary is expanding. If it's shrinking,
-                // use character based selection.
-                val isExpanding =
-                    isExpanding(newRawOffset, previousRawOffset, isStart, isReversed)
-                if (!isExpanding) {
-                    return newRawOffset
-                }
-
-                // If the previous start/end offset is not at a word boundary, which is indicating
-                // that start/end offset is updating within a word. In this case, it still uses
-                // character based selection.
-                if (!textLayoutResult.isAtWordBoundary(previousAdjustedOffset)) {
-                    return newRawOffset
-                }
-
-                // At this point we know, the updating start/end offset is still in the same line,
-                // it's expanding the selection, and it's not updating within a word. It should
-                // use word based selection.
-                return snapToWordBoundary(
-                    textLayoutResult = textLayoutResult,
-                    newRawOffset = newRawOffset,
-                    currentLine = currentLine,
-                    otherBoundaryOffset = otherBoundaryOffset,
-                    isStart = isStart,
-                    isReversed = isReversed
-                )
-            }
-
-            private fun snapToWordBoundary(
-                textLayoutResult: TextLayoutResult,
-                newRawOffset: Int,
-                currentLine: Int,
-                otherBoundaryOffset: Int,
-                isStart: Boolean,
-                isReversed: Boolean
-            ): Int {
-                val wordBoundary = textLayoutResult.getWordBoundary(newRawOffset)
-
-                // In the case where the target word crosses multiple lines due to hyphenation or
-                // being too long, we use the line start/end to keep the adjusted offset at the
-                // same line.
-                val wordStartLine = textLayoutResult.getLineForOffset(wordBoundary.start)
-                val start = if (wordStartLine == currentLine) {
-                    wordBoundary.start
-                } else {
-                    textLayoutResult.getLineStart(currentLine)
-                }
-
-                val wordEndLine = textLayoutResult.getLineForOffset(wordBoundary.end)
-                val end = if (wordEndLine == currentLine) {
-                    wordBoundary.end
-                } else {
-                    textLayoutResult.getLineEnd(currentLine)
-                }
-
-                // If one of the word boundary is exactly same as the otherBoundaryOffset, we
-                // can't snap to this word boundary since it will result in an empty selection
-                // range.
-                if (start == otherBoundaryOffset) {
-                    return end
-                }
-                if (end == otherBoundaryOffset) {
-                    return start
-                }
-
-                val threshold = (start + end) / 2
-                return if (isStart xor isReversed) {
-                    // In this branch when:
-                    // 1. selection is updating the start offset, and selection is not reversed.
-                    // 2. selection is updating the end offset, and selection is reversed.
-                    if (newRawOffset <= threshold) {
-                        start
-                    } else {
-                        end
-                    }
-                } else {
-                    // In this branch when:
-                    // 1. selection is updating the end offset, and selection is not reversed.
-                    // 2. selection is updating the start offset, and selection is reversed.
-                    if (newRawOffset >= threshold) {
-                        end
-                    } else {
-                        start
-                    }
-                }
-            }
-
-            private fun TextLayoutResult.isAtWordBoundary(offset: Int): Boolean {
-                val wordBoundary = getWordBoundary(offset)
-                return offset == wordBoundary.start || offset == wordBoundary.end
-            }
-
-            private fun isExpanding(
-                newRawOffset: Int,
-                previousRawOffset: Int,
-                isStart: Boolean,
-                previousReversed: Boolean
-            ): Boolean {
-                // -1 is considered as no previous offset, so the selection is expanding.
-                if (previousRawOffset == -1) {
-                    return true
-                }
-                if (newRawOffset == previousRawOffset) {
-                    return false
-                }
-                return if (isStart xor previousReversed) {
-                    newRawOffset < previousRawOffset
-                } else {
-                    newRawOffset > previousRawOffset
-                }
-            }
-        }
-    }
-}
-
-/**
- * This method adjusts the raw start and end offset and bounds the selection to one character. The
- * logic of bounding evaluates the last selection result, which handle is being dragged, and if
- * selection reaches the boundary.
- *
- * @param offset unprocessed start and end offset calculated directly from input position, in
- * this case start and offset equals to each other.
- * @param lastOffset last offset of the text. It's actually the length of the text.
- * @param isStartHandle true if the start handle is being dragged
- * @param previousHandlesCrossed true if the selection handles are crossed in the previous
- * selection. This function will try to maintain the handle cross state. This can help make
- * selection stable.
- *
- * @return the adjusted [TextRange].
- */
-internal fun ensureAtLeastOneChar(
-    offset: Int,
-    lastOffset: Int,
-    isStartHandle: Boolean,
-    previousHandlesCrossed: Boolean
-): TextRange {
-    // When lastOffset is 0, it can only return an empty TextRange.
-    // When previousSelection is null, it won't start a selection and return an empty TextRange.
-    if (lastOffset == 0) return TextRange(offset, offset)
-
-    // When offset is at the boundary, the handle that is not dragged should be at [offset]. Here
-    // the other handle's position is computed accordingly.
-    if (offset == 0) {
-        return if (isStartHandle) {
-            TextRange(1, 0)
-        } else {
-            TextRange(0, 1)
-        }
-    }
-
-    if (offset == lastOffset) {
-        return if (isStartHandle) {
-            TextRange(lastOffset - 1, lastOffset)
-        } else {
-            TextRange(lastOffset, lastOffset - 1)
-        }
-    }
-
-    // In other cases, this function will try to maintain the current cross handle states.
-    // Only in this way the selection can be stable.
-    return if (isStartHandle) {
-        if (!previousHandlesCrossed) {
-            // Handle is NOT crossed, and the start handle is dragged.
-            TextRange(offset - 1, offset)
-        } else {
-            // Handle is crossed, and the start handle is dragged.
-            TextRange(offset + 1, offset)
-        }
-    } else {
-        if (!previousHandlesCrossed) {
-            // Handle is NOT crossed, and the end handle is dragged.
-            TextRange(offset, offset + 1)
-        } else {
-            // Handle is crossed, and the end handle is dragged.
-            TextRange(offset, offset - 1)
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionContainer.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionContainer.kt
deleted file mode 100644
index 82d53aa..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionContainer.kt
+++ /dev/null
@@ -1,143 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.newtext.text.copypasta.ContextMenuArea
-import androidx.compose.foundation.newtext.text.copypasta.detectDownAndDragGesturesWithObserver
-import androidx.compose.foundation.newtext.text.copypasta.isInTouchMode
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
-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.input.pointer.pointerInput
-import androidx.compose.ui.platform.LocalClipboardManager
-import androidx.compose.ui.platform.LocalHapticFeedback
-import androidx.compose.ui.platform.LocalTextToolbar
-import androidx.compose.ui.util.fastForEach
-
-/**
- * Enables text selection for its direct or indirect children.
- *
- * @sample androidx.compose.foundation.samples.SelectionSample
- */
-@Composable
-fun SelectionContainer(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
-    var selection by remember { mutableStateOf<Selection?>(null) }
-    SelectionContainer(
-        modifier = modifier,
-        selection = selection,
-        onSelectionChange = {
-            selection = it
-        },
-        children = content
-    )
-}
-
-/**
- * Disables text selection for its direct or indirect children. To use this, simply add this
- * to wrap one or more text composables.
- *
- * @sample androidx.compose.foundation.samples.DisableSelectionSample
- */
-@Composable
-fun DisableSelection(content: @Composable () -> Unit) {
-    CompositionLocalProvider(
-        LocalSelectionRegistrar provides null,
-        content = content
-    )
-}
-
-/**
- * Selection Composable.
- *
- * The selection composable wraps composables and let them to be selectable. It paints the selection
- * area with start and end handles.
- */
-@Suppress("ComposableLambdaParameterNaming")
-@Composable
-internal fun SelectionContainer(
-    /** A [Modifier] for SelectionContainer. */
-    modifier: Modifier = Modifier,
-    /** Current Selection status.*/
-    selection: Selection?,
-    /** A function containing customized behaviour when selection changes. */
-    onSelectionChange: (Selection?) -> Unit,
-    children: @Composable () -> Unit
-) {
-    val registrarImpl = remember { SelectionRegistrarImpl() }
-    val manager = remember { SelectionManager(registrarImpl) }
-
-    manager.hapticFeedBack = LocalHapticFeedback.current
-    manager.clipboardManager = LocalClipboardManager.current
-    manager.textToolbar = LocalTextToolbar.current
-    manager.onSelectionChange = onSelectionChange
-    manager.selection = selection
-    manager.touchMode = isInTouchMode
-
-    ContextMenuArea(manager) {
-        CompositionLocalProvider(LocalSelectionRegistrar provides registrarImpl) {
-            // Get the layout coordinates of the selection container. This is for hit test of
-            // cross-composable selection.
-            SimpleLayout(modifier = modifier.then(manager.modifier)) {
-                children()
-                if (isInTouchMode && manager.hasFocus) {
-                    manager.selection?.let {
-                        listOf(true, false).fastForEach { isStartHandle ->
-                            val observer = remember(isStartHandle) {
-                                manager.handleDragObserver(isStartHandle)
-                            }
-                            val position = if (isStartHandle) {
-                                manager.startHandlePosition
-                            } else {
-                                manager.endHandlePosition
-                            }
-
-                            val direction = if (isStartHandle) {
-                                it.start.direction
-                            } else {
-                                it.end.direction
-                            }
-
-                            if (position != null) {
-                                SelectionHandle(
-                                    position = position,
-                                    isStartHandle = isStartHandle,
-                                    direction = direction,
-                                    handlesCrossed = it.handlesCrossed,
-                                    modifier = Modifier.pointerInput(observer) {
-                                        detectDownAndDragGesturesWithObserver(observer)
-                                    },
-                                    content = null
-                                )
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    DisposableEffect(manager) {
-        onDispose {
-            manager.hideSelectionToolbar()
-        }
-    }
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionHandles.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionHandles.kt
deleted file mode 100644
index ddea64a..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionHandles.kt
+++ /dev/null
@@ -1,68 +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.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.semantics.SemanticsPropertyKey
-import androidx.compose.ui.text.style.ResolvedTextDirection
-import androidx.compose.ui.unit.dp
-
-internal val HandleWidth = 25.dp
-internal val HandleHeight = 25.dp
-
-/**
- * [SelectionHandleInfo]s for the nodes representing selection handles. These nodes are in popup
- * windows, and will respond to drag gestures.
- */
-internal val SelectionHandleInfoKey =
-    SemanticsPropertyKey<SelectionHandleInfo>("SelectionHandleInfo")
-
-/**
- * Information about a single selection handle popup.
- *
- * @param position The position that the handle is anchored to relative to the selectable content.
- * This position is not necessarily the position of the popup itself, it's the position that the
- * handle "points" to
- */
-internal data class SelectionHandleInfo(
-    // TODO: This is removed for copypasta because it's never used in basic usage
-    // val handle: Handle,
-    val position: Offset
-)
-
-@Composable
-internal expect fun SelectionHandle(
-    position: Offset,
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean,
-    modifier: Modifier,
-    content: @Composable (() -> Unit)?
-)
-
-/**
- * Adjust coordinates for given text offset.
- *
- * Currently [android.text.Layout.getLineBottom] returns y coordinates of the next
- * line's top offset, which is not included in current line's hit area. To be able to
- * hit current line, move up this y coordinates by 1 pixel.
- */
-internal fun getAdjustedCoordinates(position: Offset): Offset {
-    return Offset(position.x, position.y - 1f)
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMagnifier.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMagnifier.kt
deleted file mode 100644
index 1f7a00c..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMagnifier.kt
+++ /dev/null
@@ -1,109 +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.newtext.text.copypasta.selection
-
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationVector2D
-import androidx.compose.animation.core.Spring
-import androidx.compose.animation.core.SpringSpec
-import androidx.compose.animation.core.TwoWayConverter
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.isSpecified
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.launch
-
-private val UnspecifiedAnimationVector2D = AnimationVector2D(Float.NaN, Float.NaN)
-
-/** Like `Offset.VectorConverter` but propagates [Offset.Unspecified] values. */
-private val UnspecifiedSafeOffsetVectorConverter = TwoWayConverter<Offset, AnimationVector2D>(
-    convertToVector = {
-        if (it.isSpecified) {
-            AnimationVector2D(it.x, it.y)
-        } else {
-            UnspecifiedAnimationVector2D
-        }
-    },
-    convertFromVector = { Offset(it.v1, it.v2) }
-)
-
-private val OffsetDisplacementThreshold = Offset(
-    Spring.DefaultDisplacementThreshold,
-    Spring.DefaultDisplacementThreshold
-)
-
-private val MagnifierSpringSpec = SpringSpec(visibilityThreshold = OffsetDisplacementThreshold)
-
-/**
- * The text magnifier follows horizontal dragging exactly, but is vertically clamped to the current
- * line, so when it changes lines we animate it.
- */
-internal fun Modifier.animatedSelectionMagnifier(
-    magnifierCenter: () -> Offset,
-    platformMagnifier: (animatedCenter: () -> Offset) -> Modifier
-): Modifier = composed {
-    val animatedCenter by rememberAnimatedMagnifierPosition(targetCalculation = magnifierCenter)
-    return@composed platformMagnifier { animatedCenter }
-}
-
-/**
- * Remembers and returns a [State] that will smoothly animate to the result of [targetCalculation]
- * any time the result of [targetCalculation] changes due to any state values it reads change.
- */
-@Composable
-private fun rememberAnimatedMagnifierPosition(
-    targetCalculation: () -> Offset,
-): State<Offset> {
-    val targetValue by remember { derivedStateOf(targetCalculation) }
-    val animatable = remember {
-        // Can't use Offset.VectorConverter because we need to handle Unspecified specially.
-        Animatable(targetValue, UnspecifiedSafeOffsetVectorConverter, OffsetDisplacementThreshold)
-    }
-    LaunchedEffect(Unit) {
-        val animationScope = this
-        snapshotFlow { targetValue }
-            .collect { targetValue ->
-                // Only animate the position when moving vertically (i.e. jumping between lines),
-                // since horizontal movement in a single line should stay as close to the gesture as
-                // possible and animation would only add unnecessary lag.
-                if (
-                    animatable.value.isSpecified &&
-                    targetValue.isSpecified &&
-                    animatable.value.y != targetValue.y
-                ) {
-                    // Launch the animation, instead of cancelling and re-starting manually via
-                    // collectLatest, so if another animation is started before this one finishes,
-                    // the new one will use the correct velocity, e.g. in order to propagate spring
-                    // inertia.
-                    animationScope.launch {
-                        animatable.animateTo(targetValue, MagnifierSpringSpec)
-                    }
-                } else {
-                    animatable.snapTo(targetValue)
-                }
-            }
-    }
-    return animatable.asState()
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.kt
deleted file mode 100644
index 73e0612..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.kt
+++ /dev/null
@@ -1,903 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.focusable
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.waitForUpOrCancellation
-import androidx.compose.foundation.newtext.text.copypasta.TextDragObserver
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.State
-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.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.hapticfeedback.HapticFeedback
-import androidx.compose.ui.hapticfeedback.HapticFeedbackType
-import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.onKeyEvent
-import androidx.compose.ui.input.pointer.PointerInputScope
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.layout.boundsInWindow
-import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.positionInWindow
-import androidx.compose.ui.platform.ClipboardManager
-import androidx.compose.ui.platform.TextToolbar
-import androidx.compose.ui.platform.TextToolbarStatus
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.unit.IntSize
-import kotlin.math.absoluteValue
-import kotlin.math.max
-import kotlin.math.min
-
-/**
- * A bridge class between user interaction to the text composables for text selection.
- */
-internal class SelectionManager(private val selectionRegistrar: SelectionRegistrarImpl) {
-
-    private val _selection: MutableState<Selection?> = mutableStateOf(null)
-
-    /**
-     * The current selection.
-     */
-    var selection: Selection?
-        get() = _selection.value
-        set(value) {
-            _selection.value = value
-            if (value != null) {
-                updateHandleOffsets()
-            }
-        }
-
-    /**
-     * Is touch mode active
-     */
-    var touchMode: Boolean = true
-
-    /**
-     * The manager will invoke this every time it comes to the conclusion that the selection should
-     * change. The expectation is that this callback will end up causing `setSelection` to get
-     * called. This is what makes this a "controlled component".
-     */
-    var onSelectionChange: (Selection?) -> Unit = {}
-
-    /**
-     * [HapticFeedback] handle to perform haptic feedback.
-     */
-    var hapticFeedBack: HapticFeedback? = null
-
-    /**
-     * [ClipboardManager] to perform clipboard features.
-     */
-    var clipboardManager: ClipboardManager? = null
-
-    /**
-     * [TextToolbar] to show floating toolbar(post-M) or primary toolbar(pre-M).
-     */
-    var textToolbar: TextToolbar? = null
-
-    /**
-     * Focus requester used to request focus when selection becomes active.
-     */
-    var focusRequester: FocusRequester = FocusRequester()
-
-    /**
-     * Return true if the corresponding SelectionContainer is focused.
-     */
-    var hasFocus: Boolean by mutableStateOf(false)
-
-    /**
-     * Modifier for selection container.
-     */
-    val modifier
-        get() = Modifier
-            .onClearSelectionRequested { onRelease() }
-            .onGloballyPositioned { containerLayoutCoordinates = it }
-            .focusRequester(focusRequester)
-            .onFocusChanged { focusState ->
-                if (!focusState.isFocused && hasFocus) {
-                    onRelease()
-                }
-                hasFocus = focusState.isFocused
-            }
-            .focusable()
-            .onKeyEvent {
-                if (isCopyKeyEvent(it)) {
-                    copy()
-                    true
-                } else {
-                    false
-                }
-            }
-            .then(if (shouldShowMagnifier) Modifier.selectionMagnifier(this) else Modifier)
-
-    private var previousPosition: Offset? = null
-
-    /**
-     * Layout Coordinates of the selection container.
-     */
-    var containerLayoutCoordinates: LayoutCoordinates? = null
-        set(value) {
-            field = value
-            if (hasFocus && selection != null) {
-                val positionInWindow = value?.positionInWindow()
-                if (previousPosition != positionInWindow) {
-                    previousPosition = positionInWindow
-                    updateHandleOffsets()
-                    updateSelectionToolbarPosition()
-                }
-            }
-        }
-
-    /**
-     * The beginning position of the drag gesture. Every time a new drag gesture starts, it wil be
-     * recalculated.
-     */
-    internal var dragBeginPosition by mutableStateOf(Offset.Zero)
-        private set
-
-    /**
-     * The total distance being dragged of the drag gesture. Every time a new drag gesture starts,
-     * it will be zeroed out.
-     */
-    internal var dragTotalDistance by mutableStateOf(Offset.Zero)
-        private set
-
-    /**
-     * The calculated position of the start handle in the [SelectionContainer] coordinates. It
-     * is null when handle shouldn't be displayed.
-     * It is a [State] so reading it during the composition will cause recomposition every time
-     * the position has been changed.
-     */
-    var startHandlePosition: Offset? by mutableStateOf(null)
-        private set
-
-    /**
-     * The calculated position of the end handle in the [SelectionContainer] coordinates. It
-     * is null when handle shouldn't be displayed.
-     * It is a [State] so reading it during the composition will cause recomposition every time
-     * the position has been changed.
-     */
-    var endHandlePosition: Offset? by mutableStateOf(null)
-        private set
-
-    /**
-     * The handle that is currently being dragged, or null when no handle is being dragged. To get
-     * the position of the last drag event, use [currentDragPosition].
-     */
-    var draggingHandle: Handle? by mutableStateOf(null)
-        private set
-
-    /**
-     * When a handle is being dragged (i.e. [draggingHandle] is non-null), this is the last position
-     * of the actual drag event. It is not clamped to handle positions. Null when not being dragged.
-     */
-    var currentDragPosition: Offset? by mutableStateOf(null)
-        private set
-
-    private val shouldShowMagnifier get() = draggingHandle != null
-
-    init {
-        selectionRegistrar.onPositionChangeCallback = { selectableId ->
-            if (
-                selectableId == selection?.start?.selectableId ||
-                selectableId == selection?.end?.selectableId
-            ) {
-                updateHandleOffsets()
-                updateSelectionToolbarPosition()
-            }
-        }
-
-        selectionRegistrar.onSelectionUpdateStartCallback =
-            { layoutCoordinates, position, selectionMode ->
-                val positionInContainer = convertToContainerCoordinates(
-                    layoutCoordinates,
-                    position
-                )
-
-                if (positionInContainer != null) {
-                    startSelection(
-                        position = positionInContainer,
-                        isStartHandle = false,
-                        adjustment = selectionMode
-                    )
-
-                    focusRequester.requestFocus()
-                    hideSelectionToolbar()
-                }
-            }
-
-        selectionRegistrar.onSelectionUpdateSelectAll =
-            { selectableId ->
-                val (newSelection, newSubselection) = selectAll(
-                    selectableId = selectableId,
-                    previousSelection = selection,
-                )
-                if (newSelection != selection) {
-                    selectionRegistrar.subselections = newSubselection
-                    onSelectionChange(newSelection)
-                }
-
-                focusRequester.requestFocus()
-                hideSelectionToolbar()
-            }
-
-        selectionRegistrar.onSelectionUpdateCallback =
-            { layoutCoordinates, newPosition, previousPosition, isStartHandle, selectionMode ->
-                val newPositionInContainer =
-                    convertToContainerCoordinates(layoutCoordinates, newPosition)
-                val previousPositionInContainer =
-                    convertToContainerCoordinates(layoutCoordinates, previousPosition)
-
-                updateSelection(
-                    newPosition = newPositionInContainer,
-                    previousPosition = previousPositionInContainer,
-                    isStartHandle = isStartHandle,
-                    adjustment = selectionMode
-                )
-            }
-
-        selectionRegistrar.onSelectionUpdateEndCallback = {
-            showSelectionToolbar()
-            // This property is set by updateSelection while dragging, so we need to clear it after
-            // the original selection drag.
-            draggingHandle = null
-            currentDragPosition = null
-        }
-
-        selectionRegistrar.onSelectableChangeCallback = { selectableKey ->
-            if (selectableKey in selectionRegistrar.subselections) {
-                // clear the selection range of each Selectable.
-                onRelease()
-                selection = null
-            }
-        }
-
-        selectionRegistrar.afterSelectableUnsubscribe = { selectableKey ->
-            if (
-                selectableKey == selection?.start?.selectableId ||
-                selectableKey == selection?.end?.selectableId
-            ) {
-                // The selectable that contains a selection handle just unsubscribed.
-                // Hide selection handles for now
-                startHandlePosition = null
-                endHandlePosition = null
-            }
-        }
-    }
-
-    /**
-     * Returns the [Selectable] responsible for managing the given [Selection.AnchorInfo], or null
-     * if the anchor is not from a currently-registered [Selectable].
-     */
-    internal fun getAnchorSelectable(anchor: Selection.AnchorInfo): Selectable? {
-        return selectionRegistrar.selectableMap[anchor.selectableId]
-    }
-
-    private fun updateHandleOffsets() {
-        val selection = selection
-        val containerCoordinates = containerLayoutCoordinates
-        val startSelectable = selection?.start?.let(::getAnchorSelectable)
-        val endSelectable = selection?.end?.let(::getAnchorSelectable)
-        val startLayoutCoordinates = startSelectable?.getLayoutCoordinates()
-        val endLayoutCoordinates = endSelectable?.getLayoutCoordinates()
-        if (
-            selection == null ||
-            containerCoordinates == null ||
-            !containerCoordinates.isAttached ||
-            startLayoutCoordinates == null ||
-            endLayoutCoordinates == null
-        ) {
-            this.startHandlePosition = null
-            this.endHandlePosition = null
-            return
-        }
-
-        val startHandlePosition = containerCoordinates.localPositionOf(
-            startLayoutCoordinates,
-            startSelectable.getHandlePosition(
-                selection = selection,
-                isStartHandle = true
-            )
-        )
-        val endHandlePosition = containerCoordinates.localPositionOf(
-            endLayoutCoordinates,
-            endSelectable.getHandlePosition(
-                selection = selection,
-                isStartHandle = false
-            )
-        )
-
-        val visibleBounds = containerCoordinates.visibleBounds()
-        this.startHandlePosition =
-            if (visibleBounds.containsInclusive(startHandlePosition)) startHandlePosition else null
-        this.endHandlePosition =
-            if (visibleBounds.containsInclusive(endHandlePosition)) endHandlePosition else null
-    }
-
-    /**
-     * Returns non-nullable [containerLayoutCoordinates].
-     */
-    internal fun requireContainerCoordinates(): LayoutCoordinates {
-        val coordinates = containerLayoutCoordinates
-        require(coordinates != null)
-        require(coordinates.isAttached)
-        return coordinates
-    }
-
-    internal fun selectAll(
-        selectableId: Long,
-        previousSelection: Selection?
-    ): Pair<Selection?, Map<Long, Selection>> {
-        val subselections = mutableMapOf<Long, Selection>()
-        val newSelection = selectionRegistrar.sort(requireContainerCoordinates())
-            .fastFold(null) { mergedSelection: Selection?, selectable: Selectable ->
-                val selection = if (selectable.selectableId == selectableId)
-                    selectable.getSelectAllSelection() else null
-                selection?.let { subselections[selectable.selectableId] = it }
-                merge(mergedSelection, selection)
-            }
-        if (newSelection != previousSelection) {
-            hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
-        }
-        return Pair(newSelection, subselections)
-    }
-
-    internal fun getSelectedText(): AnnotatedString? {
-        val selectables = selectionRegistrar.sort(requireContainerCoordinates())
-        var selectedText: AnnotatedString? = null
-
-        selection?.let {
-            for (i in selectables.indices) {
-                val selectable = selectables[i]
-                // Continue if the current selectable is before the selection starts.
-                if (selectable.selectableId != it.start.selectableId &&
-                    selectable.selectableId != it.end.selectableId &&
-                    selectedText == null
-                ) continue
-
-                val currentSelectedText = getCurrentSelectedText(
-                    selectable = selectable,
-                    selection = it
-                )
-                selectedText = selectedText?.plus(currentSelectedText) ?: currentSelectedText
-
-                // Break if the current selectable is the last selected selectable.
-                if (selectable.selectableId == it.end.selectableId && !it.handlesCrossed ||
-                    selectable.selectableId == it.start.selectableId && it.handlesCrossed
-                ) break
-            }
-        }
-        return selectedText
-    }
-
-    internal fun copy() {
-        val selectedText = getSelectedText()
-        selectedText?.let { clipboardManager?.setText(it) }
-    }
-
-    /**
-     * This function get the selected region as a Rectangle region, and pass it to [TextToolbar]
-     * to make the FloatingToolbar show up in the proper place. In addition, this function passes
-     * the copy method as a callback when "copy" is clicked.
-     */
-    internal fun showSelectionToolbar() {
-        if (hasFocus) {
-            selection?.let {
-                textToolbar?.showMenu(
-                    getContentRect(),
-                    onCopyRequested = {
-                        copy()
-                        onRelease()
-                    }
-                )
-            }
-        }
-    }
-
-    internal fun hideSelectionToolbar() {
-        if (hasFocus && textToolbar?.status == TextToolbarStatus.Shown) {
-            textToolbar?.hide()
-        }
-    }
-
-    private fun updateSelectionToolbarPosition() {
-        if (hasFocus && textToolbar?.status == TextToolbarStatus.Shown) {
-            showSelectionToolbar()
-        }
-    }
-
-    /**
-     * Calculate selected region as [Rect]. The top is the top of the first selected
-     * line, and the bottom is the bottom of the last selected line. The left is the leftmost
-     * handle's horizontal coordinates, and the right is the rightmost handle's coordinates.
-     */
-    private fun getContentRect(): Rect {
-        val selection = selection ?: return Rect.Zero
-        val startSelectable = getAnchorSelectable(selection.start)
-        val endSelectable = getAnchorSelectable(selection.end)
-        val startLayoutCoordinates = startSelectable?.getLayoutCoordinates() ?: return Rect.Zero
-        val endLayoutCoordinates = endSelectable?.getLayoutCoordinates() ?: return Rect.Zero
-
-        val localLayoutCoordinates = containerLayoutCoordinates
-        if (localLayoutCoordinates != null && localLayoutCoordinates.isAttached) {
-            var startOffset = localLayoutCoordinates.localPositionOf(
-                startLayoutCoordinates,
-                startSelectable.getHandlePosition(
-                    selection = selection,
-                    isStartHandle = true
-                )
-            )
-            var endOffset = localLayoutCoordinates.localPositionOf(
-                endLayoutCoordinates,
-                endSelectable.getHandlePosition(
-                    selection = selection,
-                    isStartHandle = false
-                )
-            )
-
-            startOffset = localLayoutCoordinates.localToRoot(startOffset)
-            endOffset = localLayoutCoordinates.localToRoot(endOffset)
-
-            val left = min(startOffset.x, endOffset.x)
-            val right = max(startOffset.x, endOffset.x)
-
-            var startTop = localLayoutCoordinates.localPositionOf(
-                startLayoutCoordinates,
-                Offset(
-                    0f,
-                    startSelectable.getBoundingBox(selection.start.offset).top
-                )
-            )
-
-            var endTop = localLayoutCoordinates.localPositionOf(
-                endLayoutCoordinates,
-                Offset(
-                    0.0f,
-                    endSelectable.getBoundingBox(selection.end.offset).top
-                )
-            )
-
-            startTop = localLayoutCoordinates.localToRoot(startTop)
-            endTop = localLayoutCoordinates.localToRoot(endTop)
-
-            val top = min(startTop.y, endTop.y)
-            val bottom = max(startOffset.y, endOffset.y) + (HandleHeight.value * 4.0).toFloat()
-
-            return Rect(
-                left,
-                top,
-                right,
-                bottom
-            )
-        }
-        return Rect.Zero
-    }
-
-    // This is for PressGestureDetector to cancel the selection.
-    fun onRelease() {
-        selectionRegistrar.subselections = emptyMap()
-        hideSelectionToolbar()
-        if (selection != null) {
-            onSelectionChange(null)
-            hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
-        }
-    }
-
-    fun handleDragObserver(isStartHandle: Boolean): TextDragObserver = object : TextDragObserver {
-        override fun onDown(point: Offset) {
-            val selection = selection ?: return
-            val anchor = if (isStartHandle) selection.start else selection.end
-            val selectable = getAnchorSelectable(anchor) ?: return
-            // The LayoutCoordinates of the composable where the drag gesture should begin. This
-            // is used to convert the position of the beginning of the drag gesture from the
-            // composable coordinates to selection container coordinates.
-            val beginLayoutCoordinates = selectable.getLayoutCoordinates() ?: return
-
-            // The position of the character where the drag gesture should begin. This is in
-            // the composable coordinates.
-            val beginCoordinates = getAdjustedCoordinates(
-                selectable.getHandlePosition(
-                    selection = selection, isStartHandle = isStartHandle
-                )
-            )
-
-            // Convert the position where drag gesture begins from composable coordinates to
-            // selection container coordinates.
-            currentDragPosition = requireContainerCoordinates().localPositionOf(
-                beginLayoutCoordinates,
-                beginCoordinates
-            )
-            draggingHandle = if (isStartHandle) Handle.SelectionStart else Handle.SelectionEnd
-        }
-
-        override fun onUp() {
-            draggingHandle = null
-            currentDragPosition = null
-        }
-
-        override fun onStart(startPoint: Offset) {
-            hideSelectionToolbar()
-            val selection = selection!!
-            val startSelectable =
-                selectionRegistrar.selectableMap[selection.start.selectableId]
-            val endSelectable =
-                selectionRegistrar.selectableMap[selection.end.selectableId]
-            // The LayoutCoordinates of the composable where the drag gesture should begin. This
-            // is used to convert the position of the beginning of the drag gesture from the
-            // composable coordinates to selection container coordinates.
-            val beginLayoutCoordinates = if (isStartHandle) {
-                startSelectable?.getLayoutCoordinates()!!
-            } else {
-                endSelectable?.getLayoutCoordinates()!!
-            }
-
-            // The position of the character where the drag gesture should begin. This is in
-            // the composable coordinates.
-            val beginCoordinates = getAdjustedCoordinates(
-                if (isStartHandle) {
-                    startSelectable!!.getHandlePosition(
-                        selection = selection, isStartHandle = true
-                    )
-                } else {
-                    endSelectable!!.getHandlePosition(
-                        selection = selection, isStartHandle = false
-                    )
-                }
-            )
-
-            // Convert the position where drag gesture begins from composable coordinates to
-            // selection container coordinates.
-            dragBeginPosition = requireContainerCoordinates().localPositionOf(
-                beginLayoutCoordinates,
-                beginCoordinates
-            )
-
-            // Zero out the total distance that being dragged.
-            dragTotalDistance = Offset.Zero
-        }
-
-        override fun onDrag(delta: Offset) {
-            dragTotalDistance += delta
-            val endPosition = dragBeginPosition + dragTotalDistance
-            val consumed = updateSelection(
-                newPosition = endPosition,
-                previousPosition = dragBeginPosition,
-                isStartHandle = isStartHandle,
-                adjustment = SelectionAdjustment.CharacterWithWordAccelerate
-            )
-            if (consumed) {
-                dragBeginPosition = endPosition
-                dragTotalDistance = Offset.Zero
-            }
-        }
-
-        override fun onStop() {
-            showSelectionToolbar()
-            draggingHandle = null
-            currentDragPosition = null
-        }
-
-        override fun onCancel() {
-            showSelectionToolbar()
-            draggingHandle = null
-            currentDragPosition = null
-        }
-    }
-
-    /**
-     * Detect tap without consuming the up event.
-     */
-    private suspend fun PointerInputScope.detectNonConsumingTap(onTap: (Offset) -> Unit) {
-        awaitEachGesture {
-            waitForUpOrCancellation()?.let {
-                onTap(it.position)
-            }
-        }
-    }
-
-    private fun Modifier.onClearSelectionRequested(block: () -> Unit): Modifier {
-        return if (hasFocus) pointerInput(Unit) { detectNonConsumingTap { block() } } else this
-    }
-
-    private fun convertToContainerCoordinates(
-        layoutCoordinates: LayoutCoordinates,
-        offset: Offset
-    ): Offset? {
-        val coordinates = containerLayoutCoordinates
-        if (coordinates == null || !coordinates.isAttached) return null
-        return requireContainerCoordinates().localPositionOf(layoutCoordinates, offset)
-    }
-
-    /**
-     * Cancel the previous selection and start a new selection at the given [position].
-     * It's used for long-press, double-click, triple-click and so on to start selection.
-     *
-     * @param position initial position of the selection. Both start and end handle is considered
-     * at this position.
-     * @param isStartHandle whether it's considered as the start handle moving. This parameter
-     * will influence the [SelectionAdjustment]'s behavior. For example,
-     * [SelectionAdjustment.Character] only adjust the moving handle.
-     * @param adjustment the selection adjustment.
-     */
-    private fun startSelection(
-        position: Offset,
-        isStartHandle: Boolean,
-        adjustment: SelectionAdjustment
-    ) {
-        updateSelection(
-            startHandlePosition = position,
-            endHandlePosition = position,
-            previousHandlePosition = null,
-            isStartHandle = isStartHandle,
-            adjustment = adjustment
-        )
-    }
-
-    /**
-     * Updates the selection after one of the selection handle moved.
-     *
-     * @param newPosition the new position of the moving selection handle.
-     * @param previousPosition the previous position of the moving selection handle.
-     * @param isStartHandle whether the moving selection handle is the start handle.
-     * @param adjustment the [SelectionAdjustment] used to adjust the raw selection range and
-     * produce the final selection range.
-     *
-     * @return a boolean representing whether the movement is consumed.
-     *
-     * @see SelectionAdjustment
-     */
-    internal fun updateSelection(
-        newPosition: Offset?,
-        previousPosition: Offset?,
-        isStartHandle: Boolean,
-        adjustment: SelectionAdjustment,
-    ): Boolean {
-        if (newPosition == null) return false
-        val otherHandlePosition = selection?.let { selection ->
-            val otherSelectableId = if (isStartHandle) {
-                selection.end.selectableId
-            } else {
-                selection.start.selectableId
-            }
-            val otherSelectable =
-                selectionRegistrar.selectableMap[otherSelectableId] ?: return@let null
-            convertToContainerCoordinates(
-                otherSelectable.getLayoutCoordinates()!!,
-                getAdjustedCoordinates(
-                    otherSelectable.getHandlePosition(selection, !isStartHandle)
-                )
-            )
-        } ?: return false
-
-        val startHandlePosition = if (isStartHandle) newPosition else otherHandlePosition
-        val endHandlePosition = if (isStartHandle) otherHandlePosition else newPosition
-
-        return updateSelection(
-            startHandlePosition = startHandlePosition,
-            endHandlePosition = endHandlePosition,
-            previousHandlePosition = previousPosition,
-            isStartHandle = isStartHandle,
-            adjustment = adjustment
-        )
-    }
-
-    /**
-     * Updates the selection after one of the selection handle moved.
-     *
-     * To make sure that [SelectionAdjustment] works correctly, it's expected that only one
-     * selection handle is updated each time. The only exception is that when a new selection is
-     * started. In this case, [previousHandlePosition] is always null.
-     *
-     * @param startHandlePosition the position of the start selection handle.
-     * @param endHandlePosition the position of the end selection handle.
-     * @param previousHandlePosition the position of the moving handle before the update.
-     * @param isStartHandle whether the moving selection handle is the start handle.
-     * @param adjustment the [SelectionAdjustment] used to adjust the raw selection range and
-     * produce the final selection range.
-     *
-     * @return a boolean representing whether the movement is consumed. It's useful for the case
-     * where a selection handle is updating consecutively. When the return value is true, it's
-     * expected that the caller will update the [startHandlePosition] to be the given
-     * [endHandlePosition] in following calls.
-     *
-     * @see SelectionAdjustment
-     */
-    internal fun updateSelection(
-        startHandlePosition: Offset,
-        endHandlePosition: Offset,
-        previousHandlePosition: Offset?,
-        isStartHandle: Boolean,
-        adjustment: SelectionAdjustment,
-    ): Boolean {
-        draggingHandle = if (isStartHandle) Handle.SelectionStart else Handle.SelectionEnd
-        currentDragPosition = if (isStartHandle) startHandlePosition else endHandlePosition
-        val newSubselections = mutableMapOf<Long, Selection>()
-        var moveConsumed = false
-        val newSelection = selectionRegistrar.sort(requireContainerCoordinates())
-            .fastFold(null) { mergedSelection: Selection?, selectable: Selectable ->
-                val previousSubselection =
-                    selectionRegistrar.subselections[selectable.selectableId]
-                val (selection, consumed) = selectable.updateSelection(
-                    startHandlePosition = startHandlePosition,
-                    endHandlePosition = endHandlePosition,
-                    previousHandlePosition = previousHandlePosition,
-                    isStartHandle = isStartHandle,
-                    containerLayoutCoordinates = requireContainerCoordinates(),
-                    adjustment = adjustment,
-                    previousSelection = previousSubselection,
-                )
-
-                moveConsumed = moveConsumed || consumed
-                selection?.let { newSubselections[selectable.selectableId] = it }
-                merge(mergedSelection, selection)
-            }
-        if (newSelection != selection) {
-            hapticFeedBack?.performHapticFeedback(HapticFeedbackType.TextHandleMove)
-            selectionRegistrar.subselections = newSubselections
-            onSelectionChange(newSelection)
-        }
-        return moveConsumed
-    }
-
-    fun contextMenuOpenAdjustment(position: Offset) {
-        val isEmptySelection = selection?.toTextRange()?.collapsed ?: true
-        // TODO(b/209483184) the logic should be more complex here, it should check that current
-        // selection doesn't include click position
-        if (isEmptySelection) {
-            startSelection(
-                position = position,
-                isStartHandle = true,
-                adjustment = SelectionAdjustment.Word
-            )
-        }
-    }
-}
-
-internal fun merge(lhs: Selection?, rhs: Selection?): Selection? {
-    return lhs?.merge(rhs) ?: rhs
-}
-
-internal expect fun isCopyKeyEvent(keyEvent: KeyEvent): Boolean
-
-internal expect fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier
-
-internal fun calculateSelectionMagnifierCenterAndroid(
-    manager: SelectionManager,
-    magnifierSize: IntSize
-): Offset {
-    fun getMagnifierCenter(anchor: Selection.AnchorInfo, isStartHandle: Boolean): Offset {
-        val selectable = manager.getAnchorSelectable(anchor) ?: return Offset.Unspecified
-        val containerCoordinates = manager.containerLayoutCoordinates ?: return Offset.Unspecified
-        val selectableCoordinates = selectable.getLayoutCoordinates() ?: return Offset.Unspecified
-        // The end offset is exclusive.
-        val offset = if (isStartHandle) anchor.offset else anchor.offset - 1
-
-        // The horizontal position doesn't snap to cursor positions but should directly track the
-        // actual drag.
-        val localDragPosition = selectableCoordinates.localPositionOf(
-            containerCoordinates,
-            manager.currentDragPosition!!
-        )
-        val dragX = localDragPosition.x
-        // But it is constrained by the horizontal bounds of the current line.
-        val centerX = selectable.getRangeOfLineContaining(offset).let { line ->
-            val lineMin = selectable.getBoundingBox(line.min)
-            // line.end is exclusive, but we want the bounding box of the actual last character in
-            // the line.
-            val lineMax = selectable.getBoundingBox((line.max - 1).coerceAtLeast(line.min))
-            val minX = minOf(lineMin.left, lineMax.left)
-            val maxX = maxOf(lineMin.right, lineMax.right)
-            dragX.coerceIn(minX, maxX)
-        }
-
-        // Hide the magnifier when dragged too far (outside the horizontal bounds of how big the
-        // magnifier actually is). See
-        // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/widget/Editor.java;l=5228-5231;drc=2fdb6bd709be078b72f011334362456bb758922c
-        if ((dragX - centerX).absoluteValue > magnifierSize.width / 2) {
-            return Offset.Unspecified
-        }
-
-        // Let the selectable determine the vertical position of the magnifier, since it should be
-        // clamped to the center of text lines.
-        val anchorBounds = selectable.getBoundingBox(offset)
-        val centerY = anchorBounds.center.y
-
-        return containerCoordinates.localPositionOf(
-            sourceCoordinates = selectableCoordinates,
-            relativeToSource = Offset(centerX, centerY)
-        )
-    }
-
-    val selection = manager.selection ?: return Offset.Unspecified
-    return when (manager.draggingHandle) {
-        null -> return Offset.Unspecified
-        Handle.SelectionStart -> getMagnifierCenter(selection.start, isStartHandle = true)
-        Handle.SelectionEnd -> getMagnifierCenter(selection.end, isStartHandle = false)
-        Handle.Cursor -> error("SelectionContainer does not support cursor")
-    }
-}
-
-internal fun getCurrentSelectedText(
-    selectable: Selectable,
-    selection: Selection
-): AnnotatedString {
-    val currentText = selectable.getText()
-
-    return if (
-        selectable.selectableId != selection.start.selectableId &&
-        selectable.selectableId != selection.end.selectableId
-    ) {
-        // Select the full text content if the current selectable is between the
-        // start and the end selectables.
-        currentText
-    } else if (
-        selectable.selectableId == selection.start.selectableId &&
-        selectable.selectableId == selection.end.selectableId
-    ) {
-        // Select partial text content if the current selectable is the start and
-        // the end selectable.
-        if (selection.handlesCrossed) {
-            currentText.subSequence(selection.end.offset, selection.start.offset)
-        } else {
-            currentText.subSequence(selection.start.offset, selection.end.offset)
-        }
-    } else if (selectable.selectableId == selection.start.selectableId) {
-        // Select partial text content if the current selectable is the start
-        // selectable.
-        if (selection.handlesCrossed) {
-            currentText.subSequence(0, selection.start.offset)
-        } else {
-            currentText.subSequence(selection.start.offset, currentText.length)
-        }
-    } else {
-        // Selectable partial text content if the current selectable is the end
-        // selectable.
-        if (selection.handlesCrossed) {
-            currentText.subSequence(selection.end.offset, currentText.length)
-        } else {
-            currentText.subSequence(0, selection.end.offset)
-        }
-    }
-}
-
-/** Returns the boundary of the visible area in this [LayoutCoordinates]. */
-internal fun LayoutCoordinates.visibleBounds(): Rect {
-    // globalBounds is the global boundaries of this LayoutCoordinates after it's clipped by
-    // parents. We can think it as the global visible bounds of this Layout. Here globalBounds
-    // is convert to local, which is the boundary of the visible area within the LayoutCoordinates.
-    val boundsInWindow = boundsInWindow()
-    return Rect(
-        windowToLocal(boundsInWindow.topLeft),
-        windowToLocal(boundsInWindow.bottomRight)
-    )
-}
-
-internal fun Rect.containsInclusive(offset: Offset): Boolean =
-    offset.x in left..right && offset.y in top..bottom
-
-internal enum class Handle {
-    Cursor,
-    SelectionStart,
-    SelectionEnd
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMode.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMode.kt
deleted file mode 100644
index da7e8e0..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionMode.kt
+++ /dev/null
@@ -1,107 +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.newtext.text.copypasta.selection
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-
-/**
- * The enum class allows user to decide the selection mode.
- */
-internal enum class SelectionMode {
-    /**
-     * When selection handles are dragged across composables, selection extends by row, for example,
-     * when the end selection handle is dragged down, upper rows will be selected first, and the
-     * lower rows.
-     */
-    Vertical {
-        override fun compare(position: Offset, bounds: Rect): Int {
-            if (bounds.contains(position)) return 0
-
-            // When the position of the selection handle is on the top of the composable, and the
-            // not on the right of the composable, it's considered as start.
-            if (position.y < bounds.top) return -1
-
-            // When the position of the selection handle is on the left of the composable, and not
-            // below the bottom of composable, it's considered as start.
-            if (position.x < bounds.left && position.y < bounds.bottom) return -1
-
-            // In all other cases, the selection handle is considered as the end.
-            return 1
-        }
-    },
-
-    /**
-     * When selection handles are dragged across composables, selection extends by column, for example,
-     * when the end selection handle is dragged to the right, left columns will be selected first,
-     * and the right rows.
-     */
-    Horizontal {
-        override fun compare(position: Offset, bounds: Rect): Int {
-            if (bounds.contains(position)) return 0
-
-            // When the end of the selection is on the left of the composable, the composable is
-            // outside of the selection range.
-            if (position.x < bounds.left) return -1
-
-            // When the end of the selection is on the top of the composable, and the not on the
-            // right of the composable, the composable is outside of the selection range.
-            if (position.y < bounds.top && position.x < bounds.right) return -1
-
-            // In all other cases, the selection handle is considered as the end.
-            return 1
-        }
-    };
-
-    /**
-     * A compare a selection handle with a  [Selectable] boundary. This defines whether an out of
-     * boundary selection handle is treated as the start or the end of the Selectable. If the
-     * [Selectable] is a text selectable, then the start is the index 0, and end corresponds to
-     * the text length.
-     *
-     * @param position the position of the selection handle.
-     * @param bounds the boundary of the [Selectable].
-     * @return 0 if the selection handle [position] is within the [bounds]; a negative value if
-     * the selection handle is considered as "start" of the [Selectable]; a positive value if the
-     * selection handle is considered as the "end" of the [Selectable].
-     */
-    internal abstract fun compare(position: Offset, bounds: Rect): Int
-
-    /**
-     * Decides if Composable which has [bounds], should be accepted by the selection and
-     * change its selected state for a selection that starts at [start] and ends at [end].
-     *
-     * @param bounds Composable bounds of the widget to be checked.
-     * @param start The start coordinates of the selection, in SelectionContainer range.
-     * @param end The end coordinates of the selection, in SelectionContainer range.
-     */
-    internal fun isSelected(
-        bounds: Rect,
-        start: Offset,
-        end: Offset
-    ): Boolean {
-        // If either of the start or end is contained by bounds, the composable is selected.
-        if (bounds.contains(start) || bounds.contains(end)) {
-            return true
-        }
-        // Compare the location of start and end to the bound. If both are on the same side, return
-        // false, otherwise return true.
-        val compareStart = compare(start, bounds)
-        val compareEnd = compare(end, bounds)
-        return (compareStart > 0) xor (compareEnd > 0)
-    }
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrar.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrar.kt
deleted file mode 100644
index dd1f86c..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrar.kt
+++ /dev/null
@@ -1,159 +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.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.compositionLocalOf
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.layout.LayoutCoordinates
-
-/**
- *  An interface allowing a composable to subscribe and unsubscribe to selection changes.
- */
-internal interface SelectionRegistrar {
-    /**
-     * The map stored current selection information on each [Selectable]. A selectable can query
-     * its selected range using its [Selectable.selectableId]. This field is backed by a
-     * [MutableState]. And any composable reading this field will be recomposed once its value
-     * changed.
-     */
-    val subselections: Map<Long, Selection>
-
-    /**
-     * Subscribe to SelectionContainer selection changes.
-     * @param selectable the [Selectable] that is subscribing to this [SelectionRegistrar].
-     */
-    fun subscribe(selectable: Selectable): Selectable
-
-    /**
-     * Unsubscribe from SelectionContainer selection changes.
-     * @param selectable the [Selectable] that is unsubscribing to this [SelectionRegistrar].
-     */
-    fun unsubscribe(selectable: Selectable)
-
-    /**
-     * Return a unique ID for a [Selectable].
-     * @see [Selectable.selectableId]
-     */
-    fun nextSelectableId(): Long
-
-    /**
-     * When the Global Position of a subscribed [Selectable] changes, this method
-     * is called.
-     */
-    fun notifyPositionChange(selectableId: Long)
-
-    /**
-     * Call this method to notify the [SelectionContainer] that the selection has been initiated.
-     * Depends on the input, [notifySelectionUpdate] may be called repeatedly after
-     * [notifySelectionUpdateStart] is called. And [notifySelectionUpdateEnd] should always be
-     * called after selection finished.
-     * For example:
-     *  1. User long pressed the text and then release. [notifySelectionUpdateStart] should be
-     *  called followed by [notifySelectionUpdateEnd] being called once.
-     *  2. User long pressed the text and then drag a distance and then release.
-     *  [notifySelectionUpdateStart] should be called first after the user long press, and then
-     *  [notifySelectionUpdate] is called several times reporting the updates, in the end
-     *  [notifySelectionUpdateEnd] is called to finish the selection.
-     *
-     * @param layoutCoordinates [LayoutCoordinates] of the [Selectable].
-     * @param startPosition coordinates of where the selection is initiated.
-     * @param adjustment selection should be adjusted according to this param
-     *
-     * @see notifySelectionUpdate
-     * @see notifySelectionUpdateEnd
-     */
-    fun notifySelectionUpdateStart(
-        layoutCoordinates: LayoutCoordinates,
-        startPosition: Offset,
-        adjustment: SelectionAdjustment
-    )
-
-    /**
-     * Call this method to notify the [SelectionContainer] that the selection has been initiated
-     * with selectAll [Selection].
-     *
-     * @param selectableId [selectableId] of the [Selectable]
-     */
-    fun notifySelectionUpdateSelectAll(selectableId: Long)
-
-    /**
-     * Call this method to notify the [SelectionContainer] that one of the selection handle has
-     * moved and selection should be updated.
-     * The caller of this method should make sure that [notifySelectionUpdateStart] is always
-     * called once before calling this function. And [notifySelectionUpdateEnd] is always called
-     * once after the all updates finished.
-     *
-     * @param layoutCoordinates [LayoutCoordinates] of the [Selectable].
-     * @param previousPosition coordinates of where the selection starts.
-     * @param newPosition coordinates of where the selection ends.
-     * @param isStartHandle whether the moving selection handle the start handle.
-     * @param adjustment selection should be adjusted according to this parameter
-     *
-     * @return true if the selection handle movement is consumed. This function acts like a
-     * pointer input consumer when a selection handle is dragged. It expects the caller to
-     * accumulate the unconsumed pointer movement:
-     * 1. if it returns true, the caller will zero out the previous movement.
-     * 2. if it returns false, the caller will continue accumulate pointer movement.
-     * @see notifySelectionUpdateStart
-     * @see notifySelectionUpdateEnd
-     */
-    fun notifySelectionUpdate(
-        layoutCoordinates: LayoutCoordinates,
-        newPosition: Offset,
-        previousPosition: Offset,
-        isStartHandle: Boolean,
-        adjustment: SelectionAdjustment
-    ): Boolean
-
-    /**
-     * Call this method to notify the [SelectionContainer] that the selection update has stopped.
-     *
-     * @see notifySelectionUpdateStart
-     * @see notifySelectionUpdate
-     */
-    fun notifySelectionUpdateEnd()
-
-    /**
-     * Call this method to notify the [SelectionContainer] that the content of the passed
-     * selectable has been changed.
-     *
-     * @param selectableId the ID of the selectable whose the content has been updated.
-     */
-    fun notifySelectableChange(selectableId: Long)
-
-    companion object {
-        /**
-         * Representing an invalid ID for [Selectable].
-         */
-        const val InvalidSelectableId = 0L
-    }
-}
-
-/**
- * Helper function that checks if there is a selection on this CoreText.
- */
-internal fun SelectionRegistrar?.hasSelection(selectableId: Long): Boolean {
-    return this?.subselections?.containsKey(selectableId) ?: false
-}
-
-/**
- * SelectionRegistrar CompositionLocal. Composables that implement selection logic can use this
- * CompositionLocal to get a [SelectionRegistrar] in order to subscribe and unsubscribe to
- * [SelectionRegistrar].
- */
-internal val LocalSelectionRegistrar = compositionLocalOf<SelectionRegistrar?> { null }
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrarImpl.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrarImpl.kt
deleted file mode 100644
index f08c238..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionRegistrarImpl.kt
+++ /dev/null
@@ -1,205 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.newtext.text.copypasta.AtomicLong
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.layout.LayoutCoordinates
-
-internal class SelectionRegistrarImpl : SelectionRegistrar {
-    /**
-     * A flag to check if the [Selectable]s have already been sorted.
-     */
-    internal var sorted: Boolean = false
-
-    /**
-     * This is essentially the list of registered components that want
-     * to handle text selection that are below the SelectionContainer.
-     */
-    private val _selectables = mutableListOf<Selectable>()
-
-    /**
-     * Getter for handlers that returns a List.
-     */
-    internal val selectables: List<Selectable>
-        get() = _selectables
-
-    private val _selectableMap = mutableMapOf<Long, Selectable>()
-
-    /**
-     * A map from selectable keys to subscribed selectables.
-     */
-    internal val selectableMap: Map<Long, Selectable>
-        get() = _selectableMap
-
-    /**
-     * The incremental id to be assigned to each selectable. It starts from 1 and 0 is used to
-     * denote an invalid id.
-     * @see SelectionRegistrar.InvalidSelectableId
-     */
-    private var incrementId = AtomicLong(1)
-
-    /**
-     * The callback to be invoked when the position change was triggered.
-     */
-    internal var onPositionChangeCallback: ((Long) -> Unit)? = null
-
-    /**
-     * The callback to be invoked when the selection is initiated.
-     */
-    internal var onSelectionUpdateStartCallback:
-        ((LayoutCoordinates, Offset, SelectionAdjustment) -> Unit)? = null
-
-    /**
-     * The callback to be invoked when the selection is initiated with selectAll [Selection].
-     */
-    internal var onSelectionUpdateSelectAll: (
-        (Long) -> Unit
-    )? = null
-
-    /**
-     * The callback to be invoked when the selection is updated.
-     * If the first offset is null it means that the start of selection is unknown for the caller.
-     */
-    internal var onSelectionUpdateCallback:
-        ((LayoutCoordinates, Offset, Offset, Boolean, SelectionAdjustment) -> Boolean)? = null
-
-    /**
-     * The callback to be invoked when selection update finished.
-     */
-    internal var onSelectionUpdateEndCallback: (() -> Unit)? = null
-
-    /**
-     * The callback to be invoked when one of the selectable has changed.
-     */
-    internal var onSelectableChangeCallback: ((Long) -> Unit)? = null
-
-    /**
-     * The callback to be invoked after a selectable is unsubscribed from this [SelectionRegistrar].
-     */
-    internal var afterSelectableUnsubscribe: ((Long) -> Unit)? = null
-
-    override var subselections: Map<Long, Selection> by mutableStateOf(emptyMap())
-
-    override fun subscribe(selectable: Selectable): Selectable {
-        require(selectable.selectableId != SelectionRegistrar.InvalidSelectableId) {
-            "The selectable contains an invalid id: ${selectable.selectableId}"
-        }
-        require(!_selectableMap.containsKey(selectable.selectableId)) {
-            "Another selectable with the id: $selectable.selectableId has already subscribed."
-        }
-        _selectableMap[selectable.selectableId] = selectable
-        _selectables.add(selectable)
-        sorted = false
-        return selectable
-    }
-
-    override fun unsubscribe(selectable: Selectable) {
-        if (!_selectableMap.containsKey(selectable.selectableId)) return
-        _selectables.remove(selectable)
-        _selectableMap.remove(selectable.selectableId)
-        afterSelectableUnsubscribe?.invoke(selectable.selectableId)
-    }
-
-    override fun nextSelectableId(): Long {
-        var id = incrementId.getAndIncrement()
-        while (id == SelectionRegistrar.InvalidSelectableId) {
-            id = incrementId.getAndIncrement()
-        }
-        return id
-    }
-
-    /**
-     * Sort the list of registered [Selectable]s in [SelectionRegistrar]. Currently the order of
-     * selectables is geometric-based.
-     */
-    fun sort(containerLayoutCoordinates: LayoutCoordinates): List<Selectable> {
-        if (!sorted) {
-            // Sort selectables by y-coordinate first, and then x-coordinate, to match English
-            // hand-writing habit.
-            _selectables.sortWith { a: Selectable, b: Selectable ->
-                val layoutCoordinatesA = a.getLayoutCoordinates()
-                val layoutCoordinatesB = b.getLayoutCoordinates()
-
-                val positionA = if (layoutCoordinatesA != null) {
-                    containerLayoutCoordinates.localPositionOf(layoutCoordinatesA, Offset.Zero)
-                } else {
-                    Offset.Zero
-                }
-                val positionB = if (layoutCoordinatesB != null) {
-                    containerLayoutCoordinates.localPositionOf(layoutCoordinatesB, Offset.Zero)
-                } else {
-                    Offset.Zero
-                }
-
-                if (positionA.y == positionB.y) {
-                    compareValues(positionA.x, positionB.x)
-                } else {
-                    compareValues(positionA.y, positionB.y)
-                }
-            }
-            sorted = true
-        }
-        return selectables
-    }
-
-    override fun notifyPositionChange(selectableId: Long) {
-        // Set the variable sorted to be false, when the global position of a registered
-        // selectable changes.
-        sorted = false
-        onPositionChangeCallback?.invoke(selectableId)
-    }
-
-    override fun notifySelectionUpdateStart(
-        layoutCoordinates: LayoutCoordinates,
-        startPosition: Offset,
-        adjustment: SelectionAdjustment
-    ) {
-        onSelectionUpdateStartCallback?.invoke(layoutCoordinates, startPosition, adjustment)
-    }
-
-    override fun notifySelectionUpdateSelectAll(selectableId: Long) {
-        onSelectionUpdateSelectAll?.invoke(selectableId)
-    }
-
-    override fun notifySelectionUpdate(
-        layoutCoordinates: LayoutCoordinates,
-        newPosition: Offset,
-        previousPosition: Offset,
-        isStartHandle: Boolean,
-        adjustment: SelectionAdjustment
-    ): Boolean {
-        return onSelectionUpdateCallback?.invoke(
-            layoutCoordinates,
-            newPosition,
-            previousPosition,
-            isStartHandle,
-            adjustment
-        ) ?: true
-    }
-
-    override fun notifySelectionUpdateEnd() {
-        onSelectionUpdateEndCallback?.invoke()
-    }
-
-    override fun notifySelectableChange(selectableId: Long) {
-        onSelectableChangeCallback?.invoke(selectableId)
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SimpleLayout.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SimpleLayout.kt
deleted file mode 100644
index 9929a2e..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SimpleLayout.kt
+++ /dev/null
@@ -1,65 +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.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.util.fastForEach
-import androidx.compose.ui.util.fastMap
-import kotlin.contracts.ExperimentalContracts
-import kotlin.contracts.contract
-import kotlin.math.max
-
-/**
- * Selection is transparent in terms of measurement and layout and passes the same constraints to
- * the children.
- */
-@Composable
-internal fun SimpleLayout(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
-    Layout(modifier = modifier, content = content) { measurables, constraints ->
-        val placeables = measurables.fastMap { measurable ->
-            measurable.measure(constraints)
-        }
-
-        val width = placeables.fastFold(0) { maxWidth, placeable ->
-            max(maxWidth, (placeable.width))
-        }
-
-        val height = placeables.fastFold(0) { minWidth, placeable ->
-            max(minWidth, (placeable.height))
-        }
-
-        layout(width, height) {
-            placeables.fastForEach { placeable ->
-                placeable.place(0, 0)
-            }
-        }
-    }
-}
-
-// copypasta from foundation to compile this copypasta
-@Suppress("BanInlineOptIn") // Treat Kotlin Contracts as non-experimental.
-@OptIn(ExperimentalContracts::class)
-internal inline fun <T, R> List<T>.fastFold(initial: R, operation: (acc: R, T) -> R): R {
-    contract { callsInPlace(operation) }
-    var accumulator = initial
-    fastForEach { e ->
-        accumulator = operation(accumulator, e)
-    }
-    return accumulator
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextPreparedSelection.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextPreparedSelection.kt
deleted file mode 100644
index a3e5817..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextPreparedSelection.kt
+++ /dev/null
@@ -1,432 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.newtext.text.copypasta.TextLayoutResultProxy
-import androidx.compose.foundation.newtext.text.copypasta.findFollowingBreak
-import androidx.compose.foundation.newtext.text.copypasta.findParagraphEnd
-import androidx.compose.foundation.newtext.text.copypasta.findParagraphStart
-import androidx.compose.foundation.newtext.text.copypasta.findPrecedingBreak
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.CommitTextCommand
-import androidx.compose.ui.text.input.EditCommand
-import androidx.compose.ui.text.input.OffsetMapping
-import androidx.compose.ui.text.input.SetSelectionCommand
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.style.ResolvedTextDirection
-
-internal class TextPreparedSelectionState {
-    // it's set at the start of vertical navigation and used as the preferred value to set a new
-    // cursor position.
-    var cachedX: Float? = null
-
-    fun resetCachedX() {
-        cachedX = null
-    }
-}
-
-/**
- * This utility class implements many selection-related operations on text (including basic
- * cursor movements and deletions) and combines them, taking into account how the text was
- * rendered. So, for example, [moveCursorToLineEnd] moves it to the visual line end.
- *
- * For many of these operations, it's particularly important to keep the difference between
- * selection start and selection end. In some systems, they are called "anchor" and "caret"
- * respectively. For example, for selection from scratch, after [moveCursorLeftByWord]
- * [moveCursorRight] will move the left side of the selection, but after [moveCursorRightByWord]
- * the right one.
- *
- * To use it in scope of text fields see [TextFieldPreparedSelection]
- */
-internal abstract class BaseTextPreparedSelection<T : BaseTextPreparedSelection<T>>(
-    val originalText: AnnotatedString,
-    val originalSelection: TextRange,
-    val layoutResult: TextLayoutResult?,
-    val offsetMapping: OffsetMapping,
-    val state: TextPreparedSelectionState
-) {
-    var selection = originalSelection
-
-    var annotatedString = originalText
-    internal val text
-        get() = annotatedString.text
-
-    @Suppress("UNCHECKED_CAST")
-    protected inline fun <U> U.apply(resetCachedX: Boolean = true, block: U.() -> Unit): T {
-        if (resetCachedX) {
-            state.resetCachedX()
-        }
-        if (text.isNotEmpty()) {
-            block()
-        }
-        return this as T
-    }
-
-    protected fun setCursor(offset: Int) {
-        setSelection(offset, offset)
-    }
-
-    protected fun setSelection(start: Int, end: Int) {
-        selection = TextRange(start, end)
-    }
-
-    fun selectAll() = apply {
-        setSelection(0, text.length)
-    }
-
-    fun deselect() = apply {
-        setCursor(selection.end)
-    }
-
-    fun moveCursorLeft() = apply {
-        if (isLtr()) {
-            moveCursorPrev()
-        } else {
-            moveCursorNext()
-        }
-    }
-
-    fun moveCursorRight() = apply {
-        if (isLtr()) {
-            moveCursorNext()
-        } else {
-            moveCursorPrev()
-        }
-    }
-
-    /**
-     * If there is already a selection, collapse it to the left side. Otherwise, execute [or]
-     */
-    fun collapseLeftOr(or: T.() -> Unit) = apply {
-        if (selection.collapsed) {
-            @Suppress("UNCHECKED_CAST")
-            or(this as T)
-        } else {
-            if (isLtr()) {
-                setCursor(selection.min)
-            } else {
-                setCursor(selection.max)
-            }
-        }
-    }
-
-    /**
-     * If there is already a selection, collapse it to the right side. Otherwise, execute [or]
-     */
-    fun collapseRightOr(or: T.() -> Unit) = apply {
-        if (selection.collapsed) {
-            @Suppress("UNCHECKED_CAST")
-            or(this as T)
-        } else {
-            if (isLtr()) {
-                setCursor(selection.max)
-            } else {
-                setCursor(selection.min)
-            }
-        }
-    }
-
-    /**
-     * Returns the index of the character break preceding the end of [selection].
-     */
-    fun getPrecedingCharacterIndex() = annotatedString.text.findPrecedingBreak(selection.end)
-
-    /**
-     * Returns the index of the character break following the end of [selection]. Returns
-     * [NoCharacterFound] if there are no more breaks before the end of the string.
-     */
-    fun getNextCharacterIndex() = annotatedString.text.findFollowingBreak(selection.end)
-
-    private fun moveCursorPrev() = apply {
-        val prev = getPrecedingCharacterIndex()
-        if (prev != -1) setCursor(prev)
-    }
-
-    private fun moveCursorNext() = apply {
-        val next = getNextCharacterIndex()
-        if (next != -1) setCursor(next)
-    }
-
-    fun moveCursorToHome() = apply {
-        setCursor(0)
-    }
-
-    fun moveCursorToEnd() = apply {
-        setCursor(text.length)
-    }
-
-    fun moveCursorLeftByWord() = apply {
-        if (isLtr()) {
-            moveCursorPrevByWord()
-        } else {
-            moveCursorNextByWord()
-        }
-    }
-
-    fun moveCursorRightByWord() = apply {
-        if (isLtr()) {
-            moveCursorNextByWord()
-        } else {
-            moveCursorPrevByWord()
-        }
-    }
-
-    fun getNextWordOffset(): Int? = layoutResult?.getNextWordOffsetForLayout()
-
-    private fun moveCursorNextByWord() = apply {
-        getNextWordOffset()?.let { setCursor(it) }
-    }
-
-    fun getPreviousWordOffset(): Int? = layoutResult?.getPrevWordOffset()
-
-    private fun moveCursorPrevByWord() = apply {
-        getPreviousWordOffset()?.let { setCursor(it) }
-    }
-
-    fun moveCursorPrevByParagraph() = apply {
-        setCursor(getParagraphStart())
-    }
-
-    fun moveCursorNextByParagraph() = apply {
-        setCursor(getParagraphEnd())
-    }
-
-    fun moveCursorUpByLine() = apply(false) {
-        layoutResult?.jumpByLinesOffset(-1)?.let { setCursor(it) }
-    }
-
-    fun moveCursorDownByLine() = apply(false) {
-        layoutResult?.jumpByLinesOffset(1)?.let { setCursor(it) }
-    }
-
-    fun getLineStartByOffset(): Int? = layoutResult?.getLineStartByOffsetForLayout()
-
-    fun moveCursorToLineStart() = apply {
-        getLineStartByOffset()?.let { setCursor(it) }
-    }
-
-    fun getLineEndByOffset(): Int? = layoutResult?.getLineEndByOffsetForLayout()
-
-    fun moveCursorToLineEnd() = apply {
-        getLineEndByOffset()?.let { setCursor(it) }
-    }
-
-    fun moveCursorToLineLeftSide() = apply {
-        if (isLtr()) {
-            moveCursorToLineStart()
-        } else {
-            moveCursorToLineEnd()
-        }
-    }
-
-    fun moveCursorToLineRightSide() = apply {
-        if (isLtr()) {
-            moveCursorToLineEnd()
-        } else {
-            moveCursorToLineStart()
-        }
-    }
-
-    // it selects a text from the original selection start to a current selection end
-    fun selectMovement() = apply(false) {
-        selection = TextRange(originalSelection.start, selection.end)
-    }
-
-    private fun isLtr(): Boolean {
-        val direction = layoutResult?.getParagraphDirection(transformedEndOffset())
-        return direction != ResolvedTextDirection.Rtl
-    }
-
-    private fun TextLayoutResult.getNextWordOffsetForLayout(
-        currentOffset: Int = transformedEndOffset()
-    ): Int {
-        if (currentOffset >= originalText.length) {
-            return originalText.length
-        }
-        val currentWord = getWordBoundary(charOffset(currentOffset))
-        return if (currentWord.end <= currentOffset) {
-            getNextWordOffsetForLayout(currentOffset + 1)
-        } else {
-            offsetMapping.transformedToOriginal(currentWord.end)
-        }
-    }
-
-    private fun TextLayoutResult.getPrevWordOffset(
-        currentOffset: Int = transformedEndOffset()
-    ): Int {
-        if (currentOffset < 0) {
-            return 0
-        }
-        val currentWord = getWordBoundary(charOffset(currentOffset))
-        return if (currentWord.start >= currentOffset) {
-            getPrevWordOffset(currentOffset - 1)
-        } else {
-            offsetMapping.transformedToOriginal(currentWord.start)
-        }
-    }
-
-    private fun TextLayoutResult.getLineStartByOffsetForLayout(
-        currentOffset: Int = transformedMinOffset()
-    ): Int {
-        val currentLine = getLineForOffset(currentOffset)
-        return offsetMapping.transformedToOriginal(getLineStart(currentLine))
-    }
-
-    private fun TextLayoutResult.getLineEndByOffsetForLayout(
-        currentOffset: Int = transformedMaxOffset()
-    ): Int {
-        val currentLine = getLineForOffset(currentOffset)
-        return offsetMapping.transformedToOriginal(getLineEnd(currentLine, true))
-    }
-
-    private fun TextLayoutResult.jumpByLinesOffset(linesAmount: Int): Int {
-        val currentOffset = transformedEndOffset()
-
-        if (state.cachedX == null) {
-            state.cachedX = getCursorRect(currentOffset).left
-        }
-
-        val targetLine = getLineForOffset(currentOffset) + linesAmount
-        when {
-            targetLine < 0 -> {
-                return 0
-            }
-            targetLine >= lineCount -> {
-                return text.length
-            }
-        }
-
-        val y = getLineBottom(targetLine) - 1
-        val x = state.cachedX!!.also {
-            if ((isLtr() && it >= getLineRight(targetLine)) ||
-                (!isLtr() && it <= getLineLeft(targetLine))
-            ) {
-                return getLineEnd(targetLine, true)
-            }
-        }
-
-        val newOffset = getOffsetForPosition(Offset(x, y)).let {
-            offsetMapping.transformedToOriginal(it)
-        }
-
-        return newOffset
-    }
-
-    private fun transformedEndOffset(): Int {
-        return offsetMapping.originalToTransformed(selection.end)
-    }
-
-    private fun transformedMinOffset(): Int {
-        return offsetMapping.originalToTransformed(selection.min)
-    }
-
-    private fun transformedMaxOffset(): Int {
-        return offsetMapping.originalToTransformed(selection.max)
-    }
-
-    private fun charOffset(offset: Int) =
-        offset.coerceAtMost(text.length - 1)
-
-    private fun getParagraphStart() = text.findParagraphStart(selection.min)
-
-    private fun getParagraphEnd() = text.findParagraphEnd(selection.max)
-
-    companion object {
-        /**
-         * Value returned by [getNextCharacterIndex] and [getPrecedingCharacterIndex] when no valid
-         * index could be found, e.g. it would be the end of the string.
-         *
-         * This is equivalent to `BreakIterator.DONE` on JVM/Android.
-         */
-        const val NoCharacterFound = -1
-    }
-}
-
-internal class TextPreparedSelection(
-    originalText: AnnotatedString,
-    originalSelection: TextRange,
-    layoutResult: TextLayoutResult? = null,
-    offsetMapping: OffsetMapping = OffsetMapping.Identity,
-    state: TextPreparedSelectionState = TextPreparedSelectionState()
-) : BaseTextPreparedSelection<TextPreparedSelection>(
-    originalText = originalText,
-    originalSelection = originalSelection,
-    layoutResult = layoutResult,
-    offsetMapping = offsetMapping,
-    state = state
-)
-
-internal class TextFieldPreparedSelection(
-    val currentValue: TextFieldValue,
-    offsetMapping: OffsetMapping = OffsetMapping.Identity,
-    val layoutResultProxy: TextLayoutResultProxy?,
-    state: TextPreparedSelectionState = TextPreparedSelectionState()
-) : BaseTextPreparedSelection<TextFieldPreparedSelection>(
-    originalText = currentValue.annotatedString,
-    originalSelection = currentValue.selection,
-    offsetMapping = offsetMapping,
-    layoutResult = layoutResultProxy?.value,
-    state = state
-) {
-    val value
-        get() = currentValue.copy(
-            annotatedString = annotatedString,
-            selection = selection
-        )
-
-    fun deleteIfSelectedOr(or: TextFieldPreparedSelection.() -> EditCommand?): List<EditCommand>? {
-        return if (selection.collapsed) {
-            or(this)?.let {
-                listOf(it)
-            }
-        } else {
-            listOf(
-                CommitTextCommand("", 0),
-                SetSelectionCommand(selection.min, selection.min)
-            )
-        }
-    }
-
-    fun moveCursorUpByPage() = apply(false) {
-        layoutResultProxy?.jumpByPagesOffset(-1)?.let { setCursor(it) }
-    }
-
-    fun moveCursorDownByPage() = apply(false) {
-        layoutResultProxy?.jumpByPagesOffset(1)?.let { setCursor(it) }
-    }
-
-    /**
-     * Returns a cursor position after jumping back or forth by [pagesAmount] number of pages,
-     * where `page` is the visible amount of space in the text field
-     */
-    private fun TextLayoutResultProxy.jumpByPagesOffset(pagesAmount: Int): Int {
-        val visibleInnerTextFieldRect = innerTextFieldCoordinates?.let { inner ->
-            decorationBoxCoordinates?.localBoundingBoxOf(inner)
-        } ?: Rect.Zero
-        val currentOffset = offsetMapping.originalToTransformed(currentValue.selection.end)
-        val currentPos = value.getCursorRect(currentOffset)
-        val x = currentPos.left
-        val y = currentPos.top + visibleInnerTextFieldRect.size.height * pagesAmount
-        return offsetMapping.transformedToOriginal(
-            value.getOffsetForPosition(Offset(x, y))
-        )
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionColors.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionColors.kt
deleted file mode 100644
index 6cc76ee..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionColors.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.compositionLocalOf
-import androidx.compose.ui.graphics.Color
-
-/**
- * Represents the colors used for text selection by text and text field components.
- *
- * See [LocalTextSelectionColors] to provide new values for this throughout the hierarchy.
- *
- * @property handleColor the color used for the selection handles on either side of the
- * selection region.
- * @property backgroundColor the color used to draw the background behind the selected
- * region. This color should have alpha applied to keep the text legible - this alpha is
- * typically 0.4f (40%) but this may need to be reduced in order to meet contrast requirements
- * depending on the color used for text, selection background, and the background behind the
- * selection background.
- */
-@Immutable
-class TextSelectionColors(
-    val handleColor: Color,
-    val backgroundColor: Color
-) {
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other !is TextSelectionColors) return false
-
-        if (handleColor != other.handleColor) return false
-        if (backgroundColor != other.backgroundColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = handleColor.hashCode()
-        result = 31 * result + backgroundColor.hashCode()
-        return result
-    }
-
-    override fun toString(): String {
-        return "SelectionColors(selectionHandleColor=$handleColor, " +
-            "selectionBackgroundColor=$backgroundColor)"
-    }
-}
-
-/**
- * CompositionLocal used to change the [TextSelectionColors] used by text and text field
- * components in the hierarchy.
- */
-val LocalTextSelectionColors = compositionLocalOf { DefaultTextSelectionColors }
-
-/**
- * Default color used is the blue from the Compose logo, b/172679845 for context
- */
-private val DefaultSelectionColor = Color(0xFF4286F4)
-
-@Stable
-private val DefaultTextSelectionColors = TextSelectionColors(
-    handleColor = DefaultSelectionColor,
-    backgroundColor = DefaultSelectionColor.copy(alpha = 0.4f)
-)
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionDelegate.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionDelegate.kt
deleted file mode 100644
index 5a530ec..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionDelegate.kt
+++ /dev/null
@@ -1,62 +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.newtext.text.copypasta.selection
-
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.text.TextLayoutResult
-import kotlin.math.max
-
-/**
- * This method returns the graphical position where the selection handle should be based on the
- * offset and other information.
- *
- * @param textLayoutResult a result of the text layout.
- * @param offset character offset to be calculated
- * @param isStart true if called for selection start handle
- * @param areHandlesCrossed true if the selection handles are crossed
- *
- * @return the graphical position where the selection handle should be.
- */
-internal fun getSelectionHandleCoordinates(
-    textLayoutResult: TextLayoutResult,
-    offset: Int,
-    isStart: Boolean,
-    areHandlesCrossed: Boolean
-): Offset {
-    val line = textLayoutResult.getLineForOffset(offset)
-    val x = textLayoutResult.getHorizontalPosition(offset, isStart, areHandlesCrossed)
-    val y = textLayoutResult.getLineBottom(line)
-
-    return Offset(x, y)
-}
-
-internal fun TextLayoutResult.getHorizontalPosition(
-    offset: Int,
-    isStart: Boolean,
-    areHandlesCrossed: Boolean
-): Float {
-    val offsetToCheck =
-        if (isStart && !areHandlesCrossed || !isStart && areHandlesCrossed) offset
-        else max(offset - 1, 0)
-    val bidiRunDirection = getBidiRunDirection(offsetToCheck)
-    val paragraphDirection = getParagraphDirection(offset)
-
-    return getHorizontalPosition(
-        offset = offset,
-        usePrimaryDirection = bidiRunDirection == paragraphDirection
-    )
-}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionMouseDetector.kt b/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionMouseDetector.kt
deleted file mode 100644
index 3931bc4..0000000
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/TextSelectionMouseDetector.kt
+++ /dev/null
@@ -1,135 +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.newtext.text.copypasta.selection
-
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.drag
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.pointer.AwaitPointerEventScope
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.PointerInputChange
-import androidx.compose.ui.input.pointer.PointerInputScope
-import androidx.compose.ui.input.pointer.PointerType
-import androidx.compose.ui.input.pointer.changedToDown
-import androidx.compose.ui.input.pointer.isPrimaryPressed
-import androidx.compose.ui.input.pointer.isShiftPressed
-import androidx.compose.ui.platform.ViewConfiguration
-import androidx.compose.ui.util.fastAll
-
-// * Without shift it starts the new selection from the scratch.
-// * With shift expand / shrink existed selection.
-// * Click sets start and end of the selection, but shift click only the end of
-// selection.
-// * The specific case of it when selection is collapsed, but the same logic is
-// applied for not collapsed selection too.
-internal interface MouseSelectionObserver {
-    // on start of shift click. if returns true event will be consumed
-    fun onExtend(downPosition: Offset): Boolean
-    // on drag after shift click. if returns true event will be consumed
-    fun onExtendDrag(dragPosition: Offset): Boolean
-
-    // if returns true event will be consumed
-    fun onStart(downPosition: Offset, adjustment: SelectionAdjustment): Boolean
-    fun onDrag(dragPosition: Offset, adjustment: SelectionAdjustment): Boolean
-}
-
-// Distance in pixels between consecutive click positions to be considered them as clicks sequence
-internal const val ClicksSlop = 100.0
-
-private class ClicksCounter(
-    private val viewConfiguration: ViewConfiguration
-) {
-    var clicks = 0
-    var prevClick: PointerInputChange? = null
-    fun update(event: PointerEvent) {
-        val currentPrevClick = prevClick
-        val newClick = event.changes[0]
-        if (currentPrevClick != null &&
-            timeIsTolerable(currentPrevClick, newClick) &&
-            positionIsTolerable(currentPrevClick, newClick)
-        ) {
-            clicks += 1
-        } else {
-            clicks = 1
-        }
-        prevClick = newClick
-    }
-
-    fun timeIsTolerable(prevClick: PointerInputChange, newClick: PointerInputChange): Boolean {
-        val diff = newClick.uptimeMillis - prevClick.uptimeMillis
-        return diff < viewConfiguration.doubleTapTimeoutMillis
-    }
-
-    fun positionIsTolerable(prevClick: PointerInputChange, newClick: PointerInputChange): Boolean {
-        val diff = newClick.position - prevClick.position
-        return diff.getDistance() < ClicksSlop
-    }
-}
-
-internal suspend fun PointerInputScope.mouseSelectionDetector(
-    observer: MouseSelectionObserver
-) {
-    awaitEachGesture {
-        val clicksCounter = ClicksCounter(viewConfiguration)
-        while (true) {
-            val down: PointerEvent = awaitMouseEventDown()
-            clicksCounter.update(down)
-            val downChange = down.changes[0]
-            if (down.keyboardModifiers.isShiftPressed) {
-                val started = observer.onExtend(downChange.position)
-                if (started) {
-                    downChange.consume()
-                    drag(downChange.id) {
-                        if (observer.onExtendDrag(it.position)) {
-                            it.consume()
-                        }
-                    }
-                }
-            } else {
-                val selectionMode = when (clicksCounter.clicks) {
-                    1 -> SelectionAdjustment.None
-                    2 -> SelectionAdjustment.Word
-                    else -> SelectionAdjustment.Paragraph
-                }
-                val started = observer.onStart(downChange.position, selectionMode)
-                if (started) {
-                    downChange.consume()
-                    drag(downChange.id) {
-                        if (observer.onDrag(it.position, selectionMode)) {
-                            it.consume()
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-private suspend fun AwaitPointerEventScope.awaitMouseEventDown(): PointerEvent {
-    var event: PointerEvent
-    do {
-        event = awaitPointerEvent(PointerEventPass.Main)
-    } while (
-        !(
-            event.buttons.isPrimaryPressed && event.changes.fastAll {
-                it.type == PointerType.Mouse && it.changedToDown()
-            }
-            )
-    )
-    return event
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt
deleted file mode 100644
index 86ddbd5..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/BasicContextMenuRepresentation.desktop.kt
+++ /dev/null
@@ -1,144 +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.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.getValue
-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.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(
-                focusable = true,
-                onDismissRequest = { state.status = ContextMenuState.Status.Closed },
-                popupPositionProvider = rememberCursorPositionProvider()
-            ) {
-                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)
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt
deleted file mode 100644
index 2a7fa89..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/ContextMenuProvider.desktop.kt
+++ /dev/null
@@ -1,259 +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
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.desktop.kt
deleted file mode 100644
index dcea9d1..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/ContextMenu.desktop.kt
+++ /dev/null
@@ -1,52 +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.newtext.text.copypasta
-
-import androidx.compose.foundation.ContextMenuItem
-import androidx.compose.foundation.ContextMenuState
-import androidx.compose.foundation.newtext.text.copypasta.selection.SelectionManager
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.geometry.Offset
-import kotlinx.coroutines.flow.collect
-
-@Composable
-internal actual fun ContextMenuArea(
-    manager: SelectionManager,
-    content: @Composable () -> Unit
-) {
-    /* noop*/
-}
-
-@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 SelectionManager.contextMenuItems(): () -> List<ContextMenuItem> {
-    return {
-        listOf()
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.desktop.kt
deleted file mode 100644
index 58ac4c9..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/StringHelpers.desktop.kt
+++ /dev/null
@@ -1,31 +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.newtext.text.copypasta
-
-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)
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.desktop.kt
deleted file mode 100644
index ff55d6d..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.desktop.kt
+++ /dev/null
@@ -1,23 +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.newtext.text.copypasta
-
-import androidx.compose.ui.input.pointer.PointerIcon
-import java.awt.Cursor
-
-internal actual val textPointerIcon: PointerIcon =
-    PointerIcon(Cursor(Cursor.TEXT_CURSOR))
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/DesktopSelectionHandles.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/DesktopSelectionHandles.desktop.kt
deleted file mode 100644
index c509e01..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/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.newtext.text.copypasta.selection
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.text.style.ResolvedTextDirection
-
-@Composable
-internal actual fun SelectionHandle(
-    position: Offset,
-    isStartHandle: Boolean,
-    direction: ResolvedTextDirection,
-    handlesCrossed: Boolean,
-    modifier: Modifier,
-    content: (@Composable () -> Unit)?
-) {
-    // TODO
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.desktop.kt b/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.desktop.kt
deleted file mode 100644
index a03574a..0000000
--- a/compose/foundation/foundation-newtext/src/desktopMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/selection/SelectionManager.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.foundation.newtext.text.copypasta.selection
-
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.key.KeyEvent
-
-// 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) = true
-
-/**
- * Magnification is not supported on desktop.
- */
-internal actual fun Modifier.selectionMagnifier(manager: SelectionManager): Modifier = this
diff --git a/compose/foundation/foundation-newtext/src/test/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt b/compose/foundation/foundation-newtext/src/test/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt
deleted file mode 100644
index 32ef628..0000000
--- a/compose/foundation/foundation-newtext/src/test/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.newtext.text.modifiers
-
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.unit.Density
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import org.mockito.kotlin.mock
-
-@RunWith(JUnit4::class)
-class MultiParagraphLayoutCacheTest {
-    private val density = Density(density = 1f)
-    private val fontFamilyResolver = mock<FontFamily.Resolver>()
-
-    @Test(expected = IllegalStateException::class)
-    fun whenMinInstrinsicWidth_withoutLayout_throws() {
-        val textDelegate = MultiParagraphLayoutCache(
-            text = AnnotatedString(""),
-            style = TextStyle.Default,
-            fontFamilyResolver = fontFamilyResolver
-        ).also {
-            it.density = density
-        }
-
-        textDelegate.minIntrinsicWidth
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun whenMaxIntrinsicWidth_withoutLayout_throws() {
-        val textDelegate = MultiParagraphLayoutCache(
-            text = AnnotatedString(""),
-            style = TextStyle.Default,
-            fontFamilyResolver = fontFamilyResolver
-        ).also {
-            it.density = density
-        }
-
-        textDelegate.maxIntrinsicWidth
-    }
-}
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index ade8b1a..97bb9ba 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -740,10 +740,13 @@
   }
 
   public final class BasicTextKt {
-    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
-    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
+    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated public static boolean getNewTextRendering1_5();
+    method @Deprecated public static void setNewTextRendering1_5(boolean);
+    property @Deprecated public static final boolean NewTextRendering1_5;
   }
 
   public final class ClickableTextKt {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 6d60e98..de3cc7c 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -1177,10 +1177,13 @@
   }
 
   public final class BasicTextKt {
-    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
-    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
+    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated public static boolean getNewTextRendering1_5();
+    method @Deprecated public static void setNewTextRendering1_5(boolean);
+    property @Deprecated public static final boolean NewTextRendering1_5;
   }
 
   public final class ClickableTextKt {
@@ -1276,3 +1279,27 @@
 
 }
 
+package androidx.compose.foundation.text2 {
+
+  public final class BasicTextField2Kt {
+    method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void BasicTextField2(androidx.compose.foundation.text2.TextFieldState state, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional androidx.compose.ui.graphics.Brush cursorBrush, optional int minLines, optional int maxLines, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.unit.Density,? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional kotlin.jvm.functions.Function1<? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> decorationBox);
+  }
+
+  @androidx.compose.foundation.ExperimentalFoundationApi public fun interface TextEditFilter {
+    method public androidx.compose.ui.text.input.TextFieldValue filter(androidx.compose.ui.text.input.TextFieldValue oldValue, androidx.compose.ui.text.input.TextFieldValue newValue);
+    field public static final androidx.compose.foundation.text2.TextEditFilter.Companion Companion;
+  }
+
+  public static final class TextEditFilter.Companion {
+    method public androidx.compose.foundation.text2.TextEditFilter getDefault();
+    property public final androidx.compose.foundation.text2.TextEditFilter Default;
+  }
+
+  @androidx.compose.foundation.ExperimentalFoundationApi public final class TextFieldState {
+    ctor public TextFieldState(optional androidx.compose.ui.text.input.TextFieldValue initialValue, optional androidx.compose.foundation.text2.TextEditFilter filter);
+    method public androidx.compose.ui.text.input.TextFieldValue getValue();
+    property public final androidx.compose.ui.text.input.TextFieldValue value;
+  }
+
+}
+
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index ade8b1a..97bb9ba 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -740,10 +740,13 @@
   }
 
   public final class BasicTextKt {
-    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
-    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
-    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines);
+    method @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(String text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines);
+    method @Deprecated @androidx.compose.runtime.Composable public static void BasicText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.text.TextStyle style, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit>? onTextLayout, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent);
+    method @Deprecated public static boolean getNewTextRendering1_5();
+    method @Deprecated public static void setNewTextRendering1_5(boolean);
+    property @Deprecated public static final boolean NewTextRendering1_5;
   }
 
   public final class ClickableTextKt {
diff --git a/compose/foundation/foundation/benchmark/build.gradle b/compose/foundation/foundation/benchmark/build.gradle
index 905f5b4..8a2d505 100644
--- a/compose/foundation/foundation/benchmark/build.gradle
+++ b/compose/foundation/foundation/benchmark/build.gradle
@@ -31,7 +31,6 @@
     androidTestImplementation project(":compose:ui:ui-text:ui-text-benchmark")
     androidTestImplementation project(":compose:foundation:foundation-layout")
     androidTestImplementation project(":compose:foundation:foundation")
-    androidTestImplementation project(":compose:foundation:foundation-do-not-ship-newtext")
     androidTestImplementation project(":compose:material:material")
     androidTestImplementation project(":compose:benchmark-utils")
     androidTestImplementation(libs.testRules)
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/EmpiricalBench.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/EmpiricalBench.kt
index a3d29f3..9c3951d 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/EmpiricalBench.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/EmpiricalBench.kt
@@ -16,12 +16,18 @@
 
 package androidx.compose.foundation.benchmark.text.empirical
 
+import androidx.compose.foundation.text.InlineTextContent
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
 import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkDraw
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkRecompose
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextStyle
 import org.junit.Rule
 import org.junit.Test
 
@@ -47,3 +53,27 @@
         benchmarkRule.toggleStateBenchmarkDraw(caseFactory)
     }
 }
+
+@Composable
+fun Subject(text: String, style: TextStyle) {
+    Text(text, style = style)
+}
+
+@Composable
+fun Subject(text: String, modifier: Modifier, style: TextStyle) {
+    Text(text, modifier, style = style)
+}
+
+@Composable
+fun Subject(text: AnnotatedString, style: TextStyle) {
+    Text(text, style = style)
+}
+
+@Composable
+fun Subject(
+    text: AnnotatedString,
+    style: TextStyle,
+    inlineContent: Map<String, InlineTextContent>
+) {
+    Text(text, style = style, inlineContent = inlineContent)
+}
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallText.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallText.kt
index 9e4a39e..38e6250 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallText.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallText.kt
@@ -17,7 +17,7 @@
 package androidx.compose.foundation.benchmark.text.empirical
 
 import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.foundation.text.BasicText
+import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
@@ -42,7 +42,7 @@
     @Composable
     override fun MeasuredContent() {
         if (toggleText.value.isNotEmpty()) {
-            BasicText(
+            Text(
                 toggleText.value,
                 style = style
             )
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallTextWithSpans.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallTextWithSpans.kt
index 2de260d..d37ba36 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallTextWithSpans.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/IfNotEmptyCallTextWithSpans.kt
@@ -17,12 +17,12 @@
 package androidx.compose.foundation.benchmark.text.empirical
 
 import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.test.filters.LargeTest
 import org.junit.Assume
@@ -49,9 +49,11 @@
 ) : LayeredComposeTestCase(), ToggleableTestCase {
     private var toggleText = mutableStateOf(AnnotatedString(""))
 
+    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
+
     @Composable
     override fun MeasuredContent() {
-        Text(toggleText.value, fontFamily = FontFamily.Monospace)
+        Subject(toggleText.value, style = style)
     }
 
     override fun toggleState() {
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierIfNotEmptyCallText.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierIfNotEmptyCallText.kt
deleted file mode 100644
index 153b285..0000000
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierIfNotEmptyCallText.kt
+++ /dev/null
@@ -1,114 +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.benchmark.text.empirical
-
-import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.foundation.newtext.text.TextUsingModifier
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.testutils.LayeredComposeTestCase
-import androidx.compose.testutils.ToggleableTestCase
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.test.filters.LargeTest
-import org.junit.Assume
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-/**
- * Toggle between missing Text and Text("aaa..") to simulate backend text loading.
- *
- * This intentionally hits as many text caches as possible, to isolate compose setText behavior.
- */
-@OptIn(ExperimentalTextApi::class)
-class ModifierIfNotEmptyCallText(
-    private val text: String
-) : LayeredComposeTestCase(), ToggleableTestCase {
-    private var toggleText = mutableStateOf("")
-
-    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
-
-    @Composable
-    override fun MeasuredContent() {
-        if (toggleText.value.isNotEmpty()) {
-            TextUsingModifier(
-                text = toggleText.value,
-                style = style
-            )
-        }
-    }
-
-    override fun toggleState() {
-        if (toggleText.value == "") {
-            toggleText.value = text
-        } else {
-            toggleText.value = ""
-        }
-    }
-}
-
-@LargeTest
-@RunWith(Parameterized::class)
-open class ModifierIfNotEmptyParent(
-    private val size: Int
-) : EmpiricalBench<ModifierIfNotEmptyCallText>() {
-
-    override val caseFactory = {
-        val text = generateCacheableStringOf(size)
-        ModifierIfNotEmptyCallText(text)
-    }
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = arrayOf()
-    }
-}
-
-/**
- * Metrics determined from all apps
- */
-@LargeTest
-@RunWith(Parameterized::class)
-class ModifierAllAppsIfNotEmptyCallText(size: Int) : ModifierIfNotEmptyParent(size) {
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = AllApps.TextLengths
-    }
-}
-
-/**
- * Metrics for Chat-like apps.
- *
- * These apps typically have more longer strings, due to user generated content.
- */
-@LargeTest
-@RunWith(Parameterized::class)
-class ModifierChatAppIfNotEmptyCallText(size: Int) : ModifierIfNotEmptyParent(size) {
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = ChatApps.TextLengths
-    }
-
-    init {
-        // we only need this for full reporting
-        Assume.assumeTrue(DoFullBenchmark)
-    }
-}
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierSetText.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierSetText.kt
deleted file mode 100644
index 0542cf5..0000000
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/ModifierSetText.kt
+++ /dev/null
@@ -1,109 +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.benchmark.text.empirical
-
-import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.foundation.newtext.text.TextUsingModifier
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.testutils.LayeredComposeTestCase
-import androidx.compose.testutils.ToggleableTestCase
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.test.filters.LargeTest
-import org.junit.Assume
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-/**
- * Toggle between "" and "aaaa..." to simulate backend text loading.
- *
- * This intentionally hits as many text caches as possible, to isolate compose setText behavior.
- */
-class ModifierSetText(private val text: String) : LayeredComposeTestCase(), ToggleableTestCase {
-    private val toggleText = mutableStateOf("")
-
-    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
-
-    @OptIn(ExperimentalTextApi::class)
-    @Composable
-    override fun MeasuredContent() {
-        TextUsingModifier(
-            toggleText.value,
-            style = style
-        )
-    }
-
-    override fun toggleState() {
-        if (toggleText.value == "") {
-            toggleText.value = text
-        } else {
-            toggleText.value = ""
-        }
-    }
-}
-
-@LargeTest
-@RunWith(Parameterized::class)
-open class ModifierSetTextParent(
-    private val size: Int
-) : EmpiricalBench<ModifierSetText>() {
-    override val caseFactory = {
-        val text = generateCacheableStringOf(size)
-        ModifierSetText(text)
-    }
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = arrayOf()
-    }
-}
-
-/**
- * Metrics determined from all apps
- */
-@LargeTest
-@RunWith(Parameterized::class)
-class ModifierAllAppsSetText(size: Int) : ModifierSetTextParent(size) {
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = AllApps.TextLengths
-    }
-}
-
-/**
- * Metrics for Chat-like apps.
- *
- * These apps typically have more longer strings, due to user generated content.
- */
-@LargeTest
-@RunWith(Parameterized::class)
-class ModifierChatAppSetText(size: Int) : ModifierSetTextParent(size) {
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "size={0}")
-        fun initParameters(): Array<Any> = ChatApps.TextLengths
-    }
-
-    init {
-        // we only need this for full reporting
-        Assume.assumeTrue(DoFullBenchmark)
-    }
-}
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetText.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetText.kt
index 2b1d49d..845e473 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetText.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetText.kt
@@ -17,7 +17,6 @@
 package androidx.compose.foundation.benchmark.text.empirical
 
 import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
@@ -41,7 +40,7 @@
 
     @Composable
     override fun MeasuredContent() {
-        BasicText(
+        Subject(
             toggleText.value,
             style = style
         )
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextFillMaxWidth.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextFillMaxWidth.kt
index f64c74c..60f2d14 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextFillMaxWidth.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextFillMaxWidth.kt
@@ -18,12 +18,12 @@
 
 import androidx.compose.foundation.benchmark.text.DoFullBenchmark
 import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.test.filters.LargeTest
 import org.junit.Assume
@@ -40,12 +40,14 @@
 class SetTextFillMaxWidth(private val text: String) : LayeredComposeTestCase(), ToggleableTestCase {
     private var toggleText = mutableStateOf("")
 
+    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
+
     @Composable
     override fun MeasuredContent() {
-        Text(
+        Subject(
             toggleText.value,
             modifier = Modifier.fillMaxWidth(),
-            fontFamily = FontFamily.Monospace
+            style = style
         )
     }
 
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithInlineContent.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithInlineContent.kt
index a157190..4916430 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithInlineContent.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithInlineContent.kt
@@ -20,7 +20,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.text.InlineTextContent
-import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
@@ -29,6 +28,7 @@
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.Placeholder
 import androidx.compose.ui.text.PlaceholderVerticalAlign
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
@@ -49,10 +49,12 @@
 ) : LayeredComposeTestCase(), ToggleableTestCase {
     private var toggleText = mutableStateOf(AnnotatedString(""))
 
+    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
+
     @Composable
     override fun MeasuredContent() {
-        Text(toggleText.value,
-            fontFamily = FontFamily.Monospace,
+        Subject(toggleText.value,
+            style = style,
             inlineContent = mapOf(
                 BenchmarkInlineContentId to InlineTextContent(
                     Placeholder(12.sp, 12.sp, PlaceholderVerticalAlign.Center)
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithSpans.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithSpans.kt
index 13c3962..bf8d216 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithSpans.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/SetTextWithSpans.kt
@@ -17,12 +17,12 @@
 package androidx.compose.foundation.benchmark.text.empirical
 
 import androidx.compose.foundation.benchmark.text.DoFullBenchmark
-import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.test.filters.LargeTest
 import org.junit.Assume.assumeTrue
@@ -49,9 +49,11 @@
 ) : LayeredComposeTestCase(), ToggleableTestCase {
     private var toggleText = mutableStateOf(AnnotatedString(""))
 
+    private val style = TextStyle.Default.copy(fontFamily = FontFamily.Monospace)
+
     @Composable
     override fun MeasuredContent() {
-        Text(toggleText.value, fontFamily = FontFamily.Monospace)
+        Subject(toggleText.value, style = style)
     }
 
     override fun toggleState() {
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/baselines/StaticLayoutBaseline.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/baselines/StaticLayoutBaseline.kt
index 0ab85a3..4e3cd87 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/baselines/StaticLayoutBaseline.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/empirical/baselines/StaticLayoutBaseline.kt
@@ -72,6 +72,9 @@
                 isEmpty = !isEmpty
                 if (isEmpty) "" else text
             }
+            // measure requires this in typical cases
+            Layout.getDesiredWidth(measureText, textPaint)
+            // paint requires this in all cases
             val layout = makeStaticLayout(measureText, textPaint)
             layout.draw(canvas)
         }
diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle
index 3c6a103..6950856 100644
--- a/compose/foundation/foundation/build.gradle
+++ b/compose/foundation/foundation/build.gradle
@@ -42,6 +42,7 @@
         implementation(libs.kotlinStdlibCommon)
         implementation(project(":compose:foundation:foundation-layout"))
         implementation(project(':emoji2:emoji2'))
+        implementation("androidx.core:core:1.9.0")
         implementation("androidx.compose.ui:ui-graphics:1.2.1")
         implementation("androidx.compose.ui:ui-text:1.2.1")
         implementation("androidx.compose.ui:ui-util:1.2.1")
@@ -66,7 +67,6 @@
         androidTestImplementation(libs.testRunner)
         androidTestImplementation(libs.testMonitor)
         androidTestImplementation "androidx.activity:activity-compose:1.3.1"
-        androidTestImplementation("androidx.core:core:1.9.0")
         androidTestImplementation(libs.espressoCore)
         androidTestImplementation(libs.junit)
         androidTestImplementation(libs.kotlinTest)
@@ -106,6 +106,7 @@
             androidMain.dependencies {
                 api("androidx.annotation:annotation:1.1.0")
                 implementation(project(':emoji2:emoji2'))
+                implementation("androidx.core:core:1.9.0")
             }
 
             desktopMain.dependencies {
@@ -137,7 +138,6 @@
                 implementation(project(":test:screenshot:screenshot"))
                 implementation(project(":internal-testutils-runtime"))
                 implementation("androidx.activity:activity-compose:1.3.1")
-                implementation("androidx.core:core:1.9.0")
 
                 implementation(libs.testUiautomator)
                 implementation(libs.testRules)
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/build.gradle b/compose/foundation/foundation/integration-tests/foundation-demos/build.gradle
index 2692883..4382106 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/build.gradle
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/build.gradle
@@ -40,24 +40,6 @@
     implementation(project(":compose:ui:ui-tooling-preview"))
     debugImplementation(project(":compose:ui:ui-tooling"))
     implementation(project(":internal-testutils-fonts"))
-
-    testImplementation(project(":compose:test-utils"))
-    testImplementation(libs.testRules)
-    testImplementation(libs.testRunner)
-    testImplementation(libs.junit)
-    testImplementation(libs.truth)
-    testImplementation(libs.kotlinTest)
-    testImplementation(libs.mockitoCore4)
-    testImplementation(libs.kotlinReflect)
-    testImplementation(libs.mockitoKotlin4)
-
-    androidTestImplementation(project(":compose:test-utils"))
-    androidTestImplementation(libs.testRules)
-    androidTestImplementation(libs.testRunner)
-    androidTestImplementation(libs.junit)
-    androidTestImplementation(libs.kotlinTest)
-    androidTestImplementation(libs.truth)
-    androidTestImplementation(libs.espressoCore)
 }
 
 android {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt
deleted file mode 100644
index 1d195c9..0000000
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt
+++ /dev/null
@@ -1,123 +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.text2.service
-
-import android.text.InputType
-import android.view.inputmethod.EditorInfo
-import androidx.compose.foundation.text2.TextFieldState
-import androidx.compose.ui.platform.LocalPlatformTextInputPluginRegistry
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class AndroidTextInputAdapterTest {
-
-    @get:Rule
-    val rule = createComposeRule()
-
-    private lateinit var adapter: AndroidTextInputAdapter
-
-    @Before
-    @OptIn(ExperimentalTextApi::class)
-    fun setup() {
-        rule.setContent {
-            val adapterProvider = LocalPlatformTextInputPluginRegistry.current
-            adapter = adapterProvider.rememberAdapter(AndroidTextInputPlugin)
-        }
-    }
-
-    @Test
-    fun startInputSession_returnsOpenSession() {
-        val state = TextFieldState()
-        rule.runOnUiThread {
-            val session = adapter.startInputSession(state)
-            assertThat(session.isOpen).isTrue()
-        }
-    }
-
-    @Test
-    fun disposedSession_returnsClosed() {
-        val state = TextFieldState()
-        rule.runOnUiThread {
-            val session = adapter.startInputSession(state)
-            session.dispose()
-            assertThat(session.isOpen).isFalse()
-        }
-    }
-
-    @Test(expected = IllegalStateException::class)
-    fun startingInputSessionOnNonMainThread_throwsIllegalStateException() {
-        adapter.startInputSession(TextFieldState())
-    }
-
-    @Test
-    fun creatingSecondInputSession_closesFirstOne() {
-        val state = TextFieldState()
-        rule.runOnUiThread {
-            val session1 = adapter.startInputSession(state)
-            val session2 = adapter.startInputSession(state)
-
-            assertThat(session1.isOpen).isFalse()
-            assertThat(session2.isOpen).isTrue()
-        }
-    }
-
-    // TODO: split into multiple tests when ImeOptions are added
-    @Test
-    fun createInputConnection_modifiesEditorInfo() {
-        val state = TextFieldState(TextFieldValue("hello", selection = TextRange(0, 5)))
-        rule.runOnUiThread {
-            adapter.startInputSession(state)
-            val editorInfo = EditorInfo()
-            adapter.createInputConnection(editorInfo)
-
-            assertThat(editorInfo.initialSelStart).isEqualTo(0)
-            assertThat(editorInfo.initialSelEnd).isEqualTo(5)
-            assertThat(editorInfo.inputType).isEqualTo(InputType.TYPE_CLASS_TEXT)
-            assertThat(editorInfo.imeOptions).isEqualTo(
-                EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
-            )
-        }
-    }
-
-    @Test
-    fun inputConnection_sendsUpdates_toActiveSession() {
-        val state1 = TextFieldState()
-        val state2 = TextFieldState()
-        rule.runOnUiThread {
-            adapter.startInputSession(state1)
-            adapter.startInputSession(state2)
-
-            val connection = adapter.createInputConnection(EditorInfo())
-
-            connection.commitText("Hello", 0)
-
-            assertThat(state1.value.text).isEqualTo("")
-            assertThat(state2.value.text).isEqualTo("Hello")
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt
index 95eb56d..1702e47 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt
@@ -17,6 +17,8 @@
 package androidx.compose.foundation.demos.text
 
 import androidx.compose.foundation.demos.text2.BasicTextField2Demos
+import androidx.compose.foundation.demos.text2.DecorationBoxDemos
+import androidx.compose.foundation.demos.text2.KeyboardOptionsDemos
 import androidx.compose.integration.demos.common.ComposableDemo
 import androidx.compose.integration.demos.common.DemoCategory
 
@@ -120,6 +122,12 @@
             listOf(
                 ComposableDemo("Basic text input") {
                     BasicTextField2Demos()
+                },
+                ComposableDemo("Keyboard Options") {
+                    KeyboardOptionsDemos()
+                },
+                ComposableDemo("Decoration Box") {
+                    DecorationBoxDemos()
                 }
             )
         ),
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/BasicTextField2Demos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/BasicTextField2Demos.kt
index 44d5663..dbb09d8 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/BasicTextField2Demos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/BasicTextField2Demos.kt
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalFoundationApi::class)
+
 package androidx.compose.foundation.demos.text2
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.demos.text.TagLine
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.text2.BasicTextField2
 import androidx.compose.foundation.text2.TextFieldState
 import androidx.compose.material.LocalTextStyle
@@ -49,7 +51,7 @@
 @Composable
 fun PlainBasicTextField2() {
     val state = remember { TextFieldState() }
-    BasicTextField2(state, Modifier.fillMaxWidth(), textStyle = LocalTextStyle.current)
+    BasicTextField2(state, demoTextFieldModifiers, textStyle = LocalTextStyle.current)
 }
 
 @Composable
@@ -62,7 +64,7 @@
         counter %= 2
     })
 
-    BasicTextField2(state, Modifier.fillMaxWidth(), textStyle = LocalTextStyle.current)
+    BasicTextField2(state, demoTextFieldModifiers, textStyle = LocalTextStyle.current)
 }
 
 @Composable
@@ -72,5 +74,5 @@
             if (new.text.isDigitsOnly()) new else old
         }
     }
-    BasicTextField2(state, Modifier.fillMaxWidth(), textStyle = LocalTextStyle.current)
+    BasicTextField2(state, demoTextFieldModifiers, textStyle = LocalTextStyle.current)
 }
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/DecorationBoxDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/DecorationBoxDemos.kt
new file mode 100644
index 0000000..84e7cfe
--- /dev/null
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/DecorationBoxDemos.kt
@@ -0,0 +1,67 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
+
+package androidx.compose.foundation.demos.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.demos.text.TagLine
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.text2.BasicTextField2
+import androidx.compose.foundation.text2.TextFieldState
+import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.material.LocalTextStyle
+import androidx.compose.material.TextFieldDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.input.VisualTransformation
+
+@Composable
+fun DecorationBoxDemos() {
+    Column {
+        TagLine(tag = "OutlinedTextField")
+        OutlinedBasicTextField2()
+    }
+}
+
+@Composable
+fun OutlinedBasicTextField2() {
+    val state = remember { TextFieldState() }
+    BasicTextField2(
+        state = state,
+        modifier = Modifier,
+        textStyle = LocalTextStyle.current,
+        decorationBox = @Composable {
+            TextFieldDefaults.OutlinedTextFieldDecorationBox(
+                value = state.value.text,
+                visualTransformation = VisualTransformation.None,
+                innerTextField = it,
+                placeholder = null,
+                label = null,
+                leadingIcon = null,
+                trailingIcon = null,
+                singleLine = true,
+                enabled = true,
+                isError = false,
+                interactionSource = remember { MutableInteractionSource() },
+                colors = TextFieldDefaults.outlinedTextFieldColors()
+            )
+        }
+    )
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/KeyboardOptionsDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/KeyboardOptionsDemos.kt
new file mode 100644
index 0000000..577711fa
--- /dev/null
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text2/KeyboardOptionsDemos.kt
@@ -0,0 +1,86 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.demos.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.border
+import androidx.compose.foundation.demos.text.TagLine
+import androidx.compose.foundation.demos.text.fontSize8
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.text2.BasicTextField2
+import androidx.compose.foundation.text2.TextFieldState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+
+@Preview
+@Composable
+fun KeyboardOptionsDemos() {
+    LazyColumn {
+        item { Item(KeyboardType.Text) }
+        item { Item(KeyboardType.Ascii) }
+        item { Item(KeyboardType.Number) }
+        item { Item(KeyboardType.Phone) }
+        item { Item(KeyboardType.Uri) }
+        item { Item(KeyboardType.Email) }
+        item { Item(KeyboardType.Password) }
+        item { Item(KeyboardType.NumberPassword) }
+    }
+}
+
+@Composable
+private fun Item(keyboardType: KeyboardType) {
+    TagLine(tag = "Keyboard Type: $keyboardType")
+    EditLine(keyboardType = keyboardType)
+}
+
+@Composable
+private fun EditLine(
+    keyboardType: KeyboardType = KeyboardType.Text,
+    imeAction: ImeAction = ImeAction.Default,
+    text: String = ""
+) {
+    val state = remember { TextFieldState(TextFieldValue(text)) }
+    BasicTextField2(
+        modifier = demoTextFieldModifiers,
+        state = state,
+        keyboardOptions = KeyboardOptions(
+            keyboardType = keyboardType,
+            imeAction = imeAction
+        ),
+        textStyle = TextStyle(fontSize = fontSize8),
+    )
+}
+
+val demoTextFieldModifiers = Modifier
+    .fillMaxWidth()
+    .padding(6.dp)
+    .border(1.dp, Color.LightGray, RoundedCornerShape(6.dp))
+    .padding(6.dp)
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/BasicTextField2.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/BasicTextField2.kt
deleted file mode 100644
index c93b842..0000000
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/BasicTextField2.kt
+++ /dev/null
@@ -1,359 +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.text2
-
-import androidx.compose.animation.core.animateFloatAsState
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.border
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.focusable
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.relocation.BringIntoViewRequester
-import androidx.compose.foundation.text.selection.LocalTextSelectionColors
-import androidx.compose.foundation.text2.service.AndroidTextInputPlugin
-import androidx.compose.foundation.text2.service.TextInputSession
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
-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.runtime.snapshots.Snapshot
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.layout.FirstBaseline
-import androidx.compose.ui.layout.LastBaseline
-import androidx.compose.ui.layout.Layout
-import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalFontFamilyResolver
-import androidx.compose.ui.platform.LocalPlatformTextInputPluginRegistry
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.Paragraph
-import androidx.compose.ui.text.Placeholder
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextMeasurer
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.drawText
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.rememberTextMeasurer
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import kotlin.math.ceil
-import kotlin.math.roundToInt
-import kotlinx.coroutines.launch
-
-/**
- * @param enabled controls the enabled state of the text field. When `false`, the text
- * field will be neither editable nor focusable, the input of the text field will not be selectable
- */
-@OptIn(
-    ExperimentalTextApi::class,
-    ExperimentalFoundationApi::class
-)
-@Composable
-fun BasicTextField2(
-    state: TextFieldState,
-    modifier: Modifier = Modifier,
-    textStyle: TextStyle = TextStyle.Default,
-    enabled: Boolean = true,
-    interactionSource: MutableInteractionSource? = null,
-    onTextLayout: (TextLayoutResult) -> Unit = {}
-) {
-    val textInputAdapter = LocalPlatformTextInputPluginRegistry.current
-        .rememberAdapter(AndroidTextInputPlugin)
-    val focusRequester = remember { FocusRequester() }
-
-    // Caching is not useful for dynamic content. We keep cache for a single layout when the
-    // content is not edited but layout phase still occurs.
-    // b/261581753
-    val textMeasurer = rememberTextMeasurer(cacheSize = 1)
-    val scope = rememberCoroutineScope()
-    val fontFamilyResolver = LocalFontFamilyResolver.current
-    val density = LocalDensity.current
-    val bringIntoViewRequester = remember { BringIntoViewRequester() }
-
-    val textLayoutState = remember {
-        TextLayoutState(
-            TextMeasureParams(
-                text = state.value.annotatedString,
-                style = textStyle,
-                density = density,
-                fontFamilyResolver = fontFamilyResolver,
-                softWrap = true,
-                placeholders = emptyList()
-            )
-        )
-    }
-
-    textLayoutState.updateParams(
-        visualText = state.value.annotatedString,
-        textStyle = textStyle,
-        softWrap = true,
-        density = density,
-        fontFamilyResolver = fontFamilyResolver
-    )
-
-    var isFocused by remember { mutableStateOf(false) }
-    val borderWidth by animateFloatAsState(targetValue = if (isFocused) 2f else 0f)
-
-    val textInputSessionState = remember { mutableStateOf<TextInputSession?>(null) }
-
-    DisposableEffect(state) {
-        // restart input if it's active
-        val textInputSession = textInputSessionState.value
-        if (textInputSession != null) {
-            textInputSession.dispose()
-            if (isFocused) {
-                textInputSessionState.value = textInputAdapter.startInputSession(state)
-            }
-        }
-        onDispose { }
-    }
-
-    val drawModifier = Modifier.drawBehind {
-        textLayoutState.layoutResult?.let { layoutResult ->
-            // TODO: draw selection
-            drawText(layoutResult)
-        }
-    }
-
-    val focusModifier = Modifier
-        .focusRequester(focusRequester)
-        .onFocusChanged {
-            if (isFocused == it.isFocused) {
-                return@onFocusChanged
-            }
-            isFocused = it.isFocused
-
-            if (it.isFocused) {
-                textInputSessionState.value = textInputAdapter.startInputSession(state)
-            }
-
-            // The focusable modifier itself will request the entire focusable be brought into view
-            // when it gains focus – in this case, that's the decoration box. However, since text
-            // fields may have their own internal scrolling, and the decoration box can do anything,
-            // we also need to specifically request that the cursor itself be brought into view.
-            // TODO(b/216790855) If this request happens after the focusable's request, the field
-            //  will only be scrolled far enough to show the cursor, _not_ the entire decoration
-            //  box.
-            if (it.isFocused) {
-                textLayoutState.layoutResult?.let { layoutResult ->
-                    scope.launch {
-                        val selectionEnd = state.value.selection.max
-                        val selectionEndBounds = when {
-                            selectionEnd < layoutResult.layoutInput.text.length -> {
-                                layoutResult.getBoundingBox(selectionEnd)
-                            }
-
-                            selectionEnd != 0 -> {
-                                layoutResult.getBoundingBox(selectionEnd - 1)
-                            }
-
-                            else -> { // empty text.
-                                val defaultSize = computeSizeForDefaultText(
-                                    textLayoutState.textMeasureParams.style,
-                                    textLayoutState.textMeasureParams.density,
-                                    textLayoutState.textMeasureParams.fontFamilyResolver
-                                )
-                                Rect(0f, 0f, 1.0f, defaultSize.height.toFloat())
-                            }
-                        }
-                        bringIntoViewRequester.bringIntoView(selectionEndBounds)
-                    }
-                }
-            } else {
-                state.deselect()
-            }
-        }
-        .focusable(interactionSource = interactionSource, enabled = enabled)
-
-    Layout(
-        content = {},
-        modifier = modifier
-            .then(focusModifier)
-            .then(drawModifier)
-            .clickable { focusRequester.requestFocus() }
-            .border(
-                width = borderWidth.dp,
-                color = LocalTextSelectionColors.current.backgroundColor
-            )
-    ) { _, constraints ->
-        val result = with(textLayoutState) { layout(textMeasurer, constraints, onTextLayout) }
-
-        // TODO: min height
-
-        layout(
-            width = result.size.width,
-            height = result.size.height,
-            alignmentLines = mapOf(
-                FirstBaseline to result.firstBaseline.roundToInt(),
-                LastBaseline to result.lastBaseline.roundToInt()
-            )
-        ) {}
-    }
-}
-
-@OptIn(ExperimentalTextApi::class)
-internal class TextLayoutState(
-    initialTextMeasureParams: TextMeasureParams
-) {
-    /**
-     * Set of parameters to compute text layout.
-     */
-    var textMeasureParams: TextMeasureParams by mutableStateOf(initialTextMeasureParams)
-        private set
-
-    /**
-     * TextFieldState holds both TextDelegate and layout result. However, these two values are not
-     * updated at the same time. TextDelegate is updated during composition according to new
-     * arguments while layoutResult is updated during layout phase. Therefore, [layoutResult] might
-     * not indicate the layout calculated from [textMeasureParams] at a given time during
-     * composition. This variable tells whether layout result is in sync with the latest
-     * [TextMeasureParams].
-     */
-    private var isLayoutResultStale: Boolean = true
-
-    var layoutResult: TextLayoutResult? by mutableStateOf(null)
-        private set
-
-    fun updateParams(
-        visualText: AnnotatedString,
-        textStyle: TextStyle,
-        softWrap: Boolean,
-        density: Density,
-        fontFamilyResolver: FontFamily.Resolver
-    ) {
-        if (!textMeasureParams.layoutCompatible(
-                text = visualText,
-                style = textStyle,
-                softWrap = softWrap,
-                density = density,
-                fontFamilyResolver = fontFamilyResolver,
-                placeholders = emptyList()
-        )) {
-            val newTextMeasureParams = TextMeasureParams(
-                text = visualText,
-                style = textStyle,
-                softWrap = softWrap,
-                density = density,
-                fontFamilyResolver = fontFamilyResolver,
-                placeholders = emptyList(),
-            )
-            isLayoutResultStale = true
-            textMeasureParams = newTextMeasureParams
-        }
-    }
-
-    fun MeasureScope.layout(
-        textMeasurer: TextMeasurer,
-        constraints: Constraints,
-        onTextLayout: (TextLayoutResult) -> Unit
-    ): TextLayoutResult {
-        val prevResult = Snapshot.withoutReadObservation { layoutResult }
-        val result = if (isLayoutResultStale || prevResult == null) {
-            textMeasurer.measure(
-                text = textMeasureParams.text,
-                style = textMeasureParams.style,
-                softWrap = textMeasureParams.softWrap,
-                density = this,
-                fontFamilyResolver = textMeasureParams.fontFamilyResolver,
-                layoutDirection = layoutDirection,
-                constraints = constraints
-            ).also {
-                layoutResult = it
-                isLayoutResultStale = false
-                onTextLayout(it)
-            }
-        } else {
-            prevResult
-        }
-        return result
-    }
-}
-
-internal data class TextMeasureParams(
-    val text: AnnotatedString,
-    val style: TextStyle,
-    val softWrap: Boolean,
-    val density: Density,
-    val fontFamilyResolver: FontFamily.Resolver,
-    val placeholders: List<Placeholder>
-) {
-    /**
-     * Returns whether given parameters and values in this [TextMeasureParams] would create the same
-     * layout or they are layout incompatible.
-     */
-    fun layoutCompatible(
-        text: AnnotatedString,
-        style: TextStyle,
-        softWrap: Boolean,
-        density: Density,
-        fontFamilyResolver: FontFamily.Resolver,
-        placeholders: List<Placeholder>
-    ): Boolean {
-        return this.text == text &&
-            this.style.hasSameLayoutAffectingAttributes(style) &&
-            this.softWrap == softWrap &&
-            this.density == density &&
-            this.fontFamilyResolver == fontFamilyResolver &&
-            this.placeholders == placeholders
-    }
-}
-
-/**
- * Computed the default width and height for TextField.
- *
- * The bounding box or x-advance of the empty text is empty, i.e. 0x0 box or 0px advance. However
- * this is not useful for TextField since text field want to reserve some amount of height for
- * accepting touch for starting text input. In Android, uses FontMetrics of the first font in the
- * fallback chain to compute this height, this is because custom font may have different
- * ascender/descender from the default font in Android.
- *
- * Until we have font metrics APIs, use the height of reference text as a workaround.
- */
-internal fun computeSizeForDefaultText(
-    style: TextStyle,
-    density: Density,
-    fontFamilyResolver: FontFamily.Resolver,
-    text: String = EmptyTextReplacement,
-    maxLines: Int = 1
-): IntSize {
-    val paragraph = Paragraph(
-        text = text,
-        style = style,
-        spanStyles = listOf(),
-        maxLines = maxLines,
-        ellipsis = false,
-        density = density,
-        fontFamilyResolver = fontFamilyResolver,
-        constraints = Constraints()
-    )
-    return IntSize(paragraph.minIntrinsicWidth.ceilToIntPx(), paragraph.height.ceilToIntPx())
-}
-
-internal fun Float.ceilToIntPx(): Int = ceil(this).roundToInt()
-internal const val DefaultWidthCharCount = 10 // min width for TextField is 10 chars long
-internal val EmptyTextReplacement = "H".repeat(DefaultWidthCharCount) // just a reference character.
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/compose/foundation/foundation/integration-tests/foundation-demos/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index 1f0955d..0000000
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/HoverableTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/HoverableTest.kt
index 634b442..3b480d2 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/HoverableTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/HoverableTest.kt
@@ -42,7 +42,6 @@
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 import org.junit.After
 import org.junit.Before
@@ -77,10 +76,7 @@
             Truth.assertThat(modifier.nameFallback).isEqualTo("hoverable")
             Truth.assertThat(modifier.valueOverride).isNull()
             Truth.assertThat(modifier.inspectableElements.map { it.name }.asIterable())
-                .containsExactly(
-                    "interactionSource",
-                    "enabled",
-                )
+                .containsExactly("interactionSource")
         }
     }
 
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextLayoutTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextLayoutTest.kt
index f6ea83a..0479889 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextLayoutTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextLayoutTest.kt
@@ -108,6 +108,9 @@
                         measurables: List<Measurable>,
                         constraints: Constraints
                     ): MeasureResult {
+                        measurables.forEach {
+                            it.measure(constraints)
+                        }
                         textMeasurable = measurables.first()
                         return layout(0, 0) {}
                     }
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifierMinMaxLinesTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextUsingModifierMinMaxLinesTest.kt
similarity index 96%
rename from compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifierMinMaxLinesTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextUsingModifierMinMaxLinesTest.kt
index a0b14c5..adb2098 100644
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifierMinMaxLinesTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/TextUsingModifierMinMaxLinesTest.kt
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text
+package androidx.compose.foundation.text
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.width
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.IntSize
@@ -33,7 +32,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@OptIn(ExperimentalTextApi::class)
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class TextUsingModifierMinMaxLinesTest {
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/BasicTextSemanticsTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/BasicTextSemanticsTest.kt
similarity index 87%
rename from compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/BasicTextSemanticsTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/BasicTextSemanticsTest.kt
index 8c70d21..8ea3136 100644
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/BasicTextSemanticsTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/BasicTextSemanticsTest.kt
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.TextUsingModifier
+import androidx.compose.foundation.text.TextUsingModifier
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import org.junit.Rule
@@ -37,7 +36,6 @@
     @get:Rule
     val rule = createComposeRule()
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun semanticsTextChanges_String() {
         var text by mutableStateOf("before")
@@ -49,7 +47,6 @@
         rule.onNodeWithText("after").assertExists()
     }
 
-    @OptIn(ExperimentalTextApi::class)
     @Test
     fun semanticsTextChanges_AnnotatedString() {
         var text by mutableStateOf("before")
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheTest.kt
similarity index 88%
rename from compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheTest.kt
index 471b37e..b411547 100644
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheTest.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.TEST_FONT_FAMILY
-import androidx.compose.foundation.newtext.text.toIntPx
+import androidx.compose.foundation.text.TEST_FONT_FAMILY
+import androidx.compose.foundation.text.toIntPx
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
@@ -61,7 +61,7 @@
 
             textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
 
-            assertThat(textDelegate.minIntrinsicWidth)
+            assertThat(textDelegate.minIntrinsicWidth(LayoutDirection.Ltr))
                 .isEqualTo((fontSize.toPx() * text.length).toIntPx())
         }
     }
@@ -83,7 +83,7 @@
 
             textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
 
-            assertThat(textDelegate.maxIntrinsicWidth)
+            assertThat(textDelegate.maxIntrinsicWidth(LayoutDirection.Ltr))
                 .isEqualTo((fontSize.toPx() * text.length).toIntPx())
         }
     }
@@ -103,7 +103,7 @@
 
         val constraintsFirstLayout = Constraints.fixed(width, heightFirstLayout)
         textDelegate.layoutWithConstraints(constraintsFirstLayout, LayoutDirection.Ltr)
-        val resultFirstLayout = textDelegate.layout
+        val resultFirstLayout = textDelegate.textLayoutResult
         assertThat(resultFirstLayout.layoutInput.constraints).isEqualTo(constraintsFirstLayout)
 
         val constraintsSecondLayout = Constraints.fixed(width, heightSecondLayout)
@@ -111,7 +111,7 @@
             constraintsSecondLayout,
             LayoutDirection.Ltr
         )
-        val resultSecondLayout = textDelegate.layout
+        val resultSecondLayout = textDelegate.textLayoutResult
         assertThat(resultSecondLayout.layoutInput.constraints).isEqualTo(constraintsSecondLayout)
     }
 
@@ -130,7 +130,7 @@
 
         val constraintsFirstLayout = Constraints.fixed(width, heightFirstLayout)
         textDelegate.layoutWithConstraints(constraintsFirstLayout, LayoutDirection.Ltr)
-        val resultFirstLayout = textDelegate.layout
+        val resultFirstLayout = textDelegate.textLayoutResult
         assertThat(resultFirstLayout.size.height).isEqualTo(heightFirstLayout)
 
         val constraintsSecondLayout = Constraints.fixed(width, heightSecondLayout)
@@ -138,7 +138,7 @@
             constraintsSecondLayout,
             LayoutDirection.Ltr
         )
-        val resultSecondLayout = textDelegate.layout
+        val resultSecondLayout = textDelegate.textLayoutResult
         assertThat(resultSecondLayout.size.height).isEqualTo(heightSecondLayout)
     }
 
@@ -158,10 +158,10 @@
 
         textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
         // Makes width smaller than needed.
-        val width = textDelegate.maxIntrinsicWidth / 2
+        val width = textDelegate.maxIntrinsicWidth(LayoutDirection.Ltr) / 2
         val constraints = Constraints(maxWidth = width)
         textDelegate.layoutWithConstraints(constraints, LayoutDirection.Ltr)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.lineCount).isEqualTo(1)
         assertThat(layoutResult.isLineEllipsized(0)).isTrue()
@@ -182,11 +182,11 @@
         }
         textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
         val constraints = Constraints(
-            maxWidth = textDelegate.maxIntrinsicWidth / 4,
+            maxWidth = textDelegate.maxIntrinsicWidth(LayoutDirection.Ltr) / 4,
             maxHeight = (fontSize * 2.7).roundToInt() // fully fits at most 2 lines
         )
         textDelegate.layoutWithConstraints(constraints, LayoutDirection.Ltr)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.lineCount).isEqualTo(2)
         assertThat(layoutResult.isLineEllipsized(1)).isTrue()
@@ -207,9 +207,9 @@
         }
 
         textDelegate.layoutWithConstraints(Constraints(), LayoutDirection.Ltr)
-        val layoutResultLtr = textDelegate.layout
+        val layoutResultLtr = textDelegate.textLayoutResult
         textDelegate.layoutWithConstraints(Constraints(), LayoutDirection.Rtl)
-        val layoutResultRtl = textDelegate.layout
+        val layoutResultRtl = textDelegate.textLayoutResult
 
         assertThat(layoutResultLtr.size.width).isEqualTo(layoutResultRtl.size.width)
     }
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt
similarity index 94%
rename from compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt
index a2195df..4bcbfc4 100644
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCacheWidthWithLetterSpacingTest.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.TEST_FONT_FAMILY
+import androidx.compose.foundation.text.TEST_FONT_FAMILY
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.TextStyle
@@ -85,7 +85,7 @@
             it.density = density
         }
         textDelegate.layoutWithConstraints(Constraints(), LayoutDirection.Ltr)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
         assertThat(layoutResult.lineCount).isEqualTo(1)
     }
 }
diff --git a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextLayoutResultIntegrationTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/TextLayoutResultIntegrationTest.kt
similarity index 89%
rename from compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextLayoutResultIntegrationTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/TextLayoutResultIntegrationTest.kt
index 4b8b7c1..1735715 100644
--- a/compose/foundation/foundation-newtext/src/androidAndroidTest/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextLayoutResultIntegrationTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/modifiers/TextLayoutResultIntegrationTest.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.TEST_FONT_FAMILY
-import androidx.compose.foundation.newtext.text.toIntPx
+import androidx.compose.foundation.text.TEST_FONT_FAMILY
+import androidx.compose.foundation.text.toIntPx
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Canvas
 import androidx.compose.ui.text.AnnotatedString
@@ -64,7 +64,7 @@
             }
 
             textDelegate.layoutWithConstraints(Constraints(0, 200), layoutDirection)
-            val layoutResult = textDelegate.layout
+            val layoutResult = textDelegate.textLayoutResult
 
             assertThat(layoutResult.size.width).isEqualTo(
                 (fontSize.toPx() * text.length).toIntPx()
@@ -87,7 +87,7 @@
         }
 
         textDelegate.layoutWithConstraints(Constraints(maxWidth = width), layoutDirection)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.size.width).isEqualTo(width)
     }
@@ -108,7 +108,7 @@
             }
 
             textDelegate.layoutWithConstraints(Constraints(), layoutDirection)
-            val layoutResult = textDelegate.layout
+            val layoutResult = textDelegate.textLayoutResult
 
             assertThat(layoutResult.size.height).isEqualTo((fontSize.toPx()).toIntPx())
         }
@@ -125,7 +125,7 @@
         }
 
         textDelegate.layoutWithConstraints(Constraints(0, 20), layoutDirection)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult).isNotNull()
     }
@@ -150,7 +150,7 @@
             it.density = density
         }
         textDelegate.layoutWithConstraints(Constraints(), layoutDirection)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         val selection = layoutResult.getOffsetForPosition(Offset.Zero)
 
@@ -177,7 +177,7 @@
                 it.density = this
             }
             textDelegate.layoutWithConstraints(Constraints(), layoutDirection)
-            val layoutResult = textDelegate.layout
+            val layoutResult = textDelegate.textLayoutResult
 
             val selection = layoutResult.getOffsetForPosition(
                 position = Offset((fontSize.toPx() * characterIndex + 1), 0f)
@@ -201,7 +201,7 @@
         }
 
         textDelegate.layoutWithConstraints(Constraints(), layoutDirection)
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.hasVisualOverflow).isFalse()
 
@@ -227,12 +227,12 @@
 
         textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
         // Tries to make 5 lines of text, which exceeds the given maxLines(3).
-        val maxWidth = textDelegate.maxIntrinsicWidth / 5
+        val maxWidth = textDelegate.maxIntrinsicWidth(LayoutDirection.Ltr) / 5
         textDelegate.layoutWithConstraints(
             Constraints(maxWidth = maxWidth),
             layoutDirection
         )
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.didOverflowHeight).isTrue()
     }
@@ -255,12 +255,12 @@
 
         textDelegate.layoutWithConstraints(Constraints.fixed(0, 0), LayoutDirection.Ltr)
         // Tries to make 5 lines of text, which doesn't exceed the given maxLines(10).
-        val maxWidth = textDelegate.maxIntrinsicWidth / 5
+        val maxWidth = textDelegate.maxIntrinsicWidth(LayoutDirection.Ltr) / 5
         textDelegate.layoutWithConstraints(
             Constraints(maxWidth = maxWidth),
             layoutDirection
         )
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.didOverflowHeight).isFalse()
     }
@@ -284,7 +284,7 @@
             layoutDirection
         )
 
-        val maxIntrinsicsHeight = textDelegate.layout.multiParagraph.height
+        val maxIntrinsicsHeight = textDelegate.textLayoutResult.multiParagraph.height
 
         // Make maxHeight smaller than needed.
         val maxHeight = floor(maxIntrinsicsHeight / 2).toInt()
@@ -292,7 +292,7 @@
             Constraints(maxHeight = maxHeight),
             layoutDirection
         )
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.didOverflowHeight).isTrue()
     }
@@ -315,7 +315,7 @@
             Constraints(),
             layoutDirection
         )
-        val maxIntrinsicsHeight = textDelegate.layout.multiParagraph.height
+        val maxIntrinsicsHeight = textDelegate.textLayoutResult.multiParagraph.height
 
         // Make max height larger than the needed.
         val maxHeight = floor(maxIntrinsicsHeight * 2).toInt()
@@ -323,7 +323,7 @@
             Constraints(maxHeight = maxHeight),
             layoutDirection
         )
-        val layoutResult = textDelegate.layout
+        val layoutResult = textDelegate.textLayoutResult
 
         assertThat(layoutResult.didOverflowHeight).isFalse()
     }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2SemanticsTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2SemanticsTest.kt
new file mode 100644
index 0000000..9607660
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2SemanticsTest.kt
@@ -0,0 +1,294 @@
+@file:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.foundation.text.InternalFoundationTextApi
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.text.TextDelegate
+import androidx.compose.foundation.text.selection.fetchTextLayoutResult
+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.platform.testTag
+import androidx.compose.ui.semantics.SemanticsActions
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.semantics.getOrNull
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertTextEquals
+import androidx.compose.ui.test.hasImeAction
+import androidx.compose.ui.test.hasSetTextAction
+import androidx.compose.ui.test.isFocused
+import androidx.compose.ui.test.isNotFocused
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performSemanticsAction
+import androidx.compose.ui.test.performTextInput
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.createFontFamilyResolver
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.Density
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+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 BasicTextField2SemanticsTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val Tag = "TextField"
+
+    private var defaultDensity = Density(1f)
+    private val context = InstrumentationRegistry.getInstrumentation().context
+    private val defaultFontFamilyResolver = createFontFamilyResolver(context)
+
+    @OptIn(InternalFoundationTextApi::class)
+    private var textLayoutState = TextLayoutState(
+        TextDelegate(
+            AnnotatedString(""),
+            TextStyle.Default,
+            fontFamilyResolver = defaultFontFamilyResolver,
+            density = defaultDensity
+        )
+    )
+
+    @Test
+    fun defaultSemantics() {
+        rule.setContent {
+            BasicTextField2(
+                modifier = Modifier.testTag(Tag),
+                state = remember { TextFieldState() },
+                decorationBox = {
+                    Column {
+                        BasicText("label")
+                        it()
+                    }
+                }
+            )
+        }
+
+        rule.onNodeWithTag(Tag)
+            .assertEditableTextEquals("")
+            .assertTextEquals("label", includeEditableText = false)
+            .assertHasClickAction()
+            .assert(hasSetTextAction())
+            .assert(hasImeAction(ImeAction.Default))
+            .assert(isNotFocused())
+            .assert(
+                SemanticsMatcher.expectValue(
+                    SemanticsProperties.TextSelectionRange,
+                    TextRange.Zero
+                )
+            )
+            .assert(SemanticsMatcher.keyIsDefined(SemanticsActions.SetText))
+            // TODO(halilibo): enable after selection work is completed.
+            // .assert(SemanticsMatcher.keyIsDefined(SemanticsActions.SetSelection))
+            .assert(SemanticsMatcher.keyIsDefined(SemanticsActions.GetTextLayoutResult))
+
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        rule.onNodeWithTag(Tag)
+            .performSemanticsAction(SemanticsActions.GetTextLayoutResult) { it(textLayoutResults) }
+        assert(textLayoutResults.size == 1) { "TextLayoutResult is null" }
+    }
+
+    @Test
+    fun semantics_clickAction() {
+        rule.setContent {
+            val state = remember { TextFieldState() }
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag)
+            .assert(isNotFocused())
+            .performSemanticsAction(SemanticsActions.OnClick)
+        rule.onNodeWithTag(Tag)
+            .assert(isFocused())
+    }
+
+    @Test
+    fun semantics_imeOption() {
+        rule.setContent {
+            val state = remember { TextFieldState() }
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag),
+                keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assert(hasImeAction(ImeAction.Search))
+    }
+
+    @Test
+    fun contentSemanticsAreSet_inTheFirstComposition() {
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .testTag(Tag)
+                    .then(TextFieldContentSemanticsElement(state, textLayoutState))
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("hello")
+    }
+
+    @Test
+    fun contentSemanticsAreSet_afterRecomposition() {
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .testTag(Tag)
+                    .then(TextFieldContentSemanticsElement(state, textLayoutState))
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("hello")
+
+        state.editProcessor.reset(TextFieldValue("hello2"))
+
+        rule.onNodeWithTag(Tag).assertTextEquals("hello2")
+    }
+
+    @Test
+    fun selectionSemanticsAreSet_inTheFirstComposition() {
+        val state = TextFieldState(TextFieldValue("hello", selection = TextRange(2)))
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .testTag(Tag)
+                    .then(TextFieldContentSemanticsElement(state, textLayoutState))
+            )
+        }
+
+        with(rule.onNodeWithTag(Tag)) {
+            assertTextEquals("hello")
+            assertSelection(TextRange(2))
+        }
+    }
+
+    @Test
+    fun selectionSemanticsAreSet_afterRecomposition() {
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .testTag(Tag)
+                    .then(TextFieldContentSemanticsElement(state, textLayoutState))
+            )
+        }
+
+        with(rule.onNodeWithTag(Tag)) {
+            assertTextEquals("hello")
+            assertSelection(TextRange.Zero)
+        }
+
+        state.editProcessor.reset(TextFieldValue("hello", selection = TextRange(2)))
+
+        with(rule.onNodeWithTag(Tag)) {
+            assertTextEquals("hello")
+            assertSelection(TextRange(2))
+        }
+    }
+
+    @Test
+    fun textLayoutResultSemanticsAreSet_inTheFirstComposition() {
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("hello")
+        assertThat(rule.onNodeWithTag(Tag).fetchTextLayoutResult().layoutInput.text.text)
+            .isEqualTo("hello")
+    }
+
+    @Test
+    fun textLayoutResultSemanticsAreUpdated_afterRecomposition() {
+        val state = TextFieldState()
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("")
+        rule.onNodeWithTag(Tag).performTextInput("hello")
+        assertThat(rule.onNodeWithTag(Tag).fetchTextLayoutResult().layoutInput.text.text)
+            .isEqualTo("hello")
+    }
+
+    @Test
+    fun semanticsAreSet_afterStateObjectChanges() {
+        val state1 = TextFieldState(TextFieldValue("hello"))
+        val state2 = TextFieldState(TextFieldValue("world", TextRange(2)))
+        var chosenState by mutableStateOf(true)
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .testTag(Tag)
+                    .then(
+                        TextFieldContentSemanticsElement(
+                            if (chosenState) state1 else state2,
+                            textLayoutState
+                        )
+                    )
+            )
+        }
+
+        with(rule.onNodeWithTag(Tag)) {
+            assertTextEquals("hello")
+            assertSelection(TextRange.Zero)
+        }
+
+        chosenState = false
+
+        with(rule.onNodeWithTag(Tag)) {
+            assertTextEquals("world")
+            assertSelection(TextRange(2))
+        }
+    }
+
+    private fun SemanticsNodeInteraction.assertSelection(expected: TextRange) {
+        val selection = fetchSemanticsNode().config
+            .getOrNull(SemanticsProperties.TextSelectionRange)
+        assertThat(selection).isEqualTo(expected)
+    }
+
+    private fun SemanticsNodeInteraction.assertEditableTextEquals(
+        value: String
+    ): SemanticsNodeInteraction =
+        assert(
+            SemanticsMatcher("${SemanticsProperties.EditableText.name} = '$value'") {
+                it.config.getOrNull(SemanticsProperties.EditableText)?.text.equals(value)
+            }
+        )
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2Test.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2Test.kt
new file mode 100644
index 0000000..d7cf9d2
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/BasicTextField2Test.kt
@@ -0,0 +1,310 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.text.KeyboardHelper
+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.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.SemanticsProperties.TextSelectionRange
+import androidx.compose.ui.semantics.getOrNull
+import androidx.compose.ui.test.assertIsFocused
+import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.assertIsNotFocused
+import androidx.compose.ui.test.assertTextEquals
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextInput
+import androidx.compose.ui.test.performTextReplacement
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.sp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class BasicTextField2Test {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val Tag = "BasicTextField2"
+
+    @Test
+    fun textField_rendersEmptyContent() {
+        var textLayoutResult: TextLayoutResult? = null
+        rule.setContent {
+            val state = remember { TextFieldState() }
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.fillMaxSize(),
+                onTextLayout = { textLayoutResult = it }
+            )
+        }
+
+        rule.runOnIdle {
+            assertThat(textLayoutResult).isNotNull()
+            assertThat(textLayoutResult?.layoutInput?.text).isEqualTo(AnnotatedString(""))
+        }
+    }
+
+    @Test
+    fun textField_contentChange_updatesState() {
+        val state = TextFieldState(TextFieldValue("Hello ", TextRange(Int.MAX_VALUE)))
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).performTextInput("World!")
+
+        rule.runOnIdle {
+            assertThat(state.value.text).isEqualTo("Hello World!")
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("Hello World!")
+        val selection = rule.onNodeWithTag(Tag).fetchSemanticsNode()
+            .config.getOrNull(TextSelectionRange)
+        assertThat(selection).isEqualTo(TextRange("Hello World!".length))
+    }
+
+    /**
+     * This is a goal that we set for ourselves. Only updating the editing buffer should not cause
+     * BasicTextField to recompose.
+     */
+    @Test
+    fun textField_imeUpdatesDontCauseRecomposition() {
+        val state = TextFieldState()
+        var compositionCount = 0
+        var textLayoutResultCount = 0
+        rule.setContent {
+            compositionCount++
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag),
+                onTextLayout = { textLayoutResultCount++ }
+            )
+        }
+
+        with(rule.onNodeWithTag(Tag)) {
+            performTextInput("hello")
+        }
+
+        rule.runOnIdle {
+            assertThat(compositionCount).isEqualTo(1)
+            assertThat(textLayoutResultCount).isEqualTo(2)
+        }
+    }
+
+    @Test
+    fun textField_textStyleFontSizeChange_relayouts() {
+        val state = TextFieldState(TextFieldValue("Hello ", TextRange(Int.MAX_VALUE)))
+        var style by mutableStateOf(TextStyle(fontSize = 20.sp))
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag),
+                textStyle = style,
+                onTextLayout = { textLayoutResults += it }
+            )
+        }
+
+        style = TextStyle(fontSize = 30.sp)
+
+        rule.runOnIdle {
+            assertThat(textLayoutResults.size).isEqualTo(2)
+            assertThat(textLayoutResults.map { it.layoutInput.style.fontSize })
+                .isEqualTo(listOf(20.sp, 30.sp))
+        }
+    }
+
+    @Test
+    fun textField_textStyleColorChange_doesNotRelayout() {
+        val state = TextFieldState(TextFieldValue("Hello"))
+        var style by mutableStateOf(TextStyle(color = Color.Red))
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag),
+                textStyle = style,
+                onTextLayout = { textLayoutResults += it }
+            )
+        }
+
+        style = TextStyle(color = Color.Blue)
+
+        rule.runOnIdle {
+            assertThat(textLayoutResults.size).isEqualTo(2)
+            assertThat(textLayoutResults[0].multiParagraph)
+                .isSameInstanceAs(textLayoutResults[1].multiParagraph)
+        }
+    }
+
+    @Test
+    fun textField_contentChange_relayouts() {
+        val state = TextFieldState(TextFieldValue("Hello ", TextRange(Int.MAX_VALUE)))
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag),
+                onTextLayout = { textLayoutResults += it }
+            )
+        }
+
+        rule.onNodeWithTag(Tag).performTextInput("World!")
+
+        rule.runOnIdle {
+            assertThat(textLayoutResults.size).isEqualTo(2)
+            assertThat(textLayoutResults.map { it.layoutInput.text.text })
+                .isEqualTo(listOf("Hello ", "Hello World!"))
+        }
+    }
+
+    @Test
+    fun textField_focus_showsSoftwareKeyboard() {
+        val state = TextFieldState()
+        val keyboardHelper = KeyboardHelper(rule)
+        rule.setContent {
+            keyboardHelper.initialize()
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).performClick()
+        rule.onNodeWithTag(Tag).assertIsFocused()
+
+        keyboardHelper.waitForKeyboardVisibility(true)
+
+        rule.runOnIdle {
+            assertThat(keyboardHelper.isSoftwareKeyboardShown()).isTrue()
+        }
+    }
+
+    @Ignore // b/273412941
+    @Test
+    fun textField_focus_doesNotShowSoftwareKeyboard_ifDisabled() {
+        val state = TextFieldState()
+        val keyboardHelper = KeyboardHelper(rule)
+        rule.setContent {
+            keyboardHelper.initialize()
+            BasicTextField2(
+                state = state,
+                enabled = false,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertIsNotEnabled()
+        rule.onNodeWithTag(Tag).performClick()
+        rule.onNodeWithTag(Tag).assertIsNotFocused()
+
+        keyboardHelper.waitForKeyboardVisibility(false)
+
+        rule.runOnIdle {
+            assertThat(keyboardHelper.isSoftwareKeyboardShown()).isFalse()
+        }
+    }
+
+    @Test
+    fun textField_whenStateObjectChanges_newTextIsRendered() {
+        val state1 = TextFieldState(TextFieldValue("Hello"))
+        val state2 = TextFieldState(TextFieldValue("World"))
+        var toggleState by mutableStateOf(true)
+        val state by derivedStateOf { if (toggleState) state1 else state2 }
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                enabled = false,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag)
+            )
+        }
+
+        rule.onNodeWithTag(Tag).assertTextEquals("Hello")
+        toggleState = !toggleState
+        rule.onNodeWithTag(Tag).assertTextEquals("World")
+    }
+
+    @Test
+    fun textField_whenStateObjectChanges_restartsInput() {
+        val state1 = TextFieldState(TextFieldValue("Hello"))
+        val state2 = TextFieldState(TextFieldValue("World"))
+        var toggleState by mutableStateOf(true)
+        val state by derivedStateOf { if (toggleState) state1 else state2 }
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                enabled = false,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .testTag(Tag)
+            )
+        }
+
+        with(rule.onNodeWithTag(Tag)) {
+            performTextReplacement("Compose")
+            assertTextEquals("Compose")
+        }
+        toggleState = !toggleState
+        with(rule.onNodeWithTag(Tag)) {
+            performTextReplacement("Compose2")
+            assertTextEquals("Compose2")
+        }
+        assertThat(state1.value.text).isEqualTo("Compose")
+        assertThat(state2.value.text).isEqualTo("Compose2")
+    }
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/DecorationBoxTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/DecorationBoxTest.kt
new file mode 100644
index 0000000..9a50808
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/DecorationBoxTest.kt
@@ -0,0 +1,183 @@
+/*
+ * 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.text2
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertIsFocused
+import androidx.compose.ui.test.click
+import androidx.compose.ui.test.hasParent
+import androidx.compose.ui.test.hasSetTextAction
+import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.isFocused
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.longClick
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.text.TextRange
+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
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalFoundationApi::class)
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class DecorationBoxTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val Tag = "BasicTextField2"
+    private val DecorationTag = "DecorationBox"
+
+    @Test
+    fun focusIsAppliedOnDecoratedComposable() {
+        // create a decorated BasicTextField2
+        val state = TextFieldState()
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag),
+                decorationBox = { innerTextField ->
+                    Box(
+                        modifier = Modifier
+                            .border(BorderStroke(2.dp, SolidColor(Color.Red)))
+                            .padding(16.dp)
+                            .testTag(DecorationTag)
+                    ) {
+                        innerTextField()
+                    }
+                }
+            )
+        }
+
+        // requestFocus on node
+        rule.onNodeWithTag(Tag).performClick()
+
+        // assertThat decoration modifier has a focused parent.
+        rule.onNodeWithTag(DecorationTag, useUnmergedTree = true).assert(hasParent(isFocused()))
+    }
+
+    @Test
+    fun semanticsAreAppliedOnDecoratedComposable() {
+        // create a decorated BasicTextField2
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag),
+                decorationBox = { innerTextField ->
+                    Box(
+                        modifier = Modifier
+                            .border(BorderStroke(2.dp, SolidColor(Color.Red)))
+                            .padding(16.dp)
+                            .testTag(DecorationTag)
+                    ) {
+                        innerTextField()
+                    }
+                }
+            )
+        }
+
+        // assertThat decoration modifier has a focused parent.
+        with(rule.onNodeWithTag(DecorationTag, useUnmergedTree = true)) {
+            assert(hasParent(hasText("hello")))
+            assert(hasParent(hasSetTextAction()))
+        }
+    }
+
+    @Test
+    fun clickGestureIsAppliedOnDecoratedComposable() {
+        // create a decorated BasicTextField2
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag),
+                decorationBox = { innerTextField ->
+                    Box(
+                        modifier = Modifier
+                            .border(BorderStroke(2.dp, SolidColor(Color.Red)))
+                            .padding(16.dp)
+                            .testTag(DecorationTag)
+                    ) {
+                        innerTextField()
+                    }
+                }
+            )
+        }
+
+        // click on decoration box
+        rule.onNodeWithTag(DecorationTag, useUnmergedTree = true).performTouchInput {
+            // should be on the box not on inner text field since there is a padding
+            click(Offset(1f, 1f))
+        }
+
+        // assertThat textfield has focus
+        rule.onNodeWithTag(Tag).assertIsFocused()
+    }
+
+    @Ignore // TODO(halilibo): enable when pointerInput gestures are enabled
+    @Test
+    fun longClickGestureIsAppliedOnDecoratedComposable() {
+        // create a decorated BasicTextField2
+        val state = TextFieldState(TextFieldValue("hello"))
+        rule.setContent {
+            BasicTextField2(
+                state = state,
+                modifier = Modifier.testTag(Tag),
+                decorationBox = { innerTextField ->
+                    Box(
+                        modifier = Modifier
+                            .border(BorderStroke(2.dp, SolidColor(Color.Red)))
+                            .padding(16.dp)
+                            .testTag(DecorationTag)
+                    ) {
+                        innerTextField()
+                    }
+                }
+            )
+        }
+
+        // click on decoration box
+        rule.onNodeWithTag(DecorationTag, useUnmergedTree = true).performTouchInput {
+            // should be on the box not on inner text field since there is a padding
+            longClick(Offset(1f, 1f))
+        }
+
+        // assertThat selection happened
+        rule.runOnIdle {
+            assertThat(state.value.selection).isEqualTo(TextRange(0, 5))
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/HeightInLinesModifierTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/HeightInLinesModifierTest.kt
new file mode 100644
index 0000000..8777e2d1
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/HeightInLinesModifierTest.kt
@@ -0,0 +1,358 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2
+
+import android.content.Context
+import android.graphics.Typeface
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.foundation.text.TEST_FONT
+import androidx.compose.foundation.text.heightInLines
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.platform.InspectableValue
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFontFamilyResolver
+import androidx.compose.ui.platform.ValueElement
+import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.AndroidFont
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontLoadingStrategy
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontVariation
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.font.createFontFamilyResolver
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class HeightInLinesModifierTest {
+
+    private val longText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " +
+        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam," +
+        " quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. " +
+        "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu " +
+        "fugiat nulla pariatur."
+
+    private val context = InstrumentationRegistry.getInstrumentation().context
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun minLines_shortInputText() {
+        var subjectLayout: TextLayoutResult? = null
+        var subjectHeight: Int? = null
+        var twoLineHeight: Int? = null
+        val positionedLatch = CountDownLatch(1)
+        val twoLinePositionedLatch = CountDownLatch(1)
+
+        rule.setContent {
+            HeightObservingText(
+                onGlobalHeightPositioned = {
+                    subjectHeight = it
+                    positionedLatch.countDown()
+                },
+                onTextLayoutResult = {
+                    subjectLayout = it
+                },
+                text = "abc",
+                minLines = 2
+            )
+            HeightObservingText(
+                onGlobalHeightPositioned = {
+                    twoLineHeight = it
+                    twoLinePositionedLatch.countDown()
+                },
+                onTextLayoutResult = {},
+                text = "1\n2",
+                minLines = 2
+            )
+        }
+        assertThat(positionedLatch.await(1, TimeUnit.SECONDS)).isTrue()
+        assertThat(twoLinePositionedLatch.await(1, TimeUnit.SECONDS)).isTrue()
+
+        rule.runOnIdle {
+            assertThat(subjectLayout).isNotNull()
+            assertThat(subjectLayout!!.lineCount).isEqualTo(1)
+            assertThat(subjectHeight!!).isEqualTo(twoLineHeight)
+        }
+    }
+
+    @Test
+    fun maxLines_shortInputText() {
+        val (textLayoutResult, height) = setTextFieldWithMaxLines(
+            text = "abc",
+            maxLines = 5
+        )
+
+        rule.runOnIdle {
+            assertThat(textLayoutResult).isNotNull()
+            assertThat(textLayoutResult!!.lineCount).isEqualTo(1)
+            assertThat(textLayoutResult.size.height).isEqualTo(height)
+        }
+    }
+
+    @Test
+    fun maxLines_notApplied_infiniteMaxLines() {
+        val (textLayoutResult, height) =
+            setTextFieldWithMaxLines(longText, Int.MAX_VALUE)
+
+        rule.runOnIdle {
+            assertThat(textLayoutResult).isNotNull()
+            assertThat(textLayoutResult!!.size.height).isEqualTo(height)
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun minLines_invalidValue() {
+        rule.setContent {
+            Box(
+                modifier = Modifier.heightInLines(textStyle = TextStyle.Default, minLines = 0)
+            )
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun maxLines_invalidValue() {
+        rule.setContent {
+            Box(
+                modifier = Modifier.heightInLines(textStyle = TextStyle.Default, maxLines = 0)
+            )
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun minLines_greaterThan_maxLines_invalidValue() {
+        rule.setContent {
+            Box(
+                modifier = Modifier.heightInLines(
+                    textStyle = TextStyle.Default,
+                    minLines = 2,
+                    maxLines = 1
+                )
+            )
+        }
+    }
+
+    @Test
+    fun minLines_longInputText() {
+        val (textLayoutResult, height) = setTextFieldWithMaxLines(
+            text = longText,
+            minLines = 2
+        )
+
+        rule.runOnIdle {
+            assertThat(textLayoutResult).isNotNull()
+            // should be in the 20s, but use this to create invariant for the next assertion
+            assertThat(textLayoutResult!!.lineCount).isGreaterThan(2)
+            assertThat(textLayoutResult.size.height).isEqualTo(height)
+        }
+    }
+
+    @Test
+    fun maxLines_longInputText() {
+        var subjectLayout: TextLayoutResult? = null
+        var subjectHeight: Int? = null
+        var twoLineHeight: Int? = null
+        val positionedLatch = CountDownLatch(1)
+        val twoLinePositionedLatch = CountDownLatch(1)
+
+        rule.setContent {
+            HeightObservingText(
+                onGlobalHeightPositioned = {
+                    subjectHeight = it
+                    positionedLatch.countDown()
+                },
+                onTextLayoutResult = {
+                    subjectLayout = it
+                },
+                text = longText,
+                maxLines = 2
+            )
+            HeightObservingText(
+                onGlobalHeightPositioned = {
+                    twoLineHeight = it
+                    twoLinePositionedLatch.countDown()
+                },
+                onTextLayoutResult = {},
+                text = "1\n2",
+                maxLines = 2
+            )
+        }
+        assertThat(positionedLatch.await(1, TimeUnit.SECONDS)).isTrue()
+        assertThat(twoLinePositionedLatch.await(1, TimeUnit.SECONDS)).isTrue()
+
+        rule.runOnIdle {
+            assertThat(subjectLayout).isNotNull()
+            // should be in the 20s, but use this to create invariant for the next assertion
+            assertThat(subjectLayout!!.lineCount).isGreaterThan(2)
+            assertThat(subjectHeight!!).isEqualTo(twoLineHeight)
+        }
+    }
+
+    @OptIn(ExperimentalTextApi::class, ExperimentalCoroutinesApi::class)
+    @Test
+    fun asyncFontLoad_changesLineHeight() {
+        val testDispatcher = UnconfinedTestDispatcher()
+        val resolver = createFontFamilyResolver(context, testDispatcher)
+
+        val typefaceDeferred = CompletableDeferred<Typeface>()
+        val asyncLoader = object : AndroidFont.TypefaceLoader {
+            override fun loadBlocking(context: Context, font: AndroidFont): Typeface =
+                TODO("Not yet implemented")
+
+            override suspend fun awaitLoad(context: Context, font: AndroidFont): Typeface {
+                return typefaceDeferred.await()
+            }
+        }
+        val fontFamily = FontFamily(
+            object : AndroidFont(FontLoadingStrategy.Async, asyncLoader, FontVariation.Settings()) {
+                override val weight: FontWeight = FontWeight.Normal
+                override val style: FontStyle = FontStyle.Normal
+            },
+            TEST_FONT
+        )
+
+        val heights = mutableListOf<Int>()
+
+        rule.setContent {
+            CompositionLocalProvider(
+                LocalFontFamilyResolver provides resolver,
+                LocalDensity provides Density(1.0f, 1f)
+            ) {
+                HeightObservingText(
+                    onGlobalHeightPositioned = {
+                        heights.add(it)
+                    },
+                    onTextLayoutResult = {},
+                    text = longText,
+                    maxLines = 10,
+                    textStyle = TextStyle.Default.copy(
+                        fontFamily = fontFamily,
+                        fontSize = 80.sp
+                    )
+                )
+            }
+        }
+
+        val before = heights.toList()
+        typefaceDeferred.complete(Typeface.create("cursive", Typeface.BOLD_ITALIC))
+
+        rule.runOnIdle {
+            assertThat(heights.size).isGreaterThan(before.size)
+            assertThat(heights.distinct().size).isGreaterThan(before.distinct().size)
+        }
+    }
+
+    @Test
+    fun testInspectableValue() {
+        isDebugInspectorInfoEnabled = true
+
+        val modifier = Modifier.heightInLines(
+            textStyle = TextStyle.Default,
+            minLines = 5,
+            maxLines = 10
+        ) as InspectableValue
+        assertThat(modifier.nameFallback).isEqualTo("heightInLines")
+        assertThat(modifier.inspectableElements.asIterable()).containsExactly(
+            ValueElement("minLines", 5),
+            ValueElement("maxLines", 10),
+            ValueElement("textStyle", TextStyle.Default)
+        )
+
+        isDebugInspectorInfoEnabled = false
+    }
+
+    private fun setTextFieldWithMaxLines(
+        text: String,
+        minLines: Int = 1,
+        maxLines: Int = Int.MAX_VALUE
+    ): Pair<TextLayoutResult?, Int?> {
+        var textLayoutResult: TextLayoutResult? = null
+        var height: Int? = null
+        val positionedLatch = CountDownLatch(1)
+
+        rule.setContent {
+            HeightObservingText(
+                onGlobalHeightPositioned = {
+                    height = it
+                    positionedLatch.countDown()
+                },
+                onTextLayoutResult = {
+                    textLayoutResult = it
+                },
+                text = text,
+                minLines = minLines,
+                maxLines = maxLines
+            )
+        }
+        assertThat(positionedLatch.await(1, TimeUnit.SECONDS)).isTrue()
+
+        return Pair(textLayoutResult, height)
+    }
+
+    @Composable
+    private fun HeightObservingText(
+        onGlobalHeightPositioned: (Int) -> Unit,
+        onTextLayoutResult: Density.(TextLayoutResult) -> Unit,
+        text: String,
+        minLines: Int = 1,
+        maxLines: Int = Int.MAX_VALUE,
+        textStyle: TextStyle = TextStyle.Default
+    ) {
+        Box(
+            Modifier.onGloballyPositioned {
+                onGlobalHeightPositioned(it.size.height)
+            }
+        ) {
+            BasicTextField2(
+                state = remember { TextFieldState(TextFieldValue(text)) },
+                textStyle = textStyle,
+                minLines = minLines,
+                maxLines = maxLines,
+                modifier = Modifier.requiredWidth(100.dp),
+                onTextLayout = onTextLayoutResult
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldCursorTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldCursorTest.kt
new file mode 100644
index 0000000..48e9db1
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldCursorTest.kt
@@ -0,0 +1,476 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2
+
+import android.os.Build
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertPixelColor
+import androidx.compose.testutils.assertPixels
+import androidx.compose.testutils.assertShape
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.MotionDurationScale
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.toPixelMap
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.hasSetTextAction
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextReplacement
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.TextFieldValue
+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.unit.sp
+import androidx.compose.ui.unit.toOffset
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import kotlin.math.ceil
+import kotlin.math.floor
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+class TextFieldCursorTest {
+
+    private val motionDurationScale = object : MotionDurationScale {
+        override var scaleFactor: Float by mutableStateOf(1f)
+    }
+
+    @OptIn(ExperimentalTestApi::class)
+    @get:Rule
+    val rule = createComposeRule(effectContext = motionDurationScale).also {
+        it.mainClock.autoAdvance = false
+    }
+
+    private val boxPadding = 10.dp
+    private val cursorColor = Color.Red
+    private val textStyle = TextStyle(
+        color = Color.White,
+        background = Color.White,
+        fontSize = 10.sp
+    )
+
+    private val textFieldWidth = 10.dp
+    private val textFieldHeight = 20.dp
+    private val textFieldBgColor = Color.White
+    private var isFocused = false
+    private var cursorRect = Rect.Zero
+
+    private val bgModifier = Modifier.background(textFieldBgColor)
+    private val focusModifier = Modifier.onFocusChanged { if (it.isFocused) isFocused = true }
+    private val sizeModifier = Modifier.size(textFieldWidth, textFieldHeight)
+
+    // default TextFieldModifier
+    private val textFieldModifier = sizeModifier
+        .then(bgModifier)
+        .then(focusModifier)
+
+    // default onTextLayout to capture cursor boundaries.
+    private val onTextLayout: Density.(TextLayoutResult) -> Unit = {
+        cursorRect = it.getCursorRect(0)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun textFieldFocused_cursorRendered() = with(rule.density) {
+        val state = TextFieldState()
+        rule.setContent {
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(cursorColor),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        rule.mainClock.advanceTimeBy(100)
+
+        with(rule.density) {
+            rule.onNode(hasSetTextAction())
+                .captureToImage()
+                .assertCursor(2.dp, this, cursorRect)
+        }
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun textFieldFocused_cursorWithBrush() = with(rule.density) {
+        val state = TextFieldState()
+        rule.setContent {
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle.copy(fontSize = textStyle.fontSize * 2),
+                    modifier = Modifier
+                        .size(textFieldWidth, textFieldHeight * 2)
+                        .then(bgModifier)
+                        .then(focusModifier),
+                    cursorBrush = Brush.verticalGradient(
+                        // make a brush double/triple color at the beginning and end so we have stable
+                        // colors at the ends.
+                        // Without triple bottom, the bottom color never hits to the provided color.
+                        listOf(
+                            Color.Blue,
+                            Color.Blue,
+                            Color.Green,
+                            Color.Green,
+                            Color.Green
+                        )
+                    ),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        rule.mainClock.advanceTimeBy(100)
+
+        val bitmap = rule.onNode(hasSetTextAction())
+            .captureToImage().toPixelMap()
+
+        val cursorLeft = ceil(cursorRect.left).toInt() + 1
+        val cursorTop = ceil(cursorRect.top).toInt() + 1
+        val cursorBottom = floor(cursorRect.bottom).toInt() - 1
+        bitmap.assertPixelColor(Color.Blue, x = cursorLeft, y = cursorTop)
+        bitmap.assertPixelColor(Color.Green, x = cursorLeft, y = cursorBottom)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun cursorBlinkingAnimation() = with(rule.density) {
+        val state = TextFieldState()
+        rule.setContent {
+            // The padding helps if the test is run accidentally in landscape. Landscape makes
+            // the cursor to be next to the navigation bar which affects the red color to be a bit
+            // different - possibly anti-aliasing.
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(cursorColor),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        // cursor visible first 500 ms
+        rule.mainClock.advanceTimeBy(100)
+        with(rule.density) {
+            rule.onNode(hasSetTextAction())
+                .captureToImage()
+                .assertCursor(2.dp, this, cursorRect)
+        }
+
+        // cursor invisible during next 500 ms
+        rule.mainClock.advanceTimeBy(700)
+        rule.onNode(hasSetTextAction())
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = RectangleShape,
+                shapeColor = Color.White,
+                backgroundColor = Color.White,
+                shapeOverlapPixelCount = 0.0f
+            )
+    }
+
+    @Suppress("UnnecessaryOptInAnnotation")
+    @OptIn(ExperimentalTestApi::class)
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun cursorBlinkingAnimation_whenSystemDisablesAnimations() = with(rule.density) {
+        motionDurationScale.scaleFactor = 0f
+        val state = TextFieldState()
+
+        rule.setContent {
+            // The padding helps if the test is run accidentally in landscape. Landscape makes
+            // the cursor to be next to the navigation bar which affects the red color to be a bit
+            // different - possibly anti-aliasing.
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(cursorColor),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        // cursor visible first 500 ms
+        rule.mainClock.advanceTimeBy(100)
+        with(rule.density) {
+            rule.onNode(hasSetTextAction())
+                .captureToImage()
+                .assertCursor(2.dp, this, cursorRect)
+        }
+
+        // cursor invisible during next 500 ms
+        rule.mainClock.advanceTimeBy(700)
+        rule.onNode(hasSetTextAction())
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = RectangleShape,
+                shapeColor = Color.White,
+                backgroundColor = Color.White,
+                shapeOverlapPixelCount = 0.0f
+            )
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun cursorUnsetColor_noCursor() = with(rule.density) {
+        rule.setContent {
+            // The padding helps if the test is run accidentally in landscape. Landscape makes
+            // the cursor to be next to the navigation bar which affects the red color to be a bit
+            // different - possibly anti-aliasing.
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField(
+                    value = "",
+                    onValueChange = {},
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(Color.Unspecified)
+                )
+            }
+        }
+
+        focusAndWait()
+
+        // no cursor when usually shown
+        rule.onNode(hasSetTextAction())
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = RectangleShape,
+                shapeColor = Color.White,
+                backgroundColor = Color.White,
+                shapeOverlapPixelCount = 0.0f
+            )
+
+        // no cursor when should be no cursor
+        rule.mainClock.advanceTimeBy(700)
+        rule.onNode(hasSetTextAction())
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = RectangleShape,
+                shapeColor = Color.White,
+                backgroundColor = Color.White,
+                shapeOverlapPixelCount = 0.0f
+            )
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun cursorNotBlinking_whileTyping() = with(rule.density) {
+        val state = TextFieldState(TextFieldValue("test"))
+        rule.setContent {
+            // The padding helps if the test is run accidentally in landscape. Landscape makes
+            // the cursor to be next to the navigation bar which affects the red color to be a bit
+            // different - possibly anti-aliasing.
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(cursorColor),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        // cursor visible first 500 ms
+        rule.mainClock.advanceTimeBy(500)
+        // TODO(b/170298051) check here that cursor is visible when we have a way to control
+        //  cursor position when sending a text
+
+        // change text field value
+        rule.onNode(hasSetTextAction())
+            .performTextReplacement("")
+
+        // cursor would have been invisible during next 500 ms if cursor blinks while typing.
+        // To prevent blinking while typing we restart animation when new symbol is typed.
+        rule.mainClock.advanceTimeBy(400)
+        with(rule.density) {
+            rule.onNode(hasSetTextAction())
+                .captureToImage()
+                .assertCursor(2.dp, this, cursorRect)
+        }
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun selectionChanges_cursorNotBlinking() = with(rule.density) {
+        rule.mainClock.autoAdvance = false
+        val state = TextFieldState(TextFieldValue("test", selection = TextRange(2)))
+        rule.setContent {
+            // The padding helps if the test is run accidentally in landscape. Landscape makes
+            // the cursor to be next to the navigation bar which affects the red color to be a bit
+            // different - possibly anti-aliasing.
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = SolidColor(cursorColor),
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        // hide the cursor
+        rule.mainClock.advanceTimeBy(500)
+        rule.mainClock.advanceTimeByFrame()
+
+        // TODO(b/170298051) check here that cursor is visible when we have a way to control
+        //  cursor position when sending a text
+
+        rule.runOnIdle {
+            state.editProcessor.reset(state.value.copy(selection = TextRange(0)))
+        }
+
+        // necessary for animation to start (shows cursor again)
+        rule.mainClock.advanceTimeByFrame()
+
+        with(rule.density) {
+            rule.onNode(hasSetTextAction())
+                .captureToImage()
+                .assertCursor(2.dp, this, cursorRect)
+        }
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun brushChanged_doesntResetTimer() {
+        var cursorBrush by mutableStateOf(SolidColor(cursorColor))
+        val state = TextFieldState()
+        rule.setContent {
+            Box(Modifier.padding(boxPadding)) {
+                BasicTextField2(
+                    state = state,
+                    textStyle = textStyle,
+                    modifier = textFieldModifier,
+                    cursorBrush = cursorBrush,
+                    onTextLayout = onTextLayout
+                )
+            }
+        }
+
+        focusAndWait()
+
+        rule.mainClock.advanceTimeBy(800)
+        cursorBrush = SolidColor(Color.Green)
+        rule.mainClock.advanceTimeByFrame()
+
+        rule.onNode(hasSetTextAction())
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                shape = RectangleShape,
+                shapeColor = Color.White,
+                backgroundColor = Color.White,
+                shapeOverlapPixelCount = 0.0f
+            )
+    }
+
+    private fun focusAndWait() {
+        rule.onNode(hasSetTextAction()).performClick()
+        rule.mainClock.advanceTimeUntil { isFocused }
+    }
+
+    private fun ImageBitmap.assertCursor(cursorWidth: Dp, density: Density, cursorRect: Rect) {
+        assertThat(cursorRect.height).isNotEqualTo(0f)
+        assertThat(cursorRect).isNotEqualTo(Rect.Zero)
+        val cursorWidthPx = (with(density) { cursorWidth.roundToPx() })
+
+        // assert cursor width is greater than 2 since we will shrink the check area by 1 on each
+        // side
+        assertThat(cursorWidthPx).isGreaterThan(2)
+
+        // shrink the check are by 1px for left, top, right, bottom
+        val checkRect = Rect(
+            ceil(cursorRect.left) + 1,
+            ceil(cursorRect.top) + 1,
+            floor(cursorRect.right) + cursorWidthPx - 1,
+            floor(cursorRect.bottom) - 1
+        )
+
+        // skip an expanded rectangle that is 1px larger than cursor rectangle due to antialiasing
+        val skipRect = Rect(
+            floor(cursorRect.left) - 1,
+            floor(cursorRect.top) - 1,
+            ceil(cursorRect.right) + cursorWidthPx + 1,
+            ceil(cursorRect.bottom) + 1
+        )
+
+        val width = width
+        val height = height
+        this.assertPixels(
+            IntSize(width, height)
+        ) { position ->
+            if (checkRect.contains(position.toOffset())) {
+                // cursor
+                cursorColor
+            } else if (skipRect.contains(position.toOffset())) {
+                // skip some pixels around cursor
+                null
+            } else {
+                // text field background
+                textFieldBgColor
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldFocusTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldFocusTest.kt
new file mode 100644
index 0000000..1bc6713
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/TextFieldFocusTest.kt
@@ -0,0 +1,493 @@
+@file:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2
+
+import android.os.SystemClock
+import android.view.InputDevice
+import android.view.KeyEvent
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.border
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardHelper
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+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.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.key.NativeKeyEvent
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsFocused
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performKeyPress
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Dialog
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class TextFieldFocusTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val keyboardHelper = KeyboardHelper(rule)
+
+    @Composable
+    private fun TextFieldApp(dataList: List<FocusTestData>) {
+        for (data in dataList) {
+            val state = remember { TextFieldState() }
+            BasicTextField2(
+                state = state,
+                modifier = Modifier
+                    .focusRequester(data.focusRequester)
+                    .onFocusChanged { data.focused = it.isFocused }
+                    .requiredWidth(10.dp)
+            )
+        }
+    }
+
+    data class FocusTestData(val focusRequester: FocusRequester, var focused: Boolean = false)
+
+    @Test
+    fun requestFocus() {
+        lateinit var testDataList: List<FocusTestData>
+
+        rule.setContent {
+            testDataList = listOf(
+                FocusTestData(FocusRequester()),
+                FocusTestData(FocusRequester()),
+                FocusTestData(FocusRequester())
+            )
+
+            TextFieldApp(testDataList)
+        }
+
+        rule.runOnIdle { testDataList[0].focusRequester.requestFocus() }
+
+        rule.runOnIdle {
+            assertThat(testDataList[0].focused).isTrue()
+            assertThat(testDataList[1].focused).isFalse()
+            assertThat(testDataList[2].focused).isFalse()
+        }
+
+        rule.runOnIdle { testDataList[1].focusRequester.requestFocus() }
+        rule.runOnIdle {
+            assertThat(testDataList[0].focused).isFalse()
+            assertThat(testDataList[1].focused).isTrue()
+            assertThat(testDataList[2].focused).isFalse()
+        }
+
+        rule.runOnIdle { testDataList[2].focusRequester.requestFocus() }
+        rule.runOnIdle {
+            assertThat(testDataList[0].focused).isFalse()
+            assertThat(testDataList[1].focused).isFalse()
+            assertThat(testDataList[2].focused).isTrue()
+        }
+    }
+
+    @Test
+    fun noCrashWhenSwitchingBetweenEnabledFocusedAndDisabledTextField() {
+        val enabled = mutableStateOf(true)
+        var focused = false
+        val tag = "textField"
+        rule.setContent {
+            val state = remember { TextFieldState() }
+            BasicTextField2(
+                state = state,
+                enabled = enabled.value,
+                modifier = Modifier
+                    .testTag(tag)
+                    .onFocusChanged {
+                        focused = it.isFocused
+                    }
+                    .requiredWidth(10.dp)
+            )
+        }
+        // bring enabled text field into focus
+        rule.onNodeWithTag(tag).performClick()
+        rule.runOnIdle {
+            assertThat(focused).isTrue()
+        }
+
+        // make text field disabled
+        enabled.value = false
+        rule.runOnIdle {
+            assertThat(focused).isFalse()
+        }
+
+        // make text field enabled again, it must not crash
+        enabled.value = true
+        rule.runOnIdle {
+            assertThat(focused).isFalse()
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    fun keyboardIsShown_forFieldInActivity_whenFocusRequestedImmediately_fromLaunchedEffect() {
+        keyboardIsShown_whenFocusRequestedImmediately_fromEffect(
+            runEffect = {
+                LaunchedEffect(Unit) {
+                    it()
+                }
+            }
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    fun keyboardIsShown_forFieldInActivity_whenFocusRequestedImmediately_fromDisposableEffect() {
+        keyboardIsShown_whenFocusRequestedImmediately_fromEffect(
+            runEffect = {
+                DisposableEffect(Unit) {
+                    it()
+                    onDispose {}
+                }
+            }
+        )
+    }
+
+    // TODO(b/229378542) We can't accurately detect IME visibility from dialogs before API 30 so
+    //  this test can't assert.
+    @SdkSuppress(minSdkVersion = 30)
+    @Test
+    fun keyboardIsShown_forFieldInDialog_whenFocusRequestedImmediately_fromLaunchedEffect() {
+        keyboardIsShown_whenFocusRequestedImmediately_fromEffect(
+            runEffect = {
+                LaunchedEffect(Unit) {
+                    it()
+                }
+            },
+            wrapContent = {
+                Dialog(onDismissRequest = {}, content = it)
+            }
+        )
+    }
+
+    // TODO(b/229378542) We can't accurately detect IME visibility from dialogs before API 30 so
+    //  this test can't assert.
+    @SdkSuppress(minSdkVersion = 30)
+    @Test
+    fun keyboardIsShown_forFieldInDialog_whenFocusRequestedImmediately_fromDisposableEffect() {
+        keyboardIsShown_whenFocusRequestedImmediately_fromEffect(
+            runEffect = {
+                DisposableEffect(Unit) {
+                    it()
+                    onDispose {}
+                }
+            },
+            wrapContent = {
+                Dialog(onDismissRequest = {}, content = it)
+            }
+        )
+    }
+
+    private fun keyboardIsShown_whenFocusRequestedImmediately_fromEffect(
+        runEffect: @Composable (body: () -> Unit) -> Unit,
+        wrapContent: @Composable (@Composable () -> Unit) -> Unit = { it() }
+    ) {
+        val focusRequester = FocusRequester()
+        val keyboardHelper = KeyboardHelper(rule)
+
+        rule.setContent {
+            wrapContent {
+                keyboardHelper.initialize()
+
+                runEffect {
+                    assertThat(keyboardHelper.isSoftwareKeyboardShown()).isFalse()
+                    focusRequester.requestFocus()
+                }
+
+                BasicTextField(
+                    value = "",
+                    onValueChange = {},
+                    modifier = Modifier.focusRequester(focusRequester)
+                )
+            }
+        }
+
+        keyboardHelper.waitForKeyboardVisibility(visible = true)
+
+        // Ensure the keyboard doesn't leak in to the next test. Can't do this at the start of the
+        // test since the KeyboardHelper won't be initialized until composition runs, and this test
+        // is checking behavior that all happens on the first frame.
+        keyboardHelper.hideKeyboard()
+        keyboardHelper.waitForKeyboardVisibility(visible = false)
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    @Ignore // TODO(halilibo): reenable when dpad focus modifier does not use TextFieldState
+    fun basicTextField_checkFocusNavigation_onDPadLeft() {
+        setupAndEnableBasicTextField()
+        inputSingleLineTextInBasicTextField()
+
+        // Dismiss keyboard on back press
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_BACK)
+        rule.waitForIdle()
+
+        // Move focus to the focusable element on left
+        keyPressOnPhysicalKeyboard(rule, NativeKeyEvent.KEYCODE_DPAD_LEFT)
+
+        // Check if the element to the left of text field gains focus
+        rule.onNodeWithTag("test-button-left").assertIsFocused()
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    @Ignore // TODO(halilibo): reenable when dpad focus modifier does not use TextFieldState
+    fun basicTextField_checkFocusNavigation_onDPadRight() {
+        setupAndEnableBasicTextField()
+        inputSingleLineTextInBasicTextField()
+
+        // Dismiss keyboard on back press
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_BACK)
+        rule.waitForIdle()
+
+        // Move focus to the focusable element on right
+        keyPressOnPhysicalKeyboard(rule, NativeKeyEvent.KEYCODE_DPAD_RIGHT)
+
+        // Check if the element to the right of text field gains focus
+        rule.onNodeWithTag("test-button-right").assertIsFocused()
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    @Ignore // TODO(halilibo): reenable when dpad focus modifier does not use TextFieldState
+    fun basicTextField_checkFocusNavigation_onDPadUp() {
+        setupAndEnableBasicTextField()
+        inputMultilineTextInBasicTextField()
+
+        // Dismiss keyboard on back press
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_BACK)
+        rule.waitForIdle()
+
+        // Move focus to the focusable element on top
+        keyPressOnPhysicalKeyboard(rule, NativeKeyEvent.KEYCODE_DPAD_UP)
+
+        // Check if the element on the top of text field gains focus
+        rule.onNodeWithTag("test-button-top").assertIsFocused()
+    }
+
+    @SdkSuppress(minSdkVersion = 22) // b/266742195
+    @Test
+    @Ignore // TODO(halilibo): re-enable when dpad focus modifier does not use TextFieldState
+    fun basicTextField_checkFocusNavigation_onDPadDown() {
+        setupAndEnableBasicTextField()
+        inputMultilineTextInBasicTextField()
+
+        // Dismiss keyboard on back press
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_BACK)
+        rule.waitForIdle()
+
+        // Move focus to the focusable element on bottom
+        keyPressOnPhysicalKeyboard(rule, NativeKeyEvent.KEYCODE_DPAD_DOWN)
+
+        // Check if the element to the bottom of text field gains focus
+        rule.onNodeWithTag("test-button-bottom").assertIsFocused()
+    }
+
+    @Ignore // b/264919150
+    @Test
+    fun basicTextField_checkKeyboardShown_onDPadCenter() {
+        setupAndEnableBasicTextField()
+        inputSingleLineTextInBasicTextField()
+
+        // Dismiss keyboard on back press
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_BACK)
+        keyboardHelper.waitForKeyboardVisibility(false)
+        rule.runOnIdle {
+            assertThat(keyboardHelper.isSoftwareKeyboardShown()).isFalse()
+        }
+
+        // Check if keyboard is enabled on Dpad center key press
+        keyPressOnPhysicalKeyboard(rule, NativeKeyEvent.KEYCODE_DPAD_CENTER)
+        keyboardHelper.waitForKeyboardVisibility(true)
+        rule.runOnIdle {
+            assertThat(keyboardHelper.isSoftwareKeyboardShown()).isTrue()
+        }
+    }
+
+    @Test
+    fun basicTextField_handlesInvalidDevice() {
+        setupAndEnableBasicTextField()
+        inputSingleLineTextInBasicTextField()
+
+        // -2 shouldn't be a valid device – we verify this below by asserting the device in the
+        // event is actually null.
+        val invalidDeviceId = -2
+        val keyCode = NativeKeyEvent.KEYCODE_DPAD_CENTER
+        val keyEventDown = KeyEvent(
+            SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
+            KeyEvent.ACTION_DOWN, keyCode, 0, 0, invalidDeviceId, 0
+        )
+        assertThat(keyEventDown.device).isNull()
+        rule.onRoot().performKeyPress(androidx.compose.ui.input.key.KeyEvent(keyEventDown))
+        rule.waitForIdle()
+        val keyEventUp = KeyEvent(
+            SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
+            KeyEvent.ACTION_UP, keyCode, 0, 0, invalidDeviceId, 0
+        )
+        rule.onRoot().performKeyPress(androidx.compose.ui.input.key.KeyEvent(keyEventUp))
+        rule.waitForIdle()
+    }
+
+    private fun setupAndEnableBasicTextField() {
+        setupContent()
+
+        rule.onNodeWithTag("test-text-field-1").assertIsFocused()
+    }
+
+    private fun inputSingleLineTextInBasicTextField() {
+        // Input "abc"
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_A)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_B)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_C)
+        rule.waitForIdle()
+    }
+
+    private fun inputMultilineTextInBasicTextField() {
+        // Input "a\nb\nc"
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_A)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_ENTER)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_B)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_ENTER)
+        rule.waitForIdle()
+        keyPressOnVirtualKeyboard(NativeKeyEvent.KEYCODE_C)
+        rule.waitForIdle()
+    }
+
+    private fun setupContent() {
+        rule.setContent {
+            keyboardHelper.initialize()
+            Column() {
+                Row(horizontalArrangement = Arrangement.Center) {
+                    TestFocusableElement(id = "top")
+                }
+                Row() {
+                    TestFocusableElement(id = "left")
+                    TestBasicTextField(id = "1", requestFocus = true)
+                    TestFocusableElement(id = "right")
+                }
+                Row(horizontalArrangement = Arrangement.Center) {
+                    TestFocusableElement(id = "bottom")
+                }
+            }
+        }
+        rule.waitForIdle()
+    }
+
+    @Composable
+    private fun TestFocusableElement(id: String) {
+        var isFocused by remember {
+            mutableStateOf(false)
+        }
+        BasicText(
+            text = "test-button-$id",
+            modifier = Modifier
+                .testTag("test-button-$id")
+                .padding(10.dp)
+                .onFocusChanged {
+                    isFocused = it.hasFocus
+                }
+                .focusable()
+                .border(2.dp, if (isFocused) Color.Green else Color.Cyan)
+        )
+    }
+
+    @Composable
+    private fun TestBasicTextField(
+        id: String,
+        requestFocus: Boolean = false
+    ) {
+        var textInput by remember {
+            mutableStateOf("")
+        }
+        var isFocused by remember {
+            mutableStateOf(false)
+        }
+        val focusRequester = remember {
+            FocusRequester()
+        }
+        val modifier = if (requestFocus) Modifier.focusRequester(focusRequester) else Modifier
+
+        BasicTextField(
+            value = textInput,
+            onValueChange = {
+                textInput = it
+            },
+            modifier = modifier
+                .testTag("test-text-field-$id")
+                .padding(10.dp)
+                .onFocusChanged {
+                    isFocused = it.isFocused || it.hasFocus
+                }
+                .border(2.dp, if (isFocused) Color.Red else Color.Transparent)
+        )
+
+        LaunchedEffect(requestFocus, focusRequester) {
+            if (requestFocus) focusRequester.requestFocus()
+        }
+    }
+
+    // Triggers a key press on the root node from a non-virtual device
+    private fun keyPressOnPhysicalKeyboard(
+        rule: ComposeContentTestRule,
+        keyCode: Int,
+        count: Int = 1
+    ) {
+        repeat(count) {
+            val deviceId = InputDevice.getDeviceIds().first { id ->
+                InputDevice.getDevice(id)?.isVirtual?.not() ?: false
+            }
+            val keyEventDown = KeyEvent(
+                SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
+                KeyEvent.ACTION_DOWN, keyCode, 0, 0, deviceId, 0
+            )
+            rule.onRoot().performKeyPress(androidx.compose.ui.input.key.KeyEvent(keyEventDown))
+            rule.waitForIdle()
+            val keyEventUp = KeyEvent(
+                SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
+                KeyEvent.ACTION_UP, keyCode, 0, 0, deviceId, 0
+            )
+            rule.onRoot().performKeyPress(androidx.compose.ui.input.key.KeyEvent(keyEventUp))
+        }
+    }
+
+    // Triggers a key press on the virtual keyboard
+    private fun keyPressOnVirtualKeyboard(keyCode: Int, count: Int = 1) {
+        repeat(count) {
+            InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode)
+        }
+    }
+}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/input/BackspaceCommandTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/input/BackspaceCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/input/BackspaceCommandTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/input/BackspaceCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/input/MoveCursorCommandTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/input/MoveCursorCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/input/MoveCursorCommandTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/input/MoveCursorCommandTest.kt
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt
new file mode 100644
index 0000000..4dbeebe
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapterTest.kt
@@ -0,0 +1,219 @@
+/*
+ * 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:OptIn(ExperimentalFoundationApi::class)
+
+package androidx.compose.foundation.text2.service
+
+import android.text.InputType
+import android.view.inputmethod.EditorInfo
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.text2.TextFieldState
+import androidx.compose.ui.platform.LocalPlatformTextInputPluginRegistry
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.ImeOptions
+import androidx.compose.ui.text.input.KeyboardCapitalization
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AndroidTextInputAdapterTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    private lateinit var adapter: AndroidTextInputAdapter
+
+    @Before
+    fun setup() {
+        rule.setContent {
+            val adapterProvider = LocalPlatformTextInputPluginRegistry.current
+            adapter = adapterProvider.rememberAdapter(AndroidTextInputPlugin)
+        }
+    }
+
+    @Test
+    fun startInputSession_returnsOpenSession() {
+        val state = TextFieldState()
+        rule.runOnUiThread {
+            val session = adapter.startInputSession(state, ImeOptions.Default)
+            assertThat(session.isOpen).isTrue()
+        }
+    }
+
+    @Test
+    fun disposedSession_returnsClosed() {
+        val state = TextFieldState()
+        rule.runOnUiThread {
+            val session = adapter.startInputSession(state, ImeOptions.Default)
+            session.dispose()
+            assertThat(session.isOpen).isFalse()
+        }
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun startingInputSessionOnNonMainThread_throwsIllegalStateException() {
+        adapter.startInputSession(TextFieldState(), ImeOptions.Default)
+    }
+
+    @Test
+    fun creatingSecondInputSession_closesFirstOne() {
+        val state = TextFieldState()
+        rule.runOnUiThread {
+            val session1 = adapter.startInputSession(state, ImeOptions.Default)
+            val session2 = adapter.startInputSession(state, ImeOptions.Default)
+
+            assertThat(session1.isOpen).isFalse()
+            assertThat(session2.isOpen).isTrue()
+        }
+    }
+
+    @Test
+    fun createInputConnection_modifiesEditorInfo() {
+        val state = TextFieldState(TextFieldValue("hello", selection = TextRange(0, 5)))
+        rule.runOnUiThread {
+            adapter.startInputSession(state, ImeOptions.Default)
+            val editorInfo = EditorInfo()
+            adapter.createInputConnection(editorInfo)
+
+            assertThat(editorInfo.initialSelStart).isEqualTo(0)
+            assertThat(editorInfo.initialSelEnd).isEqualTo(5)
+            assertThat(editorInfo.inputType).isEqualTo(
+                InputType.TYPE_CLASS_TEXT or
+                    InputType.TYPE_TEXT_FLAG_MULTI_LINE or
+                    InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+            )
+            assertThat(editorInfo.imeOptions).isEqualTo(
+                    EditorInfo.IME_FLAG_NO_FULLSCREEN or
+                    EditorInfo.IME_FLAG_NO_ENTER_ACTION
+            )
+        }
+    }
+
+    @Test
+    fun inputConnection_sendsUpdates_toActiveSession() {
+        val state1 = TextFieldState()
+        val state2 = TextFieldState()
+        rule.runOnUiThread {
+            adapter.startInputSession(state1, ImeOptions.Default)
+            adapter.startInputSession(state2, ImeOptions.Default)
+
+            val connection = adapter.createInputConnection(EditorInfo())
+
+            connection.commitText("Hello", 0)
+
+            assertThat(state1.value.text).isEqualTo("")
+            assertThat(state2.value.text).isEqualTo("Hello")
+        }
+    }
+
+    @Test
+    fun createInputConnection_updatesEditorInfo() {
+        val editorInfo = EditorInfo()
+        rule.runOnUiThread {
+            adapter.startInputSession(
+                TextFieldState(),
+                ImeOptions(
+                    singleLine = true,
+                    keyboardType = KeyboardType.Email,
+                    autoCorrect = false,
+                    imeAction = ImeAction.Search,
+                    capitalization = KeyboardCapitalization.Words
+                )
+            )
+
+            adapter.createInputConnection(editorInfo)
+
+            assertThat(editorInfo.inputType).isEqualTo(
+                InputType.TYPE_CLASS_TEXT or
+                    InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS or
+                    InputType.TYPE_TEXT_FLAG_CAP_WORDS
+            )
+            assertThat(editorInfo.imeOptions).isEqualTo(
+                EditorInfo.IME_ACTION_SEARCH or EditorInfo.IME_FLAG_NO_FULLSCREEN
+            )
+        }
+    }
+
+    @Test
+    fun createInputConnection_updatesEditorInfo_withTheLatestSession() {
+        val editorInfo = EditorInfo()
+        rule.runOnUiThread {
+            adapter.startInputSession(
+                TextFieldState(),
+                ImeOptions(
+                    keyboardType = KeyboardType.Number
+                )
+            )
+            adapter.startInputSession(
+                TextFieldState(),
+                ImeOptions(
+                    singleLine = true,
+                    keyboardType = KeyboardType.Email,
+                    autoCorrect = false,
+                    imeAction = ImeAction.Search,
+                    capitalization = KeyboardCapitalization.Words
+                )
+            )
+
+            adapter.createInputConnection(editorInfo)
+
+            assertThat(editorInfo.inputType).isEqualTo(
+                InputType.TYPE_CLASS_TEXT or
+                    InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS or
+                    InputType.TYPE_TEXT_FLAG_CAP_WORDS
+            )
+            assertThat(editorInfo.imeOptions).isEqualTo(
+                EditorInfo.IME_ACTION_SEARCH or EditorInfo.IME_FLAG_NO_FULLSCREEN
+            )
+        }
+    }
+
+    @Test
+    fun createInputConnection_updatesEditorInfo_noActiveSession() {
+        val noActiveSessionEI = EditorInfo()
+        val activeSessionEI = EditorInfo()
+        val disposedSessionEI = EditorInfo()
+        rule.runOnUiThread {
+            adapter.createInputConnection(noActiveSessionEI)
+            val session = adapter.startInputSession(
+                TextFieldState(),
+                ImeOptions(
+                    keyboardType = KeyboardType.Number
+                )
+            )
+            adapter.createInputConnection(activeSessionEI)
+            session.dispose()
+            adapter.createInputConnection(disposedSessionEI)
+
+            assertThat(noActiveSessionEI.inputType).isNotEqualTo(activeSessionEI.inputType)
+            assertThat(noActiveSessionEI.imeOptions).isNotEqualTo(activeSessionEI.imeOptions)
+
+            assertThat(noActiveSessionEI.inputType).isEqualTo(disposedSessionEI.inputType)
+            assertThat(noActiveSessionEI.imeOptions).isEqualTo(disposedSessionEI.imeOptions)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/EditorInfoTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/EditorInfoTest.kt
new file mode 100644
index 0000000..3055b66
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/EditorInfoTest.kt
@@ -0,0 +1,542 @@
+/*
+ * 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.text2.service
+
+import android.text.InputType
+import android.view.inputmethod.EditorInfo
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.ImeOptions
+import androidx.compose.ui.text.input.KeyboardCapitalization
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class EditorInfoTest {
+
+    @Test
+    fun test_fill_editor_info_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_ascii() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_number() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_phone() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Phone,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_PHONE and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_uri() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Uri,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_URI and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_email() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Email,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS and info.inputType) != 0)
+            .isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_password() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Password,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_number_password() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.NumberPassword,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_NUMBER_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_decimal_number() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Decimal,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_NUMBER_FLAG_DECIMAL and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_none() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.None
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_NONE
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_go() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Go
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_GO
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_next() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Next
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_NEXT
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_previous() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Previous
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_PREVIOUS
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_search() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Search,
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_SEARCH
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_send() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Send
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_SEND
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_done() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_DONE
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line_with_default_action() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_single_line() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_single_line_changes_ime_from_unspecified_to_done() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((EditorInfo.IME_ACTION_DONE and info.imeOptions) == 0).isFalse()
+        assertThat((EditorInfo.IME_ACTION_UNSPECIFIED and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line_not_set_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_none() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.None,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_characters() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Characters,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isFalse()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_words() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Words,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isFalse()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_sentences() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done,
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_not_added_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done,
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_auto_correct_on() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_auto_correct_off() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun autocorrect_not_added_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun initial_default_selection_info_is_set() {
+        val info = EditorInfo()
+        info.update(ImeOptions.Default)
+
+        assertThat(info.initialSelStart).isEqualTo(0)
+        assertThat(info.initialSelEnd).isEqualTo(0)
+    }
+
+    @Test
+    fun initial_selection_info_is_set() {
+        val selection = TextRange(1, 2)
+        val info = EditorInfo()
+        info.update(TextFieldValue("abc", selection), ImeOptions.Default)
+
+        assertThat(info.initialSelStart).isEqualTo(selection.start)
+        assertThat(info.initialSelEnd).isEqualTo(selection.end)
+    }
+
+    private fun EditorInfo.update(imeOptions: ImeOptions) {
+        this.update(TextFieldValue(), imeOptions)
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt
similarity index 98%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt
index 624768d..35a023d 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/androidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnectionTest.kt
@@ -26,6 +26,7 @@
 import androidx.compose.foundation.text2.input.SetSelectionCommand
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.ImeOptions
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -48,6 +49,7 @@
 
     private var isOpen: Boolean = true
     private var value: TextFieldValue = TextFieldValue()
+    private var imeOptions: ImeOptions = ImeOptions.Default
     private var onRequestEdits: ((List<EditCommand>) -> Unit)? = null
 
     private val activeSessionProvider: () -> EditableTextInputSession? = { activeSession }
@@ -62,6 +64,9 @@
             override val value: TextFieldValue
                 get() = this@StatelessInputConnectionTest.value
 
+            override val imeOptions: ImeOptions
+                get() = this@StatelessInputConnectionTest.imeOptions
+
             override fun requestEdits(editCommands: List<EditCommand>) {
                 onRequestEdits?.invoke(editCommands)
             }
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
index a62fdb5..879e105 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
@@ -16,21 +16,21 @@
 
 package androidx.compose.foundation
 
+import android.annotation.SuppressLint
 import android.os.Build
 import android.view.View
 import androidx.annotation.RequiresApi
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.collection.mutableVectorOf
-import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.layout.OnGloballyPositionedModifier
 import androidx.compose.ui.layout.boundsInRoot
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
+import androidx.compose.ui.node.GlobalPositionAwareModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.currentValueOf
+import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.platform.debugInspectorInfo
 import kotlin.math.roundToInt
 
 /**
@@ -42,11 +42,7 @@
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
         this
     } else {
-        composed(inspectorInfo = debugInspectorInfo {
-            name = "systemGestureExclusion"
-        }) {
-            excludeFromSystemGestureQ(null)
-        }
+        this then excludeFromSystemGestureQ(null)
     }
 
 /**
@@ -63,37 +59,55 @@
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
         this
     } else {
-        composed(inspectorInfo = debugInspectorInfo {
-            name = "systemGestureExclusion"
-            properties["exclusion"] = exclusion
-        }) {
-            excludeFromSystemGestureQ(exclusion)
-        }
+        this then excludeFromSystemGestureQ(exclusion)
     }
 
 @Suppress("NOTHING_TO_INLINE", "ComposableModifierFactory", "ModifierFactoryExtensionFunction")
 @RequiresApi(Build.VERSION_CODES.Q)
-@Composable
 private inline fun excludeFromSystemGestureQ(
     noinline exclusion: ((LayoutCoordinates) -> Rect)?
-): Modifier {
-    val view = LocalView.current
-    val modifier = remember(view, exclusion) { ExcludeFromSystemGestureModifier(view, exclusion) }
-    DisposableEffect(modifier) {
-        onDispose {
-            modifier.removeRect()
+): Modifier = ExcludeFromSystemGestureElement(exclusion)
+
+@RequiresApi(Build.VERSION_CODES.Q)
+private class ExcludeFromSystemGestureElement(
+    val exclusion: ((LayoutCoordinates) -> Rect)?
+) : ModifierNodeElement<ExcludeFromSystemGestureNode>() {
+    @SuppressLint("NewApi")
+    override fun create(): ExcludeFromSystemGestureNode {
+        return ExcludeFromSystemGestureNode(exclusion)
+    }
+
+    override fun update(node: ExcludeFromSystemGestureNode): ExcludeFromSystemGestureNode =
+        node.also {
+            it.exclusion = exclusion
+        }
+
+    override fun hashCode(): Int {
+        return exclusion.hashCode()
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (other !is ExcludeFromSystemGestureElement) return false
+        return exclusion == other.exclusion
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        name = "systemGestureExclusion"
+        if (exclusion != null) {
+            properties["exclusion"] = exclusion
         }
     }
-    return modifier
 }
 
 @RequiresApi(Build.VERSION_CODES.Q)
-private class ExcludeFromSystemGestureModifier(
-    val view: View,
-    val exclusion: ((LayoutCoordinates) -> Rect)?
-) : OnGloballyPositionedModifier {
+private class ExcludeFromSystemGestureNode(
+    var exclusion: ((LayoutCoordinates) -> Rect)?
+) : Modifier.Node(), GlobalPositionAwareModifierNode, CompositionLocalConsumerModifierNode {
     var rect: android.graphics.Rect? = null
 
+    private val view: View
+        get() = currentValueOf(LocalView)
+
     override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
         val newRect = if (exclusion == null) {
             val boundsInRoot = coordinates.boundsInRoot()
@@ -104,13 +118,14 @@
                 boundsInRoot.bottom.roundToInt()
             )
         } else {
-            calcBounds(coordinates, exclusion.invoke(coordinates))
+            calcBounds(coordinates, exclusion!!.invoke(coordinates))
         }
         replaceRect(newRect)
     }
 
-    fun removeRect() {
-        replaceRect(null)
+    override fun onDetach() {
+        super.onDetach()
+        replaceRect(null) // On Node detach, reset
     }
 
     fun replaceRect(newRect: android.graphics.Rect?) {
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt
new file mode 100644
index 0000000..e25f2ea
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt
@@ -0,0 +1,301 @@
+/*
+ * 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.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.text.DefaultMinLines
+import androidx.compose.foundation.text.InternalFoundationTextApi
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.text.TextDelegate
+import androidx.compose.foundation.text.heightInLines
+import androidx.compose.foundation.text.selection.LocalTextSelectionColors
+import androidx.compose.foundation.text.selection.SimpleLayout
+import androidx.compose.foundation.text.textFieldMinSize
+import androidx.compose.foundation.text2.input.CommitTextCommand
+import androidx.compose.foundation.text2.input.DeleteAllCommand
+import androidx.compose.foundation.text2.service.AndroidTextInputPlugin
+import androidx.compose.foundation.text2.service.TextInputSession
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+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.draw.drawBehind
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
+import androidx.compose.ui.layout.FirstBaseline
+import androidx.compose.ui.layout.LastBaseline
+import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFontFamilyResolver
+import androidx.compose.ui.platform.LocalPlatformTextInputPluginRegistry
+import androidx.compose.ui.semantics.disabled
+import androidx.compose.ui.semantics.imeAction
+import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.setText
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextPainter
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.unit.Density
+import kotlin.math.roundToInt
+
+/**
+ * BasicTextField2 is a new text input Composable under heavy development. Please refrain from
+ * using it in production since it has a very unstable API and implementation for the time being.
+ * Many core features like selection, cursor, gestures, etc. may fail or simply not exist.
+ *
+ * @param state State object that holds the internal state of a [BasicTextField2]
+ * @param modifier optional [Modifier] for this text field.
+ * @param enabled controls the enabled state of the [BasicTextField2]. When `false`, the text
+ * field will be neither editable nor focusable, the input of the text field will not be selectable.
+ * @param readOnly controls the editable state of the [BasicTextField2]. When `true`, the text
+ * field can not be modified, however, a user can focus it and copy text from it. Read-only text
+ * fields are usually used to display pre-filled forms that user can not edit
+ * @param textStyle Style configuration for text content that's displayed in the editor.
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this TextField. You can create and pass in your own remembered [MutableInteractionSource]
+ * if you want to observe [Interaction]s and customize the appearance / behavior of this TextField
+ * for different [Interaction]s.
+ * @param cursorBrush [Brush] to paint cursor with. If [SolidColor] with [Color.Unspecified]
+ * provided, there will be no cursor drawn
+ * @param minLines The minimum height in terms of minimum number of visible lines. It is required
+ * that 1 <= [minLines] <= [maxLines].
+ * @param maxLines The maximum height in terms of maximum number of visible lines. It is required
+ * that 1 <= [minLines] <= [maxLines].
+ * @param keyboardOptions software keyboard options that contains configuration such as
+ * [KeyboardType] and [ImeAction].
+ * @param onTextLayout Callback that is executed when a new text layout is calculated. A
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw a cursor or selection around the text. [Density]
+ * scope is the one that was used while creating the given text layout.
+ * @param decorationBox Composable lambda that allows to add decorations around text field, such
+ * as icon, placeholder, helper messages or similar, and automatically increase the hit target area
+ * of the text field. To allow you to control the placement of the inner text field relative to your
+ * decorations, the text field implementation will pass in a framework-controlled composable
+ * parameter "innerTextField" to the decorationBox lambda you provide. You must call
+ * innerTextField exactly once.
+ */
+@ExperimentalFoundationApi
+@OptIn(InternalFoundationTextApi::class)
+@Composable
+fun BasicTextField2(
+    state: TextFieldState,
+    modifier: Modifier = Modifier,
+    enabled: Boolean = true,
+    readOnly: Boolean = false,
+    textStyle: TextStyle = TextStyle.Default,
+    interactionSource: MutableInteractionSource? = null,
+    cursorBrush: Brush = SolidColor(Color.Black),
+    minLines: Int = DefaultMinLines,
+    maxLines: Int = Int.MAX_VALUE,
+    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
+    onTextLayout: Density.(TextLayoutResult) -> Unit = {},
+    decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
+        @Composable { innerTextField -> innerTextField() }
+) {
+    // only read from local and create an adapter if this text field is enabled and editable
+    val textInputAdapter = LocalPlatformTextInputPluginRegistry.takeIf { enabled && !readOnly }
+        ?.current?.rememberAdapter(AndroidTextInputPlugin)
+
+    val focusRequester = remember { FocusRequester() }
+
+    val fontFamilyResolver = LocalFontFamilyResolver.current
+    val density = LocalDensity.current
+    val selectionBackgroundColor = LocalTextSelectionColors.current.backgroundColor
+    val singleLine = minLines == 1 && maxLines == 1
+
+    val textLayoutState = remember {
+        TextLayoutState(
+            TextDelegate(
+                text = state.value.annotatedString,
+                style = textStyle,
+                density = density,
+                fontFamilyResolver = fontFamilyResolver,
+                softWrap = true,
+                placeholders = emptyList()
+            )
+        )
+    }
+
+    var isFocused by remember { mutableStateOf(false) }
+
+    val textInputSessionState = remember { mutableStateOf<TextInputSession?>(null) }
+
+    // Hide the keyboard if made disabled or read-only while focused (b/237308379).
+    if (enabled && !readOnly) {
+        // TODO(b/230536793) This is a workaround since we don't get an explicit focus blur event
+        //  when the text field is removed from the composition entirely.
+        DisposableEffect(state) {
+            if (isFocused) {
+                textInputSessionState.value = textInputAdapter?.startInputSession(
+                    state,
+                    keyboardOptions.toImeOptions(singleLine)
+                )
+            }
+            onDispose {
+                if (isFocused) {
+                    textInputSessionState.value?.dispose()
+                    textInputSessionState.value = null
+                }
+            }
+        }
+    }
+
+    val semanticsModifier = Modifier.semantics {
+        this.imeAction = keyboardOptions.imeAction
+        if (!enabled) this.disabled()
+
+        setText { text ->
+            state.editProcessor.update(
+                listOf(
+                    DeleteAllCommand,
+                    CommitTextCommand(text, 1)
+                )
+            )
+            true
+        }
+        onClick {
+            // according to the documentation, we still need to provide proper semantics actions
+            // even if the state is 'disabled'
+            if (!isFocused) {
+                focusRequester.requestFocus()
+            }
+            true
+        }
+    }
+
+    val drawModifier = Modifier.drawBehind {
+        textLayoutState.layoutResult?.let { layoutResult ->
+            // draw selection
+            val value = state.value
+            if (!value.selection.collapsed) {
+                val start = value.selection.min
+                val end = value.selection.max
+                if (start != end) {
+                    val selectionPath = layoutResult.getPathForRange(start, end)
+                    drawPath(selectionPath, color = selectionBackgroundColor)
+                }
+            }
+            // draw text
+            drawIntoCanvas { canvas ->
+                TextPainter.paint(canvas, layoutResult)
+            }
+        }
+    }
+
+    val focusModifier = Modifier
+        .focusRequester(focusRequester)
+        .onFocusChanged {
+            if (isFocused == it.isFocused) {
+                return@onFocusChanged
+            }
+            isFocused = it.isFocused
+
+            if (it.isFocused) {
+                textInputSessionState.value = textInputAdapter?.startInputSession(
+                    state,
+                    keyboardOptions.toImeOptions(singleLine)
+                )
+                // TODO(halilibo): bringIntoView
+            } else {
+                state.deselect()
+            }
+        }
+        .focusable(interactionSource = interactionSource, enabled = enabled)
+
+    val cursorModifier = Modifier.cursor(
+        textLayoutState = textLayoutState,
+        isFocused = isFocused,
+        state = state,
+        cursorBrush = cursorBrush,
+        enabled = enabled && !readOnly
+    )
+
+    val decorationModifiers = modifier
+        .then(focusModifier)
+        .then(semanticsModifier)
+        .then(TextFieldContentSemanticsElement(state, textLayoutState))
+        .clickable {
+            focusRequester.requestFocus()
+        }
+        .onGloballyPositioned {
+            textLayoutState.proxy?.decorationBoxCoordinates = it
+        }
+
+    Box(decorationModifiers) {
+        decorationBox(innerTextField = {
+            val coreModifiers = Modifier
+                .heightInLines(
+                    textStyle = textStyle,
+                    minLines = minLines,
+                    maxLines = maxLines
+                )
+                .then(drawModifier)
+                .textFieldMinSize(textStyle)
+                .then(cursorModifier)
+                .onGloballyPositioned {
+                    textLayoutState.proxy?.innerTextFieldCoordinates = it
+                }
+
+            // A custom layout that hosts TextLayout, Selection and Cursor Handles.
+            SimpleLayout(coreModifiers) {
+                // Text Layout
+                Layout { _, constraints ->
+                    val result = with(textLayoutState) {
+                        layout(
+                            text = state.value.annotatedString,
+                            textStyle = textStyle,
+                            softWrap = true,
+                            density = density,
+                            fontFamilyResolver = fontFamilyResolver,
+                            constraints = constraints,
+                            onTextLayout = onTextLayout
+                        )
+                    }
+
+                    // TODO: min height
+
+                    layout(
+                        width = result.size.width,
+                        height = result.size.height,
+                        alignmentLines = mapOf(
+                            FirstBaseline to result.firstBaseline.roundToInt(),
+                            LastBaseline to result.lastBaseline.roundToInt()
+                        )
+                    ) {}
+                }
+            }
+        })
+    }
+}
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldContentSemantics.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldContentSemantics.kt
new file mode 100644
index 0000000..43c0246
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldContentSemantics.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.text2
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.SemanticsModifierNode
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.semantics.SemanticsConfiguration
+import androidx.compose.ui.semantics.editableText
+import androidx.compose.ui.semantics.getTextLayoutResult
+import androidx.compose.ui.semantics.textSelectionRange
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextRange
+
+@OptIn(ExperimentalFoundationApi::class)
+internal class TextFieldContentSemanticsElement(
+    private val textFieldState: TextFieldState,
+    private val textLayoutState: TextLayoutState
+) : ModifierNodeElement<TextFieldContentSemanticsNode>() {
+    override fun create(): TextFieldContentSemanticsNode = TextFieldContentSemanticsNode(
+        textFieldState,
+        textLayoutState
+    )
+
+    override fun update(node: TextFieldContentSemanticsNode): TextFieldContentSemanticsNode {
+        node.textFieldState = textFieldState
+        node.textLayoutState = textLayoutState
+        return node
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is TextFieldContentSemanticsElement) return false
+
+        if (textFieldState != other.textFieldState) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        return textFieldState.hashCode()
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        // Show nothing in the inspector.
+    }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+internal data class TextFieldContentSemanticsNode(
+    var textFieldState: TextFieldState,
+    var textLayoutState: TextLayoutState
+) : Modifier.Node(), SemanticsModifierNode {
+
+    private var lastText: AnnotatedString? = null
+    private var lastSelection: TextRange? = null
+
+    private var _semanticsConfiguration: SemanticsConfiguration? = null
+
+    private fun generateSemantics(
+        text: AnnotatedString,
+        selection: TextRange
+    ): SemanticsConfiguration {
+        lastText = text
+        lastSelection = selection
+        return SemanticsConfiguration().also { configuration ->
+            configuration.getTextLayoutResult {
+                textLayoutState.layoutResult?.let { result -> it.add(result) } ?: false
+            }
+            configuration.editableText = text
+            configuration.textSelectionRange = selection
+            _semanticsConfiguration = configuration
+        }
+    }
+
+    override val semanticsConfiguration: SemanticsConfiguration
+        get() {
+            var localSemantics = _semanticsConfiguration
+            val value = textFieldState.value
+            if (localSemantics == null ||
+                lastText != value.annotatedString ||
+                lastSelection != value.selection
+            ) {
+                localSemantics = generateSemantics(value.annotatedString, value.selection)
+            }
+            return localSemantics
+        }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldCursor.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldCursor.kt
new file mode 100644
index 0000000..9a14151
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldCursor.kt
@@ -0,0 +1,98 @@
+/*
+ * 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.text2
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.infiniteRepeatable
+import androidx.compose.animation.core.keyframes
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.MotionDurationScale
+import androidx.compose.ui.composed
+import androidx.compose.ui.draw.drawWithContent
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.isUnspecified
+import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.withContext
+
+@OptIn(ExperimentalFoundationApi::class)
+internal fun Modifier.cursor(
+    textLayoutState: TextLayoutState,
+    isFocused: Boolean,
+    state: TextFieldState,
+    cursorBrush: Brush,
+    enabled: Boolean
+) = if (enabled) composed {
+    val cursorAlpha = remember { Animatable(1f) }
+    val isBrushSpecified = !(cursorBrush is SolidColor && cursorBrush.value.isUnspecified)
+    val value = state.value
+    if (isFocused && value.selection.collapsed && isBrushSpecified) {
+        LaunchedEffect(value.annotatedString, value.selection) {
+            // Animate the cursor even when animations are disabled by the system.
+            withContext(FixedMotionDurationScale) {
+                // ensure that the value is always 1f _this_ frame by calling snapTo
+                cursorAlpha.snapTo(1f)
+                // then start the cursor blinking on animation clock (500ms on to start)
+                cursorAlpha.animateTo(0f, cursorAnimationSpec)
+            }
+        }
+        drawWithContent {
+            this.drawContent()
+            val cursorAlphaValue = cursorAlpha.value.coerceIn(0f, 1f)
+            if (cursorAlphaValue != 0f) {
+                val cursorRect = textLayoutState.layoutResult?.getCursorRect(value.selection.start)
+                    ?: Rect(0f, 0f, 0f, 0f)
+                val cursorWidth = DefaultCursorThickness.toPx()
+                val cursorX = (cursorRect.left + cursorWidth / 2)
+                    .coerceAtMost(size.width - cursorWidth / 2)
+
+                drawLine(
+                    cursorBrush,
+                    Offset(cursorX, cursorRect.top),
+                    Offset(cursorX, cursorRect.bottom),
+                    alpha = cursorAlphaValue,
+                    strokeWidth = cursorWidth
+                )
+            }
+        }
+    } else {
+        Modifier
+    }
+} else this
+
+private val cursorAnimationSpec: AnimationSpec<Float> = infiniteRepeatable(
+    animation = keyframes {
+        durationMillis = 1000
+        1f at 0
+        1f at 499
+        0f at 500
+        0f at 999
+    }
+)
+
+internal val DefaultCursorThickness = 2.dp
+
+private object FixedMotionDurationScale : MotionDurationScale {
+    override val scaleFactor: Float
+        get() = 1f
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/TextFieldState.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldState.kt
similarity index 89%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/TextFieldState.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldState.kt
index 8e456e9..ca62583 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/TextFieldState.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextFieldState.kt
@@ -16,10 +16,12 @@
 
 package androidx.compose.foundation.text2
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.text2.input.EditProcessor
 import androidx.compose.ui.text.TextRange
 import androidx.compose.ui.text.input.TextFieldValue
 
+@ExperimentalFoundationApi
 class TextFieldState(
     initialValue: TextFieldValue = TextFieldValue(),
     filter: TextEditFilter = TextEditFilter.Default
@@ -31,6 +33,7 @@
         get() = editProcessor.value
 }
 
+@ExperimentalFoundationApi
 fun interface TextEditFilter {
 
     fun filter(oldValue: TextFieldValue, newValue: TextFieldValue): TextFieldValue
@@ -40,6 +43,7 @@
     }
 }
 
+@OptIn(ExperimentalFoundationApi::class)
 internal fun TextFieldState.deselect() {
     editProcessor.reset(value.copy(selection = TextRange.Zero, composition = TextRange.Zero))
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextLayoutState.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextLayoutState.kt
new file mode 100644
index 0000000..545af5b
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/TextLayoutState.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.text2
+
+import androidx.compose.foundation.text.InternalFoundationTextApi
+import androidx.compose.foundation.text.TextDelegate
+import androidx.compose.foundation.text.TextLayoutResultProxy
+import androidx.compose.foundation.text.updateTextDelegate
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
+import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
+
+@OptIn(InternalFoundationTextApi::class)
+internal class TextLayoutState(initialTextDelegate: TextDelegate) {
+    /**
+     * Set of parameters and an internal cache to compute text layout.
+     */
+    var textDelegate: TextDelegate by mutableStateOf(initialTextDelegate)
+        private set
+
+    /**
+     * Text Layout State.
+     */
+    var layoutResult: TextLayoutResult? by mutableStateOf(null)
+        private set
+
+    /**
+     * A helper class to find positions on text layout relative to wrapping decoration box.
+     */
+    var proxy: TextLayoutResultProxy? = null
+
+    fun MeasureScope.layout(
+        text: AnnotatedString,
+        textStyle: TextStyle,
+        softWrap: Boolean,
+        density: Density,
+        fontFamilyResolver: FontFamily.Resolver,
+        constraints: Constraints,
+        onTextLayout: Density.(TextLayoutResult) -> Unit
+    ): TextLayoutResult {
+        val prevResult = Snapshot.withoutReadObservation { layoutResult }
+
+        val newTextDelegate = updateTextDelegate(
+            current = textDelegate,
+            text = text,
+            style = textStyle,
+            softWrap = softWrap,
+            density = density,
+            fontFamilyResolver = fontFamilyResolver,
+            placeholders = emptyList(),
+        )
+
+        return newTextDelegate.layout(
+            layoutDirection = layoutDirection,
+            constraints = constraints,
+            prevResult = prevResult
+        ).also {
+            textDelegate = newTextDelegate
+            if (prevResult != it) {
+                onTextLayout(it)
+            }
+            layoutResult = it
+            proxy = TextLayoutResultProxy(it)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/ApplyEditCommand.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/ApplyEditCommand.kt
similarity index 93%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/ApplyEditCommand.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/ApplyEditCommand.kt
index 0a1412a..685449b 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/ApplyEditCommand.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/ApplyEditCommand.kt
@@ -174,15 +174,17 @@
 private fun EditingBuffer.applyDeleteSurroundingTextCommand(
     deleteSurroundingTextCommand: DeleteSurroundingTextCommand
 ) {
-    delete(
-        selectionEnd,
-        minOf(selectionEnd + deleteSurroundingTextCommand.lengthAfterCursor, length)
-    )
+    // calculate the end with safe addition since lengthAfterCursor can be set to e.g. Int.MAX
+    // by the input
+    val end = selectionEnd.addExactOrElse(deleteSurroundingTextCommand.lengthAfterCursor) { length }
+    delete(selectionEnd, minOf(end, length))
 
-    delete(
-        maxOf(0, selectionStart - deleteSurroundingTextCommand.lengthBeforeCursor),
-        selectionStart
-    )
+    // calculate the start with safe subtraction since lengthBeforeCursor can be set to e.g.
+    // Int.MAX by the input
+    val start = selectionStart.subtractExactOrElse(
+        deleteSurroundingTextCommand.lengthBeforeCursor
+    ) { 0 }
+    delete(maxOf(0, start), selectionStart)
 }
 
 private fun EditingBuffer.applyBackspaceCommand() {
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EditCommand.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditCommand.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EditCommand.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditCommand.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EdiProcessor.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditProcessor.kt
similarity index 98%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EdiProcessor.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditProcessor.kt
index a3a04e9..ed691a5 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EdiProcessor.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditProcessor.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.text2.input
 
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.text2.TextEditFilter
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.getValue
@@ -35,6 +36,7 @@
  * When [TextInputService] provides [EditCommand]s, they should be applied to the internal
  * buffer using [apply].
  */
+@OptIn(ExperimentalFoundationApi::class)
 internal class EditProcessor(
     initialValue: TextFieldValue = TextFieldValue(
         EmptyAnnotatedString,
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EditingBuffer.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditingBuffer.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/EditingBuffer.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/EditingBuffer.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/GapBuffer.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/GapBuffer.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/input/GapBuffer.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/GapBuffer.kt
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/MathUItils.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/MathUItils.kt
new file mode 100644
index 0000000..9ac4025
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/input/MathUItils.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.foundation.text2.input
+
+/**
+ * Adds [this] and [right], and if an overflow occurs returns result of [defaultValue].
+ */
+internal inline fun Int.addExactOrElse(right: Int, defaultValue: () -> Int): Int {
+    val result = this + right
+    // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+    return if (this xor result and (right xor result) < 0) defaultValue() else result
+}
+
+/**
+ * Subtracts [right] from [this], and if an overflow occurs returns result of [defaultValue].
+ */
+internal fun Int.subtractExactOrElse(right: Int, defaultValue: () -> Int): Int {
+    val result = this - right
+    // HD 2-12 Overflow iff the arguments have different signs and
+    // the sign of the result is different from the sign of x
+    return if (this xor right and (this xor result) < 0) defaultValue() else result
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt
similarity index 71%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt
index a7d49ba..d1ef7d2 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputAdapter.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalFoundationApi::class)
+
 package androidx.compose.foundation.text2.service
 
 import android.os.Looper
@@ -23,11 +25,16 @@
 import android.view.View
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
+import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.text2.TextFieldState
+import androidx.compose.foundation.text2.input.CommitTextCommand
 import androidx.compose.foundation.text2.input.EditCommand
 import androidx.compose.foundation.text2.input.EditProcessor
 import androidx.compose.runtime.collection.mutableVectorOf
-import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.ImeOptions
+import androidx.compose.ui.text.input.KeyboardCapitalization
+import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.input.PlatformTextInput
 import androidx.compose.ui.text.input.PlatformTextInputAdapter
 import androidx.compose.ui.text.input.TextFieldValue
@@ -38,7 +45,6 @@
 private const val DEBUG = true
 private const val TAG = "BasicTextInputAdapter"
 
-@OptIn(ExperimentalTextApi::class)
 internal class AndroidTextInputAdapter constructor(
     view: View,
     private val platformTextInput: PlatformTextInput
@@ -50,20 +56,25 @@
 
     private val textInputCommandExecutor = TextInputCommandExecutor(view, inputMethodManager)
 
-    override val inputForTests: TextInputForTests
-        get() = error("Not implemented")
+    override val inputForTests: TextInputForTests = object : TextInputForTests {
+        private fun requireSession(): EditableTextInputSession =
+            currentTextInputSession ?: error("There is no active input session. Missing a focus?")
+
+        override fun inputTextForTest(text: String) {
+            requireSession().requestEdits(
+                listOf(CommitTextCommand(text, 1))
+            )
+        }
+    }
 
     override fun createInputConnection(outAttrs: EditorInfo): InputConnection {
         logDebug { "createInputConnection" }
         val value = currentTextInputSession?.value ?: TextFieldValue()
+        val imeOptions = currentTextInputSession?.imeOptions ?: ImeOptions.Default
 
         logDebug { "createInputConnection.value = $value" }
 
-        outAttrs.initialSelStart = value.selection.min
-        outAttrs.initialSelEnd = value.selection.max
-        outAttrs.inputType = InputType.TYPE_CLASS_TEXT
-        EditorInfoCompat.setInitialSurroundingText(outAttrs, value.text)
-        outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
+        outAttrs.update(value, imeOptions)
 
         return StatelessInputConnection(
             activeSessionProvider = { currentTextInputSession }
@@ -88,7 +99,8 @@
     }
 
     fun startInputSession(
-        state: TextFieldState
+        state: TextFieldState,
+        imeOptions: ImeOptions
     ): TextInputSession {
         if (!isMainThread()) {
             throw IllegalStateException("Input sessions can only be started from the main thread.")
@@ -105,6 +117,8 @@
             override val value: TextFieldValue
                 get() = state.value
 
+            override val imeOptions: ImeOptions = imeOptions
+
             override fun requestEdits(editCommands: List<EditCommand>) {
                 state.editProcessor.update(editCommands)
             }
@@ -283,6 +297,99 @@
     postFrameCallback { runnable.run() }
 }
 
+/**
+ * Fills necessary info of EditorInfo.
+ */
+internal fun EditorInfo.update(textFieldValue: TextFieldValue, imeOptions: ImeOptions) {
+    this.imeOptions = when (imeOptions.imeAction) {
+        ImeAction.Default -> {
+            if (imeOptions.singleLine) {
+                // this is the last resort to enable single line
+                // Android IME still shows return key even if multi line is not send
+                // TextView.java#onCreateInputConnection
+                EditorInfo.IME_ACTION_DONE
+            } else {
+                EditorInfo.IME_ACTION_UNSPECIFIED
+            }
+        }
+        ImeAction.None -> EditorInfo.IME_ACTION_NONE
+        ImeAction.Go -> EditorInfo.IME_ACTION_GO
+        ImeAction.Next -> EditorInfo.IME_ACTION_NEXT
+        ImeAction.Previous -> EditorInfo.IME_ACTION_PREVIOUS
+        ImeAction.Search -> EditorInfo.IME_ACTION_SEARCH
+        ImeAction.Send -> EditorInfo.IME_ACTION_SEND
+        ImeAction.Done -> EditorInfo.IME_ACTION_DONE
+        else -> error("invalid ImeAction")
+    }
+
+    this.inputType = when (imeOptions.keyboardType) {
+        KeyboardType.Text -> InputType.TYPE_CLASS_TEXT
+        KeyboardType.Ascii -> {
+            this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_FORCE_ASCII
+            InputType.TYPE_CLASS_TEXT
+        }
+        KeyboardType.Number ->
+            InputType.TYPE_CLASS_NUMBER
+        KeyboardType.Phone ->
+            InputType.TYPE_CLASS_PHONE
+        KeyboardType.Uri ->
+            InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI
+        KeyboardType.Email ->
+            InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+        KeyboardType.Password ->
+            InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_PASSWORD
+        KeyboardType.NumberPassword ->
+            InputType.TYPE_CLASS_NUMBER or EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD
+        KeyboardType.Decimal ->
+            InputType.TYPE_CLASS_NUMBER or EditorInfo.TYPE_NUMBER_FLAG_DECIMAL
+        else -> error("Invalid Keyboard Type")
+    }
+
+    if (!imeOptions.singleLine) {
+        if (hasFlag(this.inputType, InputType.TYPE_CLASS_TEXT)) {
+            // TextView.java#setInputTypeSingleLine
+            this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_MULTI_LINE
+
+            if (imeOptions.imeAction == ImeAction.Default) {
+                this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_NO_ENTER_ACTION
+            }
+        }
+    }
+
+    if (hasFlag(this.inputType, InputType.TYPE_CLASS_TEXT)) {
+        when (imeOptions.capitalization) {
+            KeyboardCapitalization.Characters -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
+            }
+
+            KeyboardCapitalization.Words -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_WORDS
+            }
+
+            KeyboardCapitalization.Sentences -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+            }
+
+            else -> {
+                /* do nothing */
+            }
+        }
+
+        if (imeOptions.autoCorrect) {
+            this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+        }
+    }
+
+    this.initialSelStart = textFieldValue.selection.start
+    this.initialSelEnd = textFieldValue.selection.end
+
+    EditorInfoCompat.setInitialSurroundingText(this, textFieldValue.text)
+
+    this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_NO_FULLSCREEN
+}
+
+private fun hasFlag(bits: Int, flag: Int): Boolean = (bits and flag) == flag
+
 private fun logDebug(tag: String = TAG, content: () -> String) {
     if (DEBUG) {
         Log.d(tag, content())
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt
similarity index 92%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt
index 94b5951..9fb5c65 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/AndroidTextInputPlugin.kt
@@ -17,11 +17,9 @@
 package androidx.compose.foundation.text2.service
 
 import android.view.View
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.input.PlatformTextInput
 import androidx.compose.ui.text.input.PlatformTextInputPlugin
 
-@OptIn(ExperimentalTextApi::class)
 internal object AndroidTextInputPlugin : PlatformTextInputPlugin<AndroidTextInputAdapter> {
 
     override fun createAdapter(
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/ComposeInputMethodManager.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/ComposeInputMethodManager.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/ComposeInputMethodManager.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/ComposeInputMethodManager.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/StatelessInputConnection.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnection.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/StatelessInputConnection.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/StatelessInputConnection.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/TextInputSession.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/TextInputSession.kt
similarity index 89%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/TextInputSession.kt
rename to compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/TextInputSession.kt
index c18e20e..4e29e6b 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/text2/service/TextInputSession.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text2/service/TextInputSession.kt
@@ -16,8 +16,10 @@
 
 package androidx.compose.foundation.text2.service
 
+import android.view.inputmethod.InputConnection
 import androidx.compose.foundation.text2.TextFieldState
 import androidx.compose.foundation.text2.input.EditCommand
+import androidx.compose.ui.text.input.ImeOptions
 import androidx.compose.ui.text.input.TextFieldValue
 
 /**
@@ -59,4 +61,9 @@
      * Callback to execute for InputConnection to communicate the changes requested by the IME.
      */
     fun requestEdits(editCommands: List<EditCommand>)
+
+    /**
+     * IME configuration to use when creating new [InputConnection]s while this session is active.
+     */
+    val imeOptions: ImeOptions
 }
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
index b249514..0e24104 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
@@ -40,13 +40,16 @@
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.modifier.ModifierLocalConsumer
 import androidx.compose.ui.modifier.ModifierLocalReadScope
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.SemanticsModifierNode
+import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.debugInspectorInfo
 import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsConfiguration
 import androidx.compose.ui.semantics.disabled
 import androidx.compose.ui.semantics.onClick
 import androidx.compose.ui.semantics.onLongClick
 import androidx.compose.ui.semantics.role
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.center
 import androidx.compose.ui.unit.toOffset
 import kotlinx.coroutines.CoroutineScope
@@ -512,23 +515,6 @@
     onLongClick: (() -> Unit)? = null,
     onClick: () -> Unit
 ): Modifier {
-    fun Modifier.clickSemantics() = this.semantics(mergeDescendants = true) {
-        if (role != null) {
-            this.role = role
-        }
-        // b/156468846:  add long click semantics and double click if needed
-        onClick(
-            action = { onClick(); true },
-            label = onClickLabel
-        )
-        if (onLongClick != null) {
-            onLongClick(action = { onLongClick(); true }, label = onLongClickLabel)
-        }
-        if (!enabled) {
-            disabled()
-        }
-    }
-
     fun Modifier.detectPressAndClickFromKey() = this.onKeyEvent { keyEvent ->
         when {
             enabled && keyEvent.isPress -> {
@@ -555,11 +541,101 @@
             else -> false
         }
     }
-    return this
-        .clickSemantics()
-        .detectPressAndClickFromKey()
-        .indication(interactionSource, indication)
-        .hoverable(enabled = enabled, interactionSource = interactionSource)
-        .focusableInNonTouchMode(enabled = enabled, interactionSource = interactionSource)
-        .then(gestureModifiers)
+    return this then
+        ClickableSemanticsElement(
+            enabled = enabled,
+            role = role,
+            onLongClickLabel = onLongClickLabel,
+            onLongClick = onLongClick,
+            onClickLabel = onClickLabel,
+            onClick = onClick
+        )
+            .detectPressAndClickFromKey()
+            .indication(interactionSource, indication)
+            .hoverable(enabled = enabled, interactionSource = interactionSource)
+            .focusableInNonTouchMode(enabled = enabled, interactionSource = interactionSource)
+            .then(gestureModifiers)
+}
+
+private class ClickableSemanticsElement(
+    private val enabled: Boolean,
+    private val role: Role?,
+    private val onLongClickLabel: String?,
+    private val onLongClick: (() -> Unit)?,
+    private val onClickLabel: String?,
+    private val onClick: () -> Unit
+) : ModifierNodeElement<ClickableSemanticsNode>() {
+    override fun create() = ClickableSemanticsNode(
+        enabled = enabled,
+        role = role,
+        onLongClickLabel = onLongClickLabel,
+        onLongClick = onLongClick,
+        onClickLabel = onClickLabel,
+        onClick = onClick
+    )
+
+    override fun update(node: ClickableSemanticsNode) = node.also {
+        it.enabled = enabled
+        it.role = role
+        it.onLongClickLabel = onLongClickLabel
+        it.onLongClick = onLongClick
+        it.onClickLabel = onClickLabel
+        it.onClick = onClick
+    }
+
+    override fun InspectorInfo.inspectableProperties() = Unit
+
+    override fun hashCode(): Int {
+        var result = enabled.hashCode()
+        result = 31 * result + role.hashCode()
+        result = 31 * result + onLongClickLabel.hashCode()
+        result = 31 * result + onLongClick.hashCode()
+        result = 31 * result + onClickLabel.hashCode()
+        result = 31 * result + onClick.hashCode()
+        return result
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is ClickableSemanticsElement) return false
+
+        if (enabled != other.enabled) return false
+        if (role != other.role) return false
+        if (onLongClickLabel != other.onLongClickLabel) return false
+        if (onLongClick != other.onLongClick) return false
+        if (onClickLabel != other.onClickLabel) return false
+        if (onClick != other.onClick) return false
+
+        return true
+    }
+}
+
+private class ClickableSemanticsNode(
+    var enabled: Boolean,
+    var role: Role?,
+    var onLongClickLabel: String?,
+    var onLongClick: (() -> Unit)?,
+    var onClickLabel: String?,
+    var onClick: () -> Unit,
+) : SemanticsModifierNode, Modifier.Node() {
+    override val semanticsConfiguration
+        get() = SemanticsConfiguration().apply {
+            isMergingSemanticsOfDescendants = true
+            if (this@ClickableSemanticsNode.role != null) {
+                role = this@ClickableSemanticsNode.role!!
+            }
+            onClick(
+                action = { onClick(); true },
+                label = onClickLabel
+            )
+            if (onLongClick != null) {
+                onLongClick(
+                    action = { onLongClick?.invoke(); true },
+                    label = onLongClickLabel
+                )
+            }
+            if (!enabled) {
+                disabled()
+            }
+        }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
index 0b6ea3e..4f2ae94 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
@@ -18,20 +18,14 @@
 
 import androidx.compose.foundation.interaction.HoverInteraction
 import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.LaunchedEffect
-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.Modifier
-import androidx.compose.ui.composed
+import androidx.compose.ui.input.pointer.PointerEvent
+import androidx.compose.ui.input.pointer.PointerEventPass
 import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.platform.debugInspectorInfo
-import kotlinx.coroutines.currentCoroutineContext
-import kotlinx.coroutines.isActive
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.PointerInputModifierNode
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.unit.IntSize
 import kotlinx.coroutines.launch
 
 /**
@@ -46,15 +40,67 @@
 fun Modifier.hoverable(
     interactionSource: MutableInteractionSource,
     enabled: Boolean = true
-): Modifier = composed(
-    inspectorInfo = debugInspectorInfo {
+) = this then if (enabled) HoverableElement(interactionSource) else Modifier
+
+private class HoverableElement(
+    private val interactionSource: MutableInteractionSource
+) : ModifierNodeElement<HoverableNode>() {
+    override fun create() = HoverableNode(interactionSource)
+
+    override fun update(node: HoverableNode) = node.apply {
+        updateInteractionSource(interactionSource)
+    }
+
+    override fun hashCode(): Int {
+        return 31 * interactionSource.hashCode()
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is HoverableElement) return false
+        if (other.interactionSource != interactionSource) return false
+        return true
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
         name = "hoverable"
         properties["interactionSource"] = interactionSource
-        properties["enabled"] = enabled
     }
-) {
-    val scope = rememberCoroutineScope()
-    var hoverInteraction by remember { mutableStateOf<HoverInteraction.Enter?>(null) }
+}
+
+private class HoverableNode(
+    private var interactionSource: MutableInteractionSource
+) : PointerInputModifierNode, Modifier.Node() {
+    private var hoverInteraction: HoverInteraction.Enter? = null
+
+    fun updateInteractionSource(interactionSource: MutableInteractionSource) {
+        if (this.interactionSource != interactionSource) {
+            tryEmitExit()
+            // b/273699888 TODO: Define behavior if there is an ongoing hover
+            this.interactionSource = interactionSource
+        }
+    }
+
+    override fun onPointerEvent(
+        pointerEvent: PointerEvent,
+        pass: PointerEventPass,
+        bounds: IntSize
+    ) {
+        if (pass == PointerEventPass.Main) {
+            when (pointerEvent.type) {
+                PointerEventType.Enter -> coroutineScope.launch { emitEnter() }
+                PointerEventType.Exit -> coroutineScope.launch { emitExit() }
+            }
+        }
+    }
+
+    override fun onCancelPointerInput() {
+        tryEmitExit()
+    }
+
+    override fun onDetach() {
+        tryEmitExit()
+    }
 
     suspend fun emitEnter() {
         if (hoverInteraction == null) {
@@ -79,37 +125,4 @@
             hoverInteraction = null
         }
     }
-
-    DisposableEffect(interactionSource) {
-        onDispose { tryEmitExit() }
-    }
-    LaunchedEffect(enabled) {
-        if (!enabled) {
-            emitExit()
-        }
-    }
-
-    if (enabled) {
-        Modifier
-// TODO(b/202505231):
-//  because we only react to input events, and not on layout changes, we can have a situation when
-//  Composable is under the cursor, but not hovered. To fix that, we have two ways:
-//  a. Trigger Enter/Exit on any layout change, inside Owner
-//  b. Manually react on layout changes via Modifier.onGloballyPosition, and check something like
-//  LocalPointerPosition.current
-            .pointerInput(interactionSource) {
-                val currentContext = currentCoroutineContext()
-                awaitPointerEventScope {
-                    while (currentContext.isActive) {
-                        val event = awaitPointerEvent()
-                        when (event.type) {
-                            PointerEventType.Enter -> scope.launch { emitEnter() }
-                            PointerEventType.Exit -> scope.launch { emitExit() }
-                        }
-                    }
-                }
-            }
-    } else {
-        Modifier
-    }
 }
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/AnnotatedStringResolveInlineContent.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/AnnotatedStringResolveInlineContent.kt
similarity index 89%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/AnnotatedStringResolveInlineContent.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/AnnotatedStringResolveInlineContent.kt
index 26ebe38..71c3b75 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/AnnotatedStringResolveInlineContent.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/AnnotatedStringResolveInlineContent.kt
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text
+package androidx.compose.foundation.text
 
-import androidx.compose.foundation.text.InlineTextContent
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.text.AnnotatedString
@@ -82,9 +81,5 @@
     }
 }
 
-private typealias PlaceholderRange = AnnotatedString.Range<Placeholder>
-private typealias InlineContentRange = AnnotatedString.Range<@Composable (String) -> Unit>
-internal const val INLINE_CONTENT_TAG = "androidx.compose.foundation.text.inlineContent"
-
 private val EmptyInlineContent: Pair<List<PlaceholderRange>, List<InlineContentRange>> =
     Pair(emptyList(), emptyList())
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicText.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicText.kt
index 64c39235..ae0cf5c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicText.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/BasicText.kt
@@ -22,9 +22,12 @@
 import androidx.compose.foundation.text.selection.hasSelection
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.currentComposer
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.platform.LocalDensity
@@ -62,12 +65,26 @@
     text: String,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     overflow: TextOverflow = TextOverflow.Clip,
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE,
     minLines: Int = 1
 ) {
+    @Suppress("DEPRECATION")
+    if (NewTextRendering1_5) {
+        TextUsingModifier(
+            text = text,
+            modifier = modifier,
+            style = style,
+            onTextLayout = onTextLayout,
+            overflow = overflow,
+            softWrap = softWrap,
+            maxLines = maxLines,
+            minLines = minLines
+        )
+        return
+    }
     // NOTE(text-perf-review): consider precomputing layout here by pushing text to a channel...
     // something like:
     // remember(text) { precomputeTextLayout(text) }
@@ -133,7 +150,7 @@
             )
         )
     }
-    state.onTextLayout = onTextLayout
+    state.onTextLayout = onTextLayout ?: {}
     controller.update(selectionRegistrar)
     if (selectionRegistrar != null) {
         state.selectionBackgroundColor = LocalTextSelectionColors.current.backgroundColor
@@ -177,13 +194,28 @@
     text: AnnotatedString,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     overflow: TextOverflow = TextOverflow.Clip,
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE,
     minLines: Int = 1,
     inlineContent: Map<String, InlineTextContent> = mapOf()
 ) {
+    @Suppress("DEPRECATION")
+    if (NewTextRendering1_5) {
+        TextUsingModifier(
+            text = text,
+            modifier = modifier,
+            style = style,
+            onTextLayout = onTextLayout,
+            overflow = overflow,
+            softWrap = softWrap,
+            maxLines = maxLines,
+            minLines = minLines,
+            inlineContent = inlineContent
+        )
+        return
+    }
     // Unlike text field for which validation happens inside the 'heightInLines' modifier, in text
     // 'maxLines' are not handled by the modifier but instead passed to the StaticLayout, therefore
     // we perform validation here
@@ -250,7 +282,7 @@
             )
         )
     }
-    state.onTextLayout = onTextLayout
+    state.onTextLayout = onTextLayout ?: {}
     state.selectionBackgroundColor = selectionBackgroundColor
 
     controller.update(selectionRegistrar)
@@ -274,7 +306,7 @@
     text: String,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     overflow: TextOverflow = TextOverflow.Clip,
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE
@@ -297,7 +329,7 @@
     text: AnnotatedString,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     overflow: TextOverflow = TextOverflow.Clip,
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE,
@@ -317,6 +349,20 @@
 }
 
 /**
+ * Optionally use legacy text rendering stack from 1.4.
+ *
+ * This flag will be removed by 1.5 beta01. If you find any issues with the new stack, flip this
+ * flag to false to confirm they are newly introduced then file a bug.
+ */
+@Deprecated(
+    message = "This flag will be removed by 1.5 beta1 and should only be used for debugging " +
+        "text related issues in the new 1.5 text stack.",
+    replaceWith = ReplaceWith(""),
+    level = DeprecationLevel.WARNING
+)
+var NewTextRendering1_5: Boolean by mutableStateOf(false)
+
+/**
  * A custom saver that won't save if no selection is active.
  */
 private fun selectionIdSaver(selectionRegistrar: SelectionRegistrar?) = Saver<Long, Long>(
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
index cd39f68..5e1150a 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
@@ -45,7 +45,6 @@
 import androidx.compose.ui.layout.IntrinsicMeasurable
 import androidx.compose.ui.layout.IntrinsicMeasureScope
 import androidx.compose.ui.layout.LastBaseline
-import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.LayoutCoordinates
 import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasurePolicy
@@ -66,29 +65,11 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.util.fastForEach
-import androidx.compose.ui.util.fastMap
 import kotlin.math.floor
 import kotlin.math.roundToInt
 
-private typealias PlaceholderRange = AnnotatedString.Range<Placeholder>
-private typealias InlineContentRange = AnnotatedString.Range<@Composable (String) -> Unit>
-
-@Composable
-internal fun InlineChildren(
-    text: AnnotatedString,
-    inlineContents: List<InlineContentRange>
-) {
-    inlineContents.fastForEach { (content, start, end) ->
-        Layout(
-            content = { content(text.subSequence(start, end).text) }
-        ) { children, constrains ->
-            val placeables = children.fastMap { it.measure(constrains) }
-            layout(width = constrains.maxWidth, height = constrains.maxHeight) {
-                placeables.fastForEach { it.placeRelative(0, 0) }
-            }
-        }
-    }
-}
+internal typealias PlaceholderRange = AnnotatedString.Range<Placeholder>
+internal typealias InlineContentRange = AnnotatedString.Range<@Composable (String) -> Unit>
 
 // NOTE(text-perf-review): consider merging this with TextDelegate?
 @OptIn(InternalFoundationTextApi::class)
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextUsingModifier.kt
similarity index 88%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifier.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextUsingModifier.kt
index ca96202..c759b2b 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/TextUsingModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextUsingModifier.kt
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text
+package androidx.compose.foundation.text
 
-import androidx.compose.foundation.newtext.text.copypasta.selection.LocalSelectionRegistrar
-import androidx.compose.foundation.newtext.text.copypasta.selection.LocalTextSelectionColors
-import androidx.compose.foundation.newtext.text.modifiers.SelectableTextAnnotatedStringElement
-import androidx.compose.foundation.newtext.text.modifiers.TextAnnotatedStringElement
-import androidx.compose.foundation.newtext.text.modifiers.SelectionController
-import androidx.compose.foundation.newtext.text.modifiers.TextStringSimpleElement
-import androidx.compose.foundation.newtext.text.modifiers.validateMinMaxLines
-import androidx.compose.foundation.text.InlineTextContent
+import androidx.compose.foundation.fastMapIndexedNotNull
+import androidx.compose.foundation.text.modifiers.SelectableTextAnnotatedStringElement
+import androidx.compose.foundation.text.modifiers.SelectionController
+import androidx.compose.foundation.text.modifiers.TextAnnotatedStringElement
+import androidx.compose.foundation.text.modifiers.TextStringSimpleElement
+import androidx.compose.foundation.text.selection.LocalSelectionRegistrar
+import androidx.compose.foundation.text.selection.LocalTextSelectionColors
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.layout.Layout
@@ -38,7 +36,6 @@
 import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.platform.LocalFontFamilyResolver
 import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.Placeholder
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.TextStyle
@@ -51,12 +48,12 @@
 import kotlin.math.roundToInt
 
 /**
- * Rewrite of BasicText
+ * Implementation of [BasicText] using the new Modifier system.
+ *
+ * All features are the same.
  */
-@OptIn(ExperimentalComposeUiApi::class)
-@ExperimentalTextApi
 @Composable
-fun TextUsingModifier(
+internal fun TextUsingModifier(
     text: String,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
@@ -108,15 +105,16 @@
 }
 
 /**
- * Rewrite of BasicText
+ * Implementation of [BasicText] using the new Modifier system.
+ *
+ * All features are the same.
  */
-@ExperimentalTextApi
 @Composable
-fun TextUsingModifier(
+internal fun TextUsingModifier(
     text: AnnotatedString,
     modifier: Modifier = Modifier,
     style: TextStyle = TextStyle.Default,
-    onTextLayout: (TextLayoutResult) -> Unit = {},
+    onTextLayout: ((TextLayoutResult) -> Unit)? = null,
     overflow: TextOverflow = TextOverflow.Clip,
     softWrap: Boolean = true,
     maxLines: Int = Int.MAX_VALUE,
@@ -224,7 +222,6 @@
     }
 }
 
-@OptIn(ExperimentalComposeUiApi::class)
 private fun Modifier.textModifier(
     text: AnnotatedString,
     style: TextStyle,
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MinMaxLinesCoercer.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinMaxLinesCoercer.kt
similarity index 92%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MinMaxLinesCoercer.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinMaxLinesCoercer.kt
index c616ac9..8ab511d 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MinMaxLinesCoercer.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MinMaxLinesCoercer.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
 import androidx.compose.ui.text.Paragraph
 import androidx.compose.ui.text.TextStyle
@@ -25,6 +25,11 @@
 import androidx.compose.ui.unit.LayoutDirection
 import kotlin.math.roundToInt
 
+/**
+ * Coerce min and max lines into actual constraints.
+ *
+ * Results are cached with the assumption that there is typically N=1 style being coerced at once.
+ */
 internal class MinMaxLinesCoercer private constructor(
     val layoutDirection: LayoutDirection,
     val inputTextStyle: TextStyle,
@@ -141,12 +146,3 @@
 private const val DefaultWidthCharCount = 10 // min width for TextField is 10 chars long
 private val EmptyTextReplacement = "H".repeat(DefaultWidthCharCount) // just a reference character.
 private val TwoLineTextReplacement = EmptyTextReplacement + "\n" + EmptyTextReplacement
-
-internal fun validateMinMaxLines(minLines: Int, maxLines: Int) {
-    require(minLines > 0 && maxLines > 0) {
-        "both minLines $minLines and maxLines $maxLines must be greater than zero"
-    }
-    require(minLines <= maxLines) {
-        "minLines $minLines must be less than or equal to maxLines $maxLines"
-    }
-}
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ModifierUtils.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ModifierUtils.kt
new file mode 100644
index 0000000..050ff6d
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ModifierUtils.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.modifiers
+
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Constraints
+
+internal fun Constraints.maxWidthForTextLayout(
+    softWrap: Boolean,
+    overflow: TextOverflow
+): Int {
+    val widthMatters = softWrap || overflow == TextOverflow.Ellipsis
+    val maxWidth = if (widthMatters && hasBoundedWidth) {
+        maxWidth
+    } else {
+        Constraints.Infinity
+    }
+    return maxWidth
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCache.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCache.kt
similarity index 81%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCache.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCache.kt
index fa494d1..53b531f 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/MultiParagraphLayoutCache.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/MultiParagraphLayoutCache.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.foundation.newtext.text.ceilToIntPx
+import androidx.compose.foundation.text.DefaultMinLines
+import androidx.compose.foundation.text.ceilToIntPx
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.MultiParagraph
 import androidx.compose.ui.text.MultiParagraphIntrinsics
@@ -35,6 +35,14 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.constrain
 
+/**
+ * Performs text layout using [MultiParagraph].
+ *
+ * Results are cached whenever possible, for example when only constraints change in a way that
+ * cannot reflow text.
+ *
+ * All measurements are cached.
+ */
 internal class MultiParagraphLayoutCache(
     private var text: AnnotatedString,
     private var style: TextStyle,
@@ -45,7 +53,14 @@
     private var minLines: Int = DefaultMinLines,
     private var placeholders: List<AnnotatedString.Range<Placeholder>>? = null,
 ) {
+    /**
+     * Convert min max lines into actual constraints
+     */
     private var minMaxLinesCoercer: MinMaxLinesCoercer? = null
+
+    /**
+     * Density that text layout is performed in
+     */
     internal var density: Density? = null
         set(value) {
             val localField = field
@@ -61,40 +76,39 @@
             }
         }
 
-    /*@VisibleForTesting*/
-    // NOTE(text-perf-review): it seems like TextDelegate essentially guarantees that we use
-    // MultiParagraph. Can we have a fast-path that uses just Paragraph in simpler cases (ie,
-    // String)?
+    /**
+     * [MultiParagraphIntrinsics] will be initialized lazily
+     */
     private var paragraphIntrinsics: MultiParagraphIntrinsics? = null
 
+    /**
+     * [LayoutDirection] used to compute [MultiParagraphIntrinsics]
+     */
     private var intrinsicsLayoutDirection: LayoutDirection? = null
 
+    /**
+     * Cached value of final [TextLayoutResult]
+     */
     private var layoutCache: TextLayoutResult? = null
+
+    /**
+     * Last intrinsic height computation
+     *
+     * - first = input width
+     * - second = output height
+     */
     private var cachedIntrinsicHeight: Pair<Int, Int>? = null
 
-    private val nonNullIntrinsics: MultiParagraphIntrinsics
-        get() = paragraphIntrinsics ?: throw IllegalStateException(
-            "MeasureScope.measure() must be called first to query text intrinsics"
-        )
-
     /**
-     * The width for text if all soft wrap opportunities were taken.
-     *
-     * Valid only after [layoutWithConstraints] has been called.
+     * The last computed TextLayoutResult, or throws if not initialized.
      */
-    val minIntrinsicWidth: Int get() = nonNullIntrinsics.minIntrinsicWidth.ceilToIntPx()
-
-    /**
-     * The width at which increasing the width of the text no lonfger decreases the height.
-     *
-     * Valid only after [layoutWithConstraints] has been called.
-     */
-    val maxIntrinsicWidth: Int get() = nonNullIntrinsics.maxIntrinsicWidth.ceilToIntPx()
-
-    val layout: TextLayoutResult
+    val textLayoutResult: TextLayoutResult
         get() = layoutCache
-            ?: throw IllegalStateException("You must call doLayoutInConstraints first")
+            ?: throw IllegalStateException("You must call layoutWithConstraints first")
 
+    /**
+     * The last computed TextLayoutResult, or null if not initialized.
+     */
     val layoutOrNull: TextLayoutResult?
         get() = layoutCache
 
@@ -156,7 +170,10 @@
         return true
     }
 
-    fun intrinsicHeightAt(width: Int, layoutDirection: LayoutDirection): Int {
+    /**
+     * The natural height of text at [width] in [layoutDirection]
+     */
+    fun intrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int {
         cachedIntrinsicHeight?.let { (prevWidth, prevHeight) ->
             if (width == prevWidth) return prevHeight
         }
@@ -169,6 +186,9 @@
         return result
     }
 
+    /**
+     * Call when any parameters change, invalidation is a result of calling this method.
+     */
     fun update(
         text: AnnotatedString,
         style: TextStyle,
@@ -190,7 +210,12 @@
         markDirty()
     }
 
-    private fun setLayoutDirection(layoutDirection: LayoutDirection) {
+    /**
+     * Minimum information required to compute [MultiParagraphIntrinsics].
+     *
+     * After calling paragraphIntrinsics is cached.
+     */
+    private fun setLayoutDirection(layoutDirection: LayoutDirection): MultiParagraphIntrinsics {
         val localIntrinsics = paragraphIntrinsics
         val intrinsics = if (
             localIntrinsics == null ||
@@ -210,6 +235,7 @@
         }
 
         paragraphIntrinsics = intrinsics
+        return intrinsics
     }
 
     /**
@@ -222,7 +248,7 @@
         constraints: Constraints,
         layoutDirection: LayoutDirection
     ): MultiParagraph {
-        setLayoutDirection(layoutDirection)
+        val localParagraphIntrinsics = setLayoutDirection(layoutDirection)
 
         val minWidth = constraints.minWidth
         val widthMatters = softWrap || overflow == TextOverflow.Ellipsis
@@ -261,11 +287,11 @@
         val width = if (minWidth == maxWidth) {
             maxWidth
         } else {
-            maxIntrinsicWidth.coerceIn(minWidth, maxWidth)
+            localParagraphIntrinsics.maxIntrinsicWidth.ceilToIntPx().coerceIn(minWidth, maxWidth)
         }
 
         return MultiParagraph(
-            intrinsics = nonNullIntrinsics,
+            intrinsics = localParagraphIntrinsics,
             constraints = Constraints(maxWidth = width, maxHeight = constraints.maxHeight),
             // This is a fallback behavior for ellipsis. Native
             maxLines = finalMaxLines,
@@ -273,6 +299,10 @@
         )
     }
 
+    /**
+     * Attempt to compute if the new layout will be the same for the given constraints and
+     * layoutDirection.
+     */
     private fun TextLayoutResult?.newLayoutWillBeDifferent(
         constraints: Constraints,
         layoutDirection: LayoutDirection
@@ -330,6 +360,11 @@
         return false
     }
 
+    /**
+     * Compute the maxWidth for text layout from [Constraints]
+     *
+     * Falls back to [paragraphIntrinsics.maxIntrinsicWidth] when not exact constraints.
+     */
     private fun maxWidth(constraints: Constraints): Int {
         val minWidth = constraints.minWidth
         val widthMatters = softWrap || overflow == TextOverflow.Ellipsis
@@ -341,7 +376,7 @@
         return if (minWidth == maxWidth) {
             maxWidth
         } else {
-            maxIntrinsicWidth.coerceIn(minWidth, maxWidth)
+            paragraphIntrinsics!!.maxIntrinsicWidth.ceilToIntPx().coerceIn(minWidth, maxWidth)
         }
     }
 
@@ -349,4 +384,18 @@
         paragraphIntrinsics = null
         layoutCache = null
     }
+
+    /**
+     * The width at which increasing the width of the text no longer decreases the height.
+     */
+    fun maxIntrinsicWidth(layoutDirection: LayoutDirection): Int {
+        return setLayoutDirection(layoutDirection).maxIntrinsicWidth.ceilToIntPx()
+    }
+
+    /**
+     * The width for text if all soft wrap opportunities were taken.
+     */
+    fun minIntrinsicWidth(layoutDirection: LayoutDirection): Int {
+        return setLayoutDirection(layoutDirection).minIntrinsicWidth.ceilToIntPx()
+    }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/ParagraphLayoutCache.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ParagraphLayoutCache.kt
similarity index 81%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/ParagraphLayoutCache.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ParagraphLayoutCache.kt
index 45330d0..dadc584 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/ParagraphLayoutCache.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/ParagraphLayoutCache.kt
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.foundation.newtext.text.ceilToIntPx
+import androidx.compose.foundation.text.DefaultMinLines
+import androidx.compose.foundation.text.ceilToIntPx
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.MultiParagraph
 import androidx.compose.ui.text.MultiParagraphIntrinsics
@@ -36,6 +36,14 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.constrain
 
+/**
+ * Performs text layout using [Paragraph].
+ *
+ * Results are cached whenever possible, for example when only constraints change in a way that
+ * cannot reflow text.
+ *
+ * All measurements are cached.
+ */
 internal class ParagraphLayoutCache(
     private var text: String,
     private var style: TextStyle,
@@ -45,6 +53,9 @@
     private var maxLines: Int = Int.MAX_VALUE,
     private var minLines: Int = DefaultMinLines,
 ) {
+    /**
+     * Density that text layout is performed in
+     */
     internal var density: Density? = null
         set(value) {
             val localField = field
@@ -65,43 +76,60 @@
                 markDirty()
             }
         }
+
+    /**
+     * Read to set up a snapshot observer observe changes to fonts.
+     */
     internal val observeFontChanges: Unit
         get() {
             paragraphIntrinsics?.hasStaleResolvedFonts
         }
 
+    /**
+     * The last computed paragraph
+     */
     internal var paragraph: Paragraph? = null
+
+    /**
+     * The text did overflow
+     */
     internal var didOverflow: Boolean = false
+
+    /**
+     * The last computed layout size (as would have been reported in TextLayoutResult)
+     */
     internal var layoutSize: IntSize = IntSize(0, 0)
 
+    /**
+     * Convert min max lines into actual constraints
+     */
     private var minMaxLinesCoercer: MinMaxLinesCoercer? = null
+
+    /**
+     * [ParagraphIntrinsics] will be initialized lazily
+     */
     private var paragraphIntrinsics: ParagraphIntrinsics? = null
 
+    /**
+     * [LayoutDirection] used to compute [ParagraphIntrinsics]
+     */
     private var intrinsicsLayoutDirection: LayoutDirection? = null
+
+    /**
+     * Constraints passed to last layout.
+     */
     private var prevConstraints: Constraints = Constraints.fixed(0, 0)
 
-    private var cachedIntrinsicWidth: Int = -1
+    /**
+     * Input width for the last call to [intrinsicHeight]
+     */
+    private var cachedIntrinsicHeightInputWidth: Int = -1
+
+    /**
+     * Output height for last call to [intrinsicHeight] at [cachedIntrinsicHeightInputWidth]
+     */
     private var cachedIntrinsicHeight: Int = -1
 
-    private val nonNullIntrinsics: ParagraphIntrinsics
-        get() = paragraphIntrinsics ?: throw IllegalStateException(
-            "MeasureScope.measure() must be called first to query text intrinsics"
-        )
-
-    /**
-     * The width for text if all soft wrap opportunities were taken.
-     *
-     * Valid only after [layoutWithConstraints] has been called.
-     */
-    val minIntrinsicWidth: Int get() = nonNullIntrinsics.minIntrinsicWidth.ceilToIntPx()
-
-    /**
-     * The width at which increasing the width of the text no lonfger decreases the height.
-     *
-     * Valid only after [layoutWithConstraints] has been called.
-     */
-    val maxIntrinsicWidth: Int get() = nonNullIntrinsics.maxIntrinsicWidth.ceilToIntPx()
-
     /**
      * Update layout constraints for this text
      *
@@ -147,8 +175,11 @@
         return true
     }
 
-    fun intrinsicHeightAt(width: Int, layoutDirection: LayoutDirection): Int {
-        val localWidth = cachedIntrinsicWidth
+    /**
+     * The natural height of text at [width] in [layoutDirection]
+     */
+    fun intrinsicHeight(width: Int, layoutDirection: LayoutDirection): Int {
+        val localWidth = cachedIntrinsicHeightInputWidth
         val localHeght = cachedIntrinsicHeight
         if (width == localWidth && localWidth != -1) return localHeght
         val result = layoutText(
@@ -156,11 +187,14 @@
             layoutDirection
         ).height.ceilToIntPx()
 
-        cachedIntrinsicWidth = width
+        cachedIntrinsicHeightInputWidth = width
         cachedIntrinsicHeight = result
         return result
     }
 
+    /**
+     * Call when any parameters change, invalidation is a result of calling this method.
+     */
     fun update(
         text: String,
         style: TextStyle,
@@ -180,7 +214,12 @@
         markDirty()
     }
 
-    private fun setLayoutDirection(layoutDirection: LayoutDirection) {
+    /**
+     * Minimum information required to compute [MultiParagraphIntrinsics].
+     *
+     * After calling paragraphIntrinsics is cached.
+     */
+    private fun setLayoutDirection(layoutDirection: LayoutDirection): ParagraphIntrinsics {
         val localIntrinsics = paragraphIntrinsics
         val intrinsics = if (
             localIntrinsics == null ||
@@ -198,6 +237,7 @@
             localIntrinsics
         }
         paragraphIntrinsics = intrinsics
+        return intrinsics
     }
 
     /**
@@ -210,7 +250,7 @@
         constraints: Constraints,
         layoutDirection: LayoutDirection
     ): Paragraph {
-        setLayoutDirection(layoutDirection)
+        val localParagraphIntrinsics = setLayoutDirection(layoutDirection)
 
         val minWidth = constraints.minWidth
         val widthMatters = softWrap || overflow == TextOverflow.Ellipsis
@@ -249,12 +289,12 @@
         val width = if (minWidth == maxWidth) {
             maxWidth
         } else {
-            maxIntrinsicWidth.coerceIn(minWidth, maxWidth)
+            localParagraphIntrinsics.maxIntrinsicWidth.ceilToIntPx().coerceIn(minWidth, maxWidth)
         }
 
         val finalConstraints = Constraints(maxWidth = width, maxHeight = constraints.maxHeight)
         return Paragraph(
-            paragraphIntrinsics = nonNullIntrinsics,
+            paragraphIntrinsics = paragraphIntrinsics!!,
             constraints = finalConstraints,
             // This is a fallback behavior for ellipsis. Native
             maxLines = finalMaxLines,
@@ -262,6 +302,10 @@
         )
     }
 
+    /**
+     * Attempt to compute if the new layout will be the same for the given constraints and
+     * layoutDirection.
+     */
     private fun newLayoutWillBeDifferent(
         constraints: Constraints,
         layoutDirection: LayoutDirection
@@ -302,14 +346,6 @@
             }
         }
 
-        // check any constraint width changes for single line text
-        if (!canWrap &&
-            (constraints.maxWidth != prevConstraints.maxWidth ||
-                (constraints.minWidth != prevConstraints.minWidth))) {
-            // no soft wrap and width is different, always invalidate
-            return true
-        }
-
         // if we get here width won't change, height may be clipped
         if (constraints.maxHeight < localParagraph.height) {
             // vertical clip changes
@@ -320,6 +356,11 @@
         return false
     }
 
+    /**
+     * Compute the maxWidth for text layout from [Constraints]
+     *
+     * Falls back to [paragraphIntrinsics.maxIntrinsicWidth] when not exact constraints.
+     */
     private fun maxWidth(constraints: Constraints): Int {
         val minWidth = constraints.minWidth
         val widthMatters = softWrap || overflow == TextOverflow.Ellipsis
@@ -331,7 +372,7 @@
         return if (minWidth == maxWidth) {
             maxWidth
         } else {
-            maxIntrinsicWidth.coerceIn(minWidth, maxWidth)
+            paragraphIntrinsics!!.maxIntrinsicWidth.ceilToIntPx().coerceIn(minWidth, maxWidth)
         }
     }
 
@@ -339,7 +380,7 @@
         paragraph = null
         paragraphIntrinsics = null
         intrinsicsLayoutDirection = null
-        cachedIntrinsicWidth = -1
+        cachedIntrinsicHeightInputWidth = -1
         cachedIntrinsicHeight = -1
         prevConstraints = Constraints.fixed(0, 0)
         layoutSize = IntSize(0, 0)
@@ -347,7 +388,11 @@
     }
 
     /**
-     * This does an entire Text layout to produce the result, it is slow
+     * Compute a [TextLayoutResult] for the current Layout values.
+     *
+     * This does an entire Text layout to produce the result, it is slow.
+     *
+     * Exposed for semantics GetTextLayoutResult
      */
     fun slowCreateTextLayoutResultOrNull(): TextLayoutResult? {
         // make sure we're in a valid place
@@ -386,4 +431,18 @@
             layoutSize
         )
     }
+
+    /**
+     * The width for text if all soft wrap opportunities were taken.
+     */
+    fun minIntrinsicWidth(layoutDirection: LayoutDirection): Int {
+        return setLayoutDirection(layoutDirection).minIntrinsicWidth.ceilToIntPx()
+    }
+
+    /**
+     * The width at which increasing the width of the text no lonfger decreases the height.
+     */
+    fun maxIntrinsicWidth(layoutDirection: LayoutDirection): Int {
+        return setLayoutDirection(layoutDirection).maxIntrinsicWidth.ceilToIntPx()
+    }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
similarity index 95%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringElement.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
index 0b4fa32..b2293d4 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringElement.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.InspectorInfo
@@ -28,7 +27,9 @@
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.style.TextOverflow
 
-@ExperimentalComposeUiApi
+/**
+ * Element for any text that is in a selection container.
+ */
 internal data class SelectableTextAnnotatedStringElement(
     private val text: AnnotatedString,
     private val style: TextStyle,
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
similarity index 95%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringNode.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
index c369c40..9680f3b 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectableTextAnnotatedStringNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectableTextAnnotatedStringNode.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.drawscope.ContentDrawScope
 import androidx.compose.ui.layout.IntrinsicMeasurable
@@ -41,7 +40,11 @@
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.Constraints
 
-@OptIn(ExperimentalComposeUiApi::class)
+/**
+ * Node for any text that is in a selection container.
+ *
+ * This adds [GlobalPositionAwareModifierNode].
+ */
 internal class SelectableTextAnnotatedStringNode(
     text: AnnotatedString,
     style: TextStyle,
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectionController.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.kt
similarity index 90%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectionController.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.kt
index ed21488..01e71a8 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/SelectionController.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/SelectionController.kt
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.copypasta.TextDragObserver
-import androidx.compose.foundation.newtext.text.copypasta.detectDragGesturesAfterLongPressWithObserver
-import androidx.compose.foundation.newtext.text.copypasta.selection.MouseSelectionObserver
-import androidx.compose.foundation.newtext.text.copypasta.selection.MultiWidgetSelectionDelegate
-import androidx.compose.foundation.newtext.text.copypasta.selection.Selectable
-import androidx.compose.foundation.newtext.text.copypasta.selection.SelectionAdjustment
-import androidx.compose.foundation.newtext.text.copypasta.selection.SelectionRegistrar
-import androidx.compose.foundation.newtext.text.copypasta.selection.hasSelection
-import androidx.compose.foundation.newtext.text.copypasta.selection.mouseSelectionDetector
-import androidx.compose.foundation.newtext.text.copypasta.textPointerIcon
+import androidx.compose.foundation.text.TextDragObserver
+import androidx.compose.foundation.text.detectDragGesturesAfterLongPressWithObserver
+import androidx.compose.foundation.text.isInTouchMode
+import androidx.compose.foundation.text.selection.MouseSelectionObserver
+import androidx.compose.foundation.text.selection.MultiWidgetSelectionDelegate
+import androidx.compose.foundation.text.selection.Selectable
+import androidx.compose.foundation.text.selection.SelectionAdjustment
+import androidx.compose.foundation.text.selection.SelectionRegistrar
+import androidx.compose.foundation.text.selection.hasSelection
+import androidx.compose.foundation.text.selection.mouseSelectionDetector
+import androidx.compose.foundation.text.textPointerHoverIcon
+import androidx.compose.foundation.text.textPointerIcon
 import androidx.compose.runtime.RememberObserver
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
@@ -45,8 +47,10 @@
     }
 }
 
+/**
+ * Holder for selection modifiers while we wait for pointerInput to be ported to new modifiers.
+ */
 // This is _basically_ a Modifier.Node but moved into remember because we need to do pointerInput
-// TODO: Refactor when Modifier.pointerInput is available for delegation
 internal class SelectionController(
     private val selectionRegistrar: SelectionRegistrar,
     private val backgroundSelectionColor: Color
@@ -60,9 +64,8 @@
         selectableId = selectableId,
         layoutCoordinates = { params.layoutCoordinates },
         textLayoutResult = { params.textLayoutResult },
-        // TODO: Use real isInTouchMode on merge
-        isInTouchMode = true /* fake it to android hardcode */
-    )
+        isInTouchMode = isInTouchMode
+    ).textPointerHoverIcon(selectionRegistrar)
 
     override fun onRemembered() {
         selectable = selectionRegistrar.subscribe(
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
similarity index 94%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringElement.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
index e25f48a..377e096 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringElement.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.InspectorInfo
@@ -28,7 +27,11 @@
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.style.TextOverflow
 
-@ExperimentalComposeUiApi
+/**
+ * Modifier element for any Text with [AnnotatedString] or [onTextLayout] parameters
+ *
+ * This is slower than [TextAnnotatedStringElement]
+ */
 internal class TextAnnotatedStringElement(
     private val text: AnnotatedString,
     private val style: TextStyle,
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
similarity index 91%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringNode.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
index 164c4fb..dc4e9b9 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextAnnotatedStringNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.drawscope.ContentDrawScope
@@ -51,7 +50,9 @@
 import androidx.compose.ui.unit.Density
 import kotlin.math.roundToInt
 
-@OptIn(ExperimentalComposeUiApi::class)
+/**
+ * Node that implements Text for [AnnotatedString] or [onTextLayout] parameters.
+ */
 internal class TextAnnotatedStringNode(
     private var text: AnnotatedString,
     private var style: TextStyle,
@@ -89,12 +90,18 @@
         return layoutCache.also { it.density = density }
     }
 
+    /**
+     * Element has text parameters to update
+     */
     fun updateText(text: AnnotatedString): Boolean {
         if (this.text == text) return false
         this.text = text
         return true
     }
 
+    /**
+     * Element has layout parameters to update
+     */
     fun updateLayoutRelatedArgs(
         style: TextStyle,
         placeholders: List<AnnotatedString.Range<Placeholder>>?,
@@ -120,7 +127,7 @@
         }
 
         if (this.maxLines != maxLines) {
-            this.maxLines != maxLines
+            this.maxLines = maxLines
             changed = true
         }
 
@@ -142,6 +149,9 @@
         return changed
     }
 
+    /**
+     * Element has callback parameters to update
+     */
     fun updateCallbacks(
         onTextLayout: ((TextLayoutResult) -> Unit)?,
         onPlaceholderLayout: ((List<Rect?>) -> Unit)?,
@@ -166,6 +176,9 @@
         return changed
     }
 
+    /**
+     * Do appropriate invalidate calls based on the results of update above.
+     */
     fun doInvalidations(
         textChanged: Boolean,
         layoutChanged: Boolean,
@@ -233,6 +246,9 @@
         return measureScope.measure(measurable, constraints)
     }
 
+    /**
+     * Text layout is performed here.
+     */
     override fun MeasureScope.measure(
         measurable: Measurable,
         constraints: Constraints
@@ -240,7 +256,7 @@
         val layoutCache = getLayoutCache(this)
 
         val didChangeLayout = layoutCache.layoutWithConstraints(constraints, layoutDirection)
-        val textLayoutResult = layoutCache.layout
+        val textLayoutResult = layoutCache.textLayoutResult
 
         // ensure measure restarts when hasStaleResolvedFonts by reading in measure
         textLayoutResult.multiParagraph.intrinsics.hasStaleResolvedFonts
@@ -272,7 +288,7 @@
             baselineCache!!
         ) {
             // this is basically a graphicsLayer
-            placeable.place(0, 0)
+            placeable.placeWithLayer(0, 0)
         }
     }
 
@@ -288,7 +304,7 @@
         measurable: IntrinsicMeasurable,
         height: Int
     ): Int {
-        return getLayoutCache(this).minIntrinsicWidth
+        return getLayoutCache(this).minIntrinsicWidth(layoutDirection)
     }
 
     fun minIntrinsicHeightNonExtension(
@@ -302,7 +318,7 @@
     override fun IntrinsicMeasureScope.minIntrinsicHeight(
         measurable: IntrinsicMeasurable,
         width: Int
-    ): Int = getLayoutCache(this).intrinsicHeightAt(width, layoutDirection)
+    ): Int = getLayoutCache(this).intrinsicHeight(width, layoutDirection)
 
     fun maxIntrinsicWidthNonExtension(
         intrinsicMeasureScope: IntrinsicMeasureScope,
@@ -313,7 +329,7 @@
     override fun IntrinsicMeasureScope.maxIntrinsicWidth(
         measurable: IntrinsicMeasurable,
         height: Int
-    ): Int = getLayoutCache(this).maxIntrinsicWidth
+    ): Int = getLayoutCache(this).maxIntrinsicWidth(layoutDirection)
 
     fun maxIntrinsicHeightNonExtension(
         intrinsicMeasureScope: IntrinsicMeasureScope,
@@ -324,7 +340,7 @@
     override fun IntrinsicMeasureScope.maxIntrinsicHeight(
         measurable: IntrinsicMeasurable,
         width: Int
-    ): Int = getLayoutCache(this).intrinsicHeightAt(width, layoutDirection)
+    ): Int = getLayoutCache(this).intrinsicHeight(width, layoutDirection)
 
     fun drawNonExtension(
         contentDrawScope: ContentDrawScope
@@ -335,7 +351,7 @@
     override fun ContentDrawScope.draw() {
         selectionController?.draw(this)
         drawIntoCanvas { canvas ->
-            TextPainter.paint(canvas, requireNotNull(layoutCache.layout))
+            TextPainter.paint(canvas, requireNotNull(layoutCache.textLayoutResult))
         }
         if (!placeholders.isNullOrEmpty()) {
             drawContent()
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleElement.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
similarity index 90%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleElement.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
index 797e399..63be1b7 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleElement.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleElement.kt
@@ -14,17 +14,21 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.style.TextOverflow
 
-@ExperimentalComposeUiApi
+/**
+ * Modifier element for any Text with [AnnotatedString] or [onTextLayout] parameters
+ *
+ * This is slower than [TextAnnotatedStringElement]
+ */
 internal class TextStringSimpleElement(
     private val text: String,
     private val style: TextStyle,
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleNode.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
similarity index 90%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleNode.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
index a90ff59..c1249c9 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/modifiers/TextStringSimpleNode.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextStringSimpleNode.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.modifiers
+package androidx.compose.foundation.text.modifiers
 
-import androidx.compose.foundation.newtext.text.DefaultMinLines
-import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.foundation.text.DefaultMinLines
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Rect
@@ -55,7 +54,13 @@
 import androidx.compose.ui.unit.Density
 import kotlin.math.roundToInt
 
-@OptIn(ExperimentalComposeUiApi::class)
+/**
+ * Node that implements Text for [String].
+ *
+ * It has reduced functionality, and as a result gains in performance.
+ *
+ * Note that this Node never calculates [TextLayoutResult] unless needed by semantics.
+ */
 internal class TextStringSimpleNode(
     private var text: String,
     private var style: TextStyle,
@@ -88,12 +93,18 @@
         return layoutCache.also { it.density = density }
     }
 
+    /**
+     * Element has text params to update
+     */
     fun updateText(text: String): Boolean {
         if (this.text == text) return false
         this.text = text
         return true
     }
 
+    /**
+     * Element has layout related params to update
+     */
     fun updateLayoutRelatedArgs(
         style: TextStyle,
         minLines: Int,
@@ -114,7 +125,7 @@
         }
 
         if (this.maxLines != maxLines) {
-            this.maxLines != maxLines
+            this.maxLines = maxLines
             changed = true
         }
 
@@ -136,6 +147,9 @@
         return changed
     }
 
+    /**
+     * request invalidate based on the results of [updateText] and [updateLayoutRelatedArgs]
+     */
     fun doInvalidations(
         textChanged: Boolean,
         layoutChanged: Boolean
@@ -194,6 +208,9 @@
             return localSemantics
         }
 
+    /**
+     * Text layout happens here
+     */
     override fun MeasureScope.measure(
         measurable: Measurable,
         constraints: Constraints
@@ -228,7 +245,7 @@
             baselineCache!!
         ) {
             // this is basically a graphicsLayer
-            placeable.place(0, 0)
+            placeable.placeWithLayer(0, 0)
         }
     }
 
@@ -236,24 +253,27 @@
         measurable: IntrinsicMeasurable,
         height: Int
     ): Int {
-        return getLayoutCache(this).minIntrinsicWidth
+        return getLayoutCache(this).minIntrinsicWidth(layoutDirection)
     }
 
     override fun IntrinsicMeasureScope.minIntrinsicHeight(
         measurable: IntrinsicMeasurable,
         width: Int
-    ): Int = getLayoutCache(this).intrinsicHeightAt(width, layoutDirection)
+    ): Int = getLayoutCache(this).intrinsicHeight(width, layoutDirection)
 
     override fun IntrinsicMeasureScope.maxIntrinsicWidth(
         measurable: IntrinsicMeasurable,
         height: Int
-    ): Int = getLayoutCache(this).maxIntrinsicWidth
+    ): Int = getLayoutCache(this).maxIntrinsicWidth(layoutDirection)
 
     override fun IntrinsicMeasureScope.maxIntrinsicHeight(
         measurable: IntrinsicMeasurable,
         width: Int
-    ): Int = getLayoutCache(this).intrinsicHeightAt(width, layoutDirection)
+    ): Int = getLayoutCache(this).intrinsicHeight(width, layoutDirection)
 
+    /**
+     * Optimized Text draw.
+     */
     @OptIn(ExperimentalTextApi::class)
     override fun ContentDrawScope.draw() {
         val localParagraph = requireNotNull(layoutCache.paragraph)
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/CommitTextCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/CommitTextCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/CommitTextCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/CommitTextCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextInCodePointsCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextInCodePointsCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextInCodePointsCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/DeleteSurroundingTextInCodePointsCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditProcessorTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditProcessorTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditProcessorTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditProcessorTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferDeleteRangeTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferDeleteRangeTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferDeleteRangeTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferDeleteRangeTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/EditingBufferTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/FinishComposingTextCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/FinishComposingTextCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/FinishComposingTextCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/FinishComposingTextCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/GapBufferTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/GapBufferTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/GapBufferTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/GapBufferTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingRegionCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingRegionCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingRegionCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingRegionCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingTextCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingTextCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingTextCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetComposingTextCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetSelectionCommandTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetSelectionCommandTest.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/SetSelectionCommandTest.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/SetSelectionCommandTest.kt
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/matchers/EditBufferSubject.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/matchers/EditBufferSubject.kt
similarity index 100%
rename from compose/foundation/foundation/integration-tests/foundation-demos/src/test/kotlin/androidx/compose/foundation/text2/input/matchers/EditBufferSubject.kt
rename to compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/text2/input/matchers/EditBufferSubject.kt
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
index 140b281..d47a856 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
@@ -31,6 +31,7 @@
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.NewTextRendering1_5
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.integration.demos.common.ActivityDemo
 import androidx.compose.integration.demos.common.ComposableDemo
@@ -51,6 +52,7 @@
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
 import androidx.compose.material3.TopAppBar
 import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.material3.TopAppBarScrollBehavior
@@ -252,6 +254,7 @@
             actions = {
                 AppBarIcons.Filter(onClick = onStartFiltering)
                 AppBarIcons.Settings(onClick = launchSettings)
+                AppBarIcons.NewTextToggler()
             }
         )
     }
@@ -282,6 +285,24 @@
             Icon(Icons.Filled.Settings, null)
         }
     }
+
+    @Suppress("DEPRECATION")
+    @Composable
+    fun NewTextToggler() {
+        val isNewText = NewTextRendering1_5
+        val onClick = {
+            NewTextRendering1_5 = !NewTextRendering1_5
+        }
+        if (isNewText) {
+            TextButton(onClick = onClick) {
+                Text("New\nText!")
+            }
+        } else {
+            TextButton(onClick = onClick) {
+                Text("Old\nText")
+            }
+        }
+    }
 }
 
 @Composable
diff --git a/compose/integration-tests/material-catalog/src/main/AndroidManifest.xml b/compose/integration-tests/material-catalog/src/main/AndroidManifest.xml
index eb40d79..9b0c25a 100644
--- a/compose/integration-tests/material-catalog/src/main/AndroidManifest.xml
+++ b/compose/integration-tests/material-catalog/src/main/AndroidManifest.xml
@@ -21,6 +21,7 @@
     <application
         android:label="@string/compose_material_catalog"
         android:icon="@mipmap/ic_launcher"
+        android:supportsRtl="true"
         android:theme="@style/Theme.Catalog">
         <activity android:name=".CatalogActivity" android:exported="true">
             <intent-filter>
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 82ec5ec..ccbd6ff 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
@@ -33,6 +33,7 @@
 import androidx.compose.material.samples.ButtonWithIconSample
 import androidx.compose.material.samples.CardSample
 import androidx.compose.material.samples.CheckboxSample
+import androidx.compose.material.samples.ChipGroupReflowSample
 import androidx.compose.material.samples.ChipGroupSingleLineSample
 import androidx.compose.material.samples.ChipSample
 import androidx.compose.material.samples.CircularProgressIndicatorSample
@@ -300,6 +301,13 @@
         sourceUrl = ChipsExampleSourceUrl
     ) {
         ChipGroupSingleLineSample()
+    },
+    Example(
+        name = ::ChipGroupReflowSample.name,
+        description = ChipsExampleDescription,
+        sourceUrl = ChipsExampleSourceUrl
+    ) {
+        ChipGroupReflowSample()
     }
 )
 
diff --git a/compose/material/material/samples/build.gradle b/compose/material/material/samples/build.gradle
index eda78e0..0b5f612 100644
--- a/compose/material/material/samples/build.gradle
+++ b/compose/material/material/samples/build.gradle
@@ -32,7 +32,7 @@
 
     implementation("androidx.compose.animation:animation:1.2.1")
     implementation("androidx.compose.foundation:foundation:1.2.1")
-    implementation("androidx.compose.foundation:foundation-layout:1.2.1")
+    implementation("androidx.compose.foundation:foundation-layout:1.4.0-beta02")
     implementation(project(":compose:material:material"))
     implementation("androidx.compose.runtime:runtime:1.2.1")
     implementation("androidx.compose.ui:ui:1.2.1")
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ChipSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ChipSamples.kt
index c72e08d..14a45d5 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ChipSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ChipSamples.kt
@@ -18,10 +18,15 @@
 
 import androidx.annotation.Sampled
 import androidx.compose.foundation.horizontalScroll
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ExperimentalLayoutApi
+import androidx.compose.foundation.layout.FlowRow
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.material.Chip
 import androidx.compose.material.ChipDefaults
@@ -143,7 +148,7 @@
         Row(modifier = Modifier.horizontalScroll(rememberScrollState())) {
             repeat(9) { index ->
                 Chip(
-                    modifier = Modifier.padding(horizontal = 8.dp),
+                    modifier = Modifier.padding(horizontal = 4.dp),
                     onClick = { /* do something*/ }) {
                     Text("Chip $index")
                 }
@@ -151,3 +156,26 @@
         }
     }
 }
+
+@Sampled
+@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class)
+@Composable
+fun ChipGroupReflowSample() {
+    Column() {
+        FlowRow(
+            Modifier
+                .fillMaxWidth(1f)
+                .wrapContentHeight(align = Alignment.Top),
+            verticalAlignment = Alignment.CenterVertically,
+            horizontalArrangement = Arrangement.Start,
+        ) {
+            repeat(10) { index ->
+                Chip(
+                    modifier = Modifier.padding(horizontal = 4.dp),
+                    onClick = { /* do something*/ }) {
+                    Text("Chip $index")
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
index ac4def2..c40c277 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldScreenshotTest.kt
@@ -25,6 +25,7 @@
 import androidx.compose.material.GOLDEN_MATERIAL
 import androidx.compose.material.Icon
 import androidx.compose.material.LocalContentColor
+import androidx.compose.material.LocalTextStyle
 import androidx.compose.material.OutlinedTextField
 import androidx.compose.material.Text
 import androidx.compose.material.icons.Icons
@@ -44,7 +45,6 @@
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.test.swipeLeft
 import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.LayoutDirection
@@ -476,7 +476,7 @@
                 value = TextFieldValue(text = text, selection = TextRange(text.length)),
                 onValueChange = {},
                 modifier = Modifier.width(300.dp).testTag(TextFieldTag),
-                textStyle = TextStyle(textAlign = TextAlign.Center),
+                textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
                 singleLine = true
             )
         }
@@ -492,7 +492,7 @@
                 value = TextFieldValue(text = text, selection = TextRange(text.length)),
                 onValueChange = {},
                 modifier = Modifier.fillMaxWidth().testTag(TextFieldTag),
-                textStyle = TextStyle(textAlign = TextAlign.End),
+                textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.End),
                 singleLine = true
             )
         }
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.android.kt
similarity index 62%
copy from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
copy to compose/material/material/src/androidMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.android.kt
index 54ee1ec..2e65f0c 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
+++ b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.android.kt
@@ -14,10 +14,14 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.copypasta
+package androidx.compose.material
 
-/**
- * This is a temporary workaround and should be removed after proper mouse handling is settled
- * (b/171402426).
- */
-internal val isInTouchMode: Boolean = true
\ No newline at end of file
+import androidx.compose.ui.text.PlatformTextStyle
+
+private const val DefaultIncludeFontPadding = true
+
+@Suppress("DEPRECATION")
+private val DefaultPlatformTextStyle = PlatformTextStyle(
+    includeFontPadding = DefaultIncludeFontPadding
+)
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = DefaultPlatformTextStyle
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
index aec0946..9398dcd1 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
@@ -347,7 +347,7 @@
  *
  * @see ProvideTextStyle
  */
-val LocalTextStyle = compositionLocalOf(structuralEqualityPolicy()) { TextStyle.Default }
+val LocalTextStyle = compositionLocalOf(structuralEqualityPolicy()) { DefaultTextStyle }
 
 // TODO: b/156598010 remove this and replace with fold definition on the backing CompositionLocal
 /**
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Typography.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Typography.kt
index 63e208c..492072d 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Typography.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Typography.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.text.PlatformTextStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontWeight
@@ -117,67 +118,67 @@
      */
     constructor(
         defaultFontFamily: FontFamily = FontFamily.Default,
-        h1: TextStyle = TextStyle(
+        h1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Light,
             fontSize = 96.sp,
             letterSpacing = (-1.5).sp
         ),
-        h2: TextStyle = TextStyle(
+        h2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Light,
             fontSize = 60.sp,
             letterSpacing = (-0.5).sp
         ),
-        h3: TextStyle = TextStyle(
+        h3: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 48.sp,
             letterSpacing = 0.sp
         ),
-        h4: TextStyle = TextStyle(
+        h4: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 34.sp,
             letterSpacing = 0.25.sp
         ),
-        h5: TextStyle = TextStyle(
+        h5: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 24.sp,
             letterSpacing = 0.sp
         ),
-        h6: TextStyle = TextStyle(
+        h6: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 20.sp,
             letterSpacing = 0.15.sp
         ),
-        subtitle1: TextStyle = TextStyle(
+        subtitle1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 16.sp,
             letterSpacing = 0.15.sp
         ),
-        subtitle2: TextStyle = TextStyle(
+        subtitle2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 14.sp,
             letterSpacing = 0.1.sp
         ),
-        body1: TextStyle = TextStyle(
+        body1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 16.sp,
             letterSpacing = 0.5.sp
         ),
-        body2: TextStyle = TextStyle(
+        body2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 14.sp,
             letterSpacing = 0.25.sp
         ),
-        button: TextStyle = TextStyle(
+        button: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 14.sp,
             letterSpacing = 1.25.sp
         ),
-        caption: TextStyle = TextStyle(
+        caption: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 12.sp,
             letterSpacing = 0.4.sp
         ),
-        overline: TextStyle = TextStyle(
+        overline: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 10.sp,
             letterSpacing = 1.5.sp
@@ -284,6 +285,15 @@
     return if (fontFamily != null) this else copy(fontFamily = default)
 }
 
+internal val DefaultTextStyle = TextStyle.Default.copy(
+    platformStyle = defaultPlatformTextStyle()
+)
+
+/**
+ * Returns Default [PlatformTextStyle].
+ */
+internal expect fun defaultPlatformTextStyle(): PlatformTextStyle?
+
 /**
  * This CompositionLocal holds on to the current definition of typography for this application as
  * described by the Material spec. You can read the values in it when creating custom components
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt
index 8f2bd49..d8b6ef6 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/DefaultPlatformTextStyle.desktop.kt
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+package androidx.compose.material
 
-package androidx.compose.foundation.newtext.text.copypasta
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = null
\ No newline at end of file
diff --git a/compose/material3/material3-window-size-class/api/1.1.0-beta01.txt b/compose/material3/material3-window-size-class/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..cc66d9f
--- /dev/null
+++ b/compose/material3/material3-window-size-class/api/1.1.0-beta01.txt
@@ -0,0 +1,44 @@
+// Signature format: 4.0
+package androidx.compose.material3.windowsizeclass {
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowHeightSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowHeightSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowHeightSizeClass.Companion Companion;
+  }
+
+  public static final class WindowHeightSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+  @androidx.compose.runtime.Immutable public final class WindowSizeClass {
+    method public int getHeightSizeClass();
+    method public int getWidthSizeClass();
+    property public final int heightSizeClass;
+    property public final int widthSizeClass;
+    field public static final androidx.compose.material3.windowsizeclass.WindowSizeClass.Companion Companion;
+  }
+
+  public static final class WindowSizeClass.Companion {
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowWidthSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowWidthSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowWidthSizeClass.Companion Companion;
+  }
+
+  public static final class WindowWidthSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+}
+
diff --git a/compose/material3/material3-window-size-class/api/public_plus_experimental_1.1.0-beta01.txt b/compose/material3/material3-window-size-class/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..88ceafc
--- /dev/null
+++ b/compose/material3/material3-window-size-class/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.compose.material3.windowsizeclass {
+
+  public final class AndroidWindowSizeClass_androidKt {
+    method @androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi @androidx.compose.runtime.Composable public static androidx.compose.material3.windowsizeclass.WindowSizeClass calculateWindowSizeClass(android.app.Activity activity);
+  }
+
+  @kotlin.RequiresOptIn(message="This material3-window-size-class API is experimental and is likely to change or to " + "be removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3WindowSizeClassApi {
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowHeightSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowHeightSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowHeightSizeClass.Companion Companion;
+  }
+
+  public static final class WindowHeightSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+  @androidx.compose.runtime.Immutable public final class WindowSizeClass {
+    method public int getHeightSizeClass();
+    method public int getWidthSizeClass();
+    property public final int heightSizeClass;
+    property public final int widthSizeClass;
+    field public static final androidx.compose.material3.windowsizeclass.WindowSizeClass.Companion Companion;
+  }
+
+  public static final class WindowSizeClass.Companion {
+    method @androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi @org.jetbrains.annotations.TestOnly public androidx.compose.material3.windowsizeclass.WindowSizeClass calculateFromSize(long size);
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowWidthSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowWidthSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowWidthSizeClass.Companion Companion;
+  }
+
+  public static final class WindowWidthSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+}
+
diff --git a/compose/material3/material3-window-size-class/api/res-1.1.0-beta01.txt b/compose/material3/material3-window-size-class/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/material3-window-size-class/api/res-1.1.0-beta01.txt
diff --git a/compose/material3/material3-window-size-class/api/restricted_1.1.0-beta01.txt b/compose/material3/material3-window-size-class/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..cc66d9f
--- /dev/null
+++ b/compose/material3/material3-window-size-class/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,44 @@
+// Signature format: 4.0
+package androidx.compose.material3.windowsizeclass {
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowHeightSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowHeightSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowHeightSizeClass.Companion Companion;
+  }
+
+  public static final class WindowHeightSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+  @androidx.compose.runtime.Immutable public final class WindowSizeClass {
+    method public int getHeightSizeClass();
+    method public int getWidthSizeClass();
+    property public final int heightSizeClass;
+    property public final int widthSizeClass;
+    field public static final androidx.compose.material3.windowsizeclass.WindowSizeClass.Companion Companion;
+  }
+
+  public static final class WindowSizeClass.Companion {
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class WindowWidthSizeClass implements java.lang.Comparable<androidx.compose.material3.windowsizeclass.WindowWidthSizeClass> {
+    method public operator int compareTo(int other);
+    field public static final androidx.compose.material3.windowsizeclass.WindowWidthSizeClass.Companion Companion;
+  }
+
+  public static final class WindowWidthSizeClass.Companion {
+    method public int getCompact();
+    method public int getExpanded();
+    method public int getMedium();
+    property public final int Compact;
+    property public final int Expanded;
+    property public final int Medium;
+  }
+
+}
+
diff --git a/compose/material3/material3/api/1.1.0-beta01.txt b/compose/material3/material3/api/1.1.0-beta01.txt
new file mode 100644
index 0000000..7e2de6f
--- /dev/null
+++ b/compose/material3/material3/api/1.1.0-beta01.txt
@@ -0,0 +1,856 @@
+// Signature format: 4.0
+package androidx.compose.material3 {
+
+  public final class AlertDialogDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getIconContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public long getTextContentColor();
+    method @androidx.compose.runtime.Composable public long getTitleContentColor();
+    method public float getTonalElevation();
+    property public final float TonalElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long iconContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final long textContentColor;
+    property @androidx.compose.runtime.Composable public final long titleContentColor;
+    field public static final androidx.compose.material3.AlertDialogDefaults INSTANCE;
+  }
+
+  public final class AndroidAlertDialog_androidKt {
+    method @androidx.compose.runtime.Composable public static void AlertDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function0<kotlin.Unit> confirmButton, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long iconContentColor, optional long titleContentColor, optional long textContentColor, optional float tonalElevation, optional androidx.compose.ui.window.DialogProperties properties);
+  }
+
+  public final class AndroidMenu_androidKt {
+    method @androidx.compose.runtime.Composable public static void DropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional long offset, optional androidx.compose.ui.window.PopupProperties properties, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean enabled, optional androidx.compose.material3.MenuItemColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class AppBarKt {
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? floatingActionButton, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets);
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
+  public final class AssistChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder assistChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors assistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation assistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedAssistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedAssistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.AssistChipDefaults INSTANCE;
+  }
+
+  public final class BottomAppBarDefaults {
+    method @androidx.compose.runtime.Composable public long getBottomAppBarFabColor();
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getContainerElevation();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float ContainerElevation;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property @androidx.compose.runtime.Composable public final long bottomAppBarFabColor;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.BottomAppBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class ButtonColors {
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors buttonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation buttonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors elevatedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation elevatedButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors filledTonalButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation filledTonalButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method public androidx.compose.foundation.layout.PaddingValues getButtonWithIconContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledTonalShape();
+    method public float getIconSize();
+    method public float getIconSpacing();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke getOutlinedButtonBorder();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonWithIconContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTextShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors outlinedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors textButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ButtonWithIconContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property public final float IconSize;
+    property public final float IconSpacing;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonWithIconContentPadding;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape filledTonalShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.BorderStroke outlinedButtonBorder;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape textShape;
+    field public static final androidx.compose.material3.ButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class ButtonElevation {
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ElevatedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void TextButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardColors {
+  }
+
+  public final class CardDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors cardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation cardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors elevatedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation elevatedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedCardBorder(optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors outlinedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation outlinedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.CardDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardElevation {
+  }
+
+  public final class CardKt {
+    method @androidx.compose.runtime.Composable public static void Card(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, 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 static void ElevatedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CheckboxColors {
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
+    field public static final androidx.compose.material3.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CheckboxKt {
+    method @androidx.compose.runtime.Composable public static void Checkbox(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.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipBorder {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipElevation {
+  }
+
+  public final class ChipKt {
+    method @androidx.compose.runtime.Composable public static void AssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedAssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedSuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void SuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public final class ColorScheme {
+    ctor public ColorScheme(long primary, long onPrimary, long primaryContainer, long onPrimaryContainer, long inversePrimary, long secondary, long onSecondary, long secondaryContainer, long onSecondaryContainer, long tertiary, long onTertiary, long tertiaryContainer, long onTertiaryContainer, long background, long onBackground, long surface, long onSurface, long surfaceVariant, long onSurfaceVariant, long surfaceTint, long inverseSurface, long inverseOnSurface, long error, long onError, long errorContainer, long onErrorContainer, long outline, long outlineVariant, long scrim);
+    method public androidx.compose.material3.ColorScheme copy(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public long getBackground();
+    method public long getError();
+    method public long getErrorContainer();
+    method public long getInverseOnSurface();
+    method public long getInversePrimary();
+    method public long getInverseSurface();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnErrorContainer();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getScrim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSurface();
+    method public long getSurfaceTint();
+    method public long getSurfaceVariant();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    property public final long background;
+    property public final long error;
+    property public final long errorContainer;
+    property public final long inverseOnSurface;
+    property public final long inversePrimary;
+    property public final long inverseSurface;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onErrorContainer;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long scrim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long surface;
+    property public final long surfaceTint;
+    property public final long surfaceVariant;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+    method public static androidx.compose.material3.ColorScheme darkColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static androidx.compose.material3.ColorScheme lightColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static long surfaceColorAtElevation(androidx.compose.material3.ColorScheme, float elevation);
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  public final class DividerDefaults {
+    method @androidx.compose.runtime.Composable public long getColor();
+    method public float getThickness();
+    property public final float Thickness;
+    property @androidx.compose.runtime.Composable public final long color;
+    field public static final androidx.compose.material3.DividerDefaults INSTANCE;
+  }
+
+  public final class DividerKt {
+    method @androidx.compose.runtime.Composable public static void Divider(optional androidx.compose.ui.Modifier modifier, optional float thickness, optional long color);
+  }
+
+  public final class DrawerDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getDismissibleDrawerElevation();
+    method public float getMaximumDrawerWidth();
+    method public float getModalDrawerElevation();
+    method public float getPermanentDrawerElevation();
+    method @androidx.compose.runtime.Composable public long getScrimColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float DismissibleDrawerElevation;
+    property public final float MaximumDrawerWidth;
+    property public final float ModalDrawerElevation;
+    property public final float PermanentDrawerElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long scrimColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.DrawerDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class DrawerState {
+    ctor public DrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+    method public suspend Object? animateTo(androidx.compose.material3.DrawerValue targetValue, androidx.compose.animation.core.AnimationSpec<java.lang.Float> anim, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? close(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.compose.material3.DrawerValue getCurrentValue();
+    method public androidx.compose.runtime.State<java.lang.Float> getOffset();
+    method public androidx.compose.material3.DrawerValue getTargetValue();
+    method public boolean isAnimationRunning();
+    method public boolean isClosed();
+    method public boolean isOpen();
+    method public suspend Object? open(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? snapTo(androidx.compose.material3.DrawerValue targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final androidx.compose.material3.DrawerValue currentValue;
+    property public final boolean isAnimationRunning;
+    property public final boolean isClosed;
+    property public final boolean isOpen;
+    property public final androidx.compose.runtime.State<java.lang.Float> offset;
+    property public final androidx.compose.material3.DrawerValue targetValue;
+    field public static final androidx.compose.material3.DrawerState.Companion Companion;
+  }
+
+  public static final class DrawerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DrawerState,androidx.compose.material3.DrawerValue> Saver(kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public enum DrawerValue {
+    method public static androidx.compose.material3.DrawerValue valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.DrawerValue[] values();
+    enum_constant public static final androidx.compose.material3.DrawerValue Closed;
+    enum_constant public static final androidx.compose.material3.DrawerValue Open;
+  }
+
+  public final class DynamicTonalPaletteKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicDarkColorScheme(android.content.Context context);
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicLightColorScheme(android.content.Context context);
+  }
+
+  @kotlin.jvm.JvmInline public final value class FabPosition {
+    field public static final androidx.compose.material3.FabPosition.Companion Companion;
+  }
+
+  public static final class FabPosition.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    property public final int Center;
+    property public final int End;
+  }
+
+  public final class FloatingActionButtonDefaults {
+    method public androidx.compose.material3.FloatingActionButtonElevation bottomAppBarFabElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation elevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getExtendedFabShape();
+    method public float getLargeIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getLargeShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSmallShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation loweredElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    property public final float LargeIconSize;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape extendedFabShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape largeShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape smallShape;
+    field public static final androidx.compose.material3.FloatingActionButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public class FloatingActionButtonElevation {
+  }
+
+  public final class FloatingActionButtonKt {
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors filledIconToggleButtonColors(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.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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.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(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.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors outlinedIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
+    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;
+    field public static final androidx.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(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 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 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);
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconToggleButtonColors {
+  }
+
+  public final class InteractiveComponentSizeKt {
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ListItemColors {
+  }
+
+  public final class ListItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ListItemColors colors(optional long containerColor, optional long headlineColor, optional long leadingIconColor, optional long overlineColor, optional long supportingColor, optional long trailingIconColor, optional long disabledHeadlineColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContainerColor();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContentColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long containerColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long contentColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.ListItemDefaults INSTANCE;
+  }
+
+  public final class ListItemKt {
+    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);
+  }
+
+  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();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Typography typography;
+    field public static final androidx.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    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);
+  }
+
+  public final class MenuDefaults {
+    method public androidx.compose.foundation.layout.PaddingValues getDropdownMenuItemContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.MenuItemColors itemColors(optional long textColor, optional long leadingIconColor, optional long trailingIconColor, optional long disabledTextColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    property public final androidx.compose.foundation.layout.PaddingValues DropdownMenuItemContentPadding;
+    field public static final androidx.compose.material3.MenuDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class MenuItemColors {
+  }
+
+  public final class NavigationBarDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationBarItemColors {
+  }
+
+  public final class NavigationBarItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationBarItemDefaults INSTANCE;
+  }
+
+  public final class NavigationBarKt {
+    method @androidx.compose.runtime.Composable public static void NavigationBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationBarItem(androidx.compose.foundation.layout.RowScope, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationBarItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public interface NavigationDrawerItemColors {
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> badgeColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> containerColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> iconColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> textColor(boolean selected);
+  }
+
+  public final class NavigationDrawerItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationDrawerItemColors colors(optional long selectedContainerColor, optional long unselectedContainerColor, optional long selectedIconColor, optional long unselectedIconColor, optional long selectedTextColor, optional long unselectedTextColor, optional long selectedBadgeColor, optional long unselectedBadgeColor);
+    method public androidx.compose.foundation.layout.PaddingValues getItemPadding();
+    property public final androidx.compose.foundation.layout.PaddingValues ItemPadding;
+    field public static final androidx.compose.material3.NavigationDrawerItemDefaults INSTANCE;
+  }
+
+  public final class NavigationDrawerKt {
+    method @androidx.compose.runtime.Composable public static void DismissibleDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DismissibleNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationDrawerItem(kotlin.jvm.functions.Function0<kotlin.Unit> label, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? badge, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.NavigationDrawerItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void PermanentDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void PermanentNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static androidx.compose.material3.DrawerState rememberDrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public final class NavigationRailDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationRailDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationRailItemColors {
+  }
+
+  public final class NavigationRailItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationRailItemDefaults INSTANCE;
+  }
+
+  public final class NavigationRailKt {
+    method @androidx.compose.runtime.Composable public static void NavigationRail(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? header, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationRailItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationRailItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class OutlinedTextFieldKt {
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method @androidx.compose.runtime.Composable public long getCircularColor();
+    method public int getCircularDeterminateStrokeCap();
+    method public int getCircularIndeterminateStrokeCap();
+    method public float getCircularStrokeWidth();
+    method @androidx.compose.runtime.Composable public long getCircularTrackColor();
+    method @androidx.compose.runtime.Composable public long getLinearColor();
+    method public int getLinearStrokeCap();
+    method @androidx.compose.runtime.Composable public long getLinearTrackColor();
+    method public androidx.compose.animation.core.SpringSpec<java.lang.Float> getProgressAnimationSpec();
+    property public final int CircularDeterminateStrokeCap;
+    property public final int CircularIndeterminateStrokeCap;
+    property public final float CircularStrokeWidth;
+    property public final int LinearStrokeCap;
+    property public final androidx.compose.animation.core.SpringSpec<java.lang.Float> ProgressAnimationSpec;
+    property @androidx.compose.runtime.Composable public final long circularColor;
+    property @androidx.compose.runtime.Composable public final long circularTrackColor;
+    property @androidx.compose.runtime.Composable public final long linearColor;
+    property @androidx.compose.runtime.Composable public final long linearTrackColor;
+    field public static final androidx.compose.material3.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class ProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+  }
+
+  @androidx.compose.runtime.Immutable public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.RadioButtonColors colors(optional long selectedColor, optional long unselectedColor, optional long disabledSelectedColor, optional long disabledUnselectedColor);
+    field public static final androidx.compose.material3.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.RadioButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class ScaffoldDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getContentWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets contentWindowInsets;
+    field public static final androidx.compose.material3.ScaffoldDefaults INSTANCE;
+  }
+
+  public final class ScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> snackbarHost, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, optional androidx.compose.foundation.layout.WindowInsets contentWindowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Small;
+    field public static final androidx.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.material3.Shapes copy(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape small;
+  }
+
+  @androidx.compose.runtime.Immutable public final class SliderColors {
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderDefaults {
+    method @androidx.compose.runtime.Composable public void Thumb(androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled, optional long thumbSize);
+    method @androidx.compose.runtime.Composable public void Track(androidx.compose.material3.SliderPositions sliderPositions, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SliderColors colors(optional long thumbColor, optional long activeTrackColor, optional long activeTickColor, optional long inactiveTrackColor, optional long inactiveTickColor, optional long disabledThumbColor, optional long disabledActiveTrackColor, optional long disabledActiveTickColor, optional long disabledInactiveTrackColor, optional long disabledInactiveTickColor);
+    field public static final androidx.compose.material3.SliderDefaults INSTANCE;
+  }
+
+  public final class SliderKt {
+    method @androidx.compose.runtime.Composable public static void RangeSlider(kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> value, kotlin.jvm.functions.Function1<? super kotlin.ranges.ClosedFloatingPointRange<java.lang.Float>,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors);
+    method @androidx.compose.runtime.Composable public static void Slider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderPositions {
+    ctor public SliderPositions(optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> initialActiveRange, optional float[] initialTickFractions);
+    method public kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> getActiveRange();
+    method public float[] getTickFractions();
+    property public final kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> activeRange;
+    property public final float[] tickFractions;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarData {
+    method public void dismiss();
+    method public androidx.compose.material3.SnackbarVisuals getVisuals();
+    method public void performAction();
+    property public abstract androidx.compose.material3.SnackbarVisuals visuals;
+  }
+
+  public final class SnackbarDefaults {
+    method @androidx.compose.runtime.Composable public long getActionColor();
+    method @androidx.compose.runtime.Composable public long getActionContentColor();
+    method @androidx.compose.runtime.Composable public long getColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method @androidx.compose.runtime.Composable public long getDismissActionContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property @androidx.compose.runtime.Composable public final long actionColor;
+    property @androidx.compose.runtime.Composable public final long actionContentColor;
+    property @androidx.compose.runtime.Composable public final long color;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    property @androidx.compose.runtime.Composable public final long dismissActionContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SnackbarDefaults INSTANCE;
+  }
+
+  public enum SnackbarDuration {
+    method public static androidx.compose.material3.SnackbarDuration valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarDuration[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Indefinite;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Long;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Short;
+  }
+
+  public final class SnackbarHostKt {
+    method @androidx.compose.runtime.Composable public static void SnackbarHost(androidx.compose.material3.SnackbarHostState hostState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarData,kotlin.Unit> snackbar);
+  }
+
+  @androidx.compose.runtime.Stable public final class SnackbarHostState {
+    ctor public SnackbarHostState();
+    method public androidx.compose.material3.SnackbarData? getCurrentSnackbarData();
+    method public suspend Object? showSnackbar(String message, optional String? actionLabel, optional boolean withDismissAction, optional androidx.compose.material3.SnackbarDuration duration, optional kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    method public suspend Object? showSnackbar(androidx.compose.material3.SnackbarVisuals visuals, kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    property public final androidx.compose.material3.SnackbarData? currentSnackbarData;
+  }
+
+  public final class SnackbarKt {
+    method @androidx.compose.runtime.Composable public static void Snackbar(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissAction, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionContentColor, optional long dismissActionContentColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Snackbar(androidx.compose.material3.SnackbarData snackbarData, optional androidx.compose.ui.Modifier modifier, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionColor, optional long actionContentColor, optional long dismissActionContentColor);
+  }
+
+  public enum SnackbarResult {
+    method public static androidx.compose.material3.SnackbarResult valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarResult[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarResult ActionPerformed;
+    enum_constant public static final androidx.compose.material3.SnackbarResult Dismissed;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarVisuals {
+    method public String? getActionLabel();
+    method public androidx.compose.material3.SnackbarDuration getDuration();
+    method public String getMessage();
+    method public boolean getWithDismissAction();
+    property public abstract String? actionLabel;
+    property public abstract androidx.compose.material3.SnackbarDuration duration;
+    property public abstract String message;
+    property public abstract boolean withDismissAction;
+  }
+
+  public final class SuggestionChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedSuggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedSuggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder suggestionChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors suggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation suggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SuggestionChipDefaults INSTANCE;
+  }
+
+  public final class SurfaceKt {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(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 long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> getLocalAbsoluteTonalElevation();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> LocalAbsoluteTonalElevation;
+  }
+
+  @androidx.compose.runtime.Immutable public final class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedTrackColor, optional long checkedBorderColor, optional long checkedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedBorderColor, optional long uncheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledCheckedBorderColor, optional long disabledCheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedBorderColor, optional long disabledUncheckedIconColor);
+    method public float getIconSize();
+    property public final float IconSize;
+    field public static final androidx.compose.material3.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? thumbContent, optional boolean enabled, optional androidx.compose.material3.SwitchColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class TabKt {
+    method @androidx.compose.runtime.Composable public static void LeadingIconTab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TabPosition {
+    method public float getLeft();
+    method public float getRight();
+    method public float getWidth();
+    property public final float left;
+    property public final float right;
+    property public final float width;
+  }
+
+  public final class TabRowDefaults {
+    method @androidx.compose.runtime.Composable public void Indicator(optional androidx.compose.ui.Modifier modifier, optional float height, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method public androidx.compose.ui.Modifier tabIndicatorOffset(androidx.compose.ui.Modifier, androidx.compose.material3.TabPosition currentTabPosition);
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    field public static final androidx.compose.material3.TabRowDefaults INSTANCE;
+  }
+
+  public final class TabRowKt {
+    method @androidx.compose.runtime.Composable public static void ScrollableTabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float edgePadding, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+    method @androidx.compose.runtime.Composable public static void TabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledShape();
+    method public float getFocusedBorderThickness();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method public float getUnfocusedBorderThickness();
+    method public androidx.compose.foundation.layout.PaddingValues outlinedTextFieldPadding(optional float start, optional float top, optional float end, optional float bottom);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithLabelPadding(optional float start, optional float end, optional float top, optional float bottom);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithoutLabelPadding(optional float start, optional float top, optional float end, optional float bottom);
+    property public final float FocusedBorderThickness;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final float UnfocusedBorderThickness;
+    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;
+    field public static final androidx.compose.material3.TextFieldDefaults INSTANCE;
+  }
+
+  public final class TextFieldKt {
+    method @androidx.compose.runtime.Composable public static void TextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void TextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @androidx.compose.runtime.Stable public final class TimePickerState {
+    ctor public TimePickerState(int initialHour, int initialMinute, boolean is24Hour);
+    method public int getHour();
+    method public int getMinute();
+    method public boolean is24hour();
+    method public suspend Object? settle(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final int hour;
+    property public final boolean is24hour;
+    property public final int minute;
+    field public static final androidx.compose.material3.TimePickerState.Companion Companion;
+  }
+
+  public static final class TimePickerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TimePickerState,?> Saver();
+  }
+
+  @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);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    method public androidx.compose.ui.text.TextStyle getHeadlineLarge();
+    method public androidx.compose.ui.text.TextStyle getHeadlineMedium();
+    method public androidx.compose.ui.text.TextStyle getHeadlineSmall();
+    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 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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    property public final androidx.compose.ui.text.TextStyle headlineLarge;
+    property public final androidx.compose.ui.text.TextStyle headlineMedium;
+    property public final androidx.compose.ui.text.TextStyle headlineSmall;
+    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 titleLarge;
+    property public final androidx.compose.ui.text.TextStyle titleMedium;
+    property public final androidx.compose.ui.text.TextStyle titleSmall;
+  }
+
+}
+
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index e6d7e92..7e2de6f 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -578,22 +578,6 @@
     method @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> snackbarHost, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, optional androidx.compose.foundation.layout.WindowInsets contentWindowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
   }
 
-  public final class SearchBarDefaults {
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getDockedShape();
-    method public float getElevation();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFullScreenShape();
-    method public float getInputFieldHeight();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getInputFieldShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property public final float Elevation;
-    property public final float InputFieldHeight;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape dockedShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape fullScreenShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape inputFieldShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.SearchBarDefaults INSTANCE;
-  }
-
   public final class ShapeDefaults {
     method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
     method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
diff --git a/compose/material3/material3/api/public_plus_experimental_1.1.0-beta01.txt b/compose/material3/material3/api/public_plus_experimental_1.1.0-beta01.txt
new file mode 100644
index 0000000..30eb84f
--- /dev/null
+++ b/compose/material3/material3/api/public_plus_experimental_1.1.0-beta01.txt
@@ -0,0 +1,1328 @@
+// Signature format: 4.0
+package androidx.compose.material3 {
+
+  public final class AlertDialogDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getIconContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public long getTextContentColor();
+    method @androidx.compose.runtime.Composable public long getTitleContentColor();
+    method public float getTonalElevation();
+    property public final float TonalElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long iconContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final long textContentColor;
+    property @androidx.compose.runtime.Composable public final long titleContentColor;
+    field public static final androidx.compose.material3.AlertDialogDefaults INSTANCE;
+  }
+
+  public final class AndroidAlertDialog_androidKt {
+    method @androidx.compose.runtime.Composable public static void AlertDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function0<kotlin.Unit> confirmButton, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long iconContentColor, optional long titleContentColor, optional long textContentColor, optional float tonalElevation, optional androidx.compose.ui.window.DialogProperties properties);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void AlertDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.window.DialogProperties properties, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class AndroidMenu_androidKt {
+    method @androidx.compose.runtime.Composable public static void DropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional long offset, optional androidx.compose.ui.window.PopupProperties properties, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean enabled, optional androidx.compose.material3.MenuItemColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class AppBarKt {
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? floatingActionButton, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets);
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @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 androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @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 @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 @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void SmallTopAppBar(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 @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 @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TopAppBarState rememberTopAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
+  }
+
+  public final class AssistChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder assistChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors assistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation assistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedAssistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedAssistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.AssistChipDefaults INSTANCE;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class BadgeDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    field public static final androidx.compose.material3.BadgeDefaults INSTANCE;
+  }
+
+  public final class BadgeKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void Badge(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit>? content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void BadgedBox(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> badge, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
+  public final class BottomAppBarDefaults {
+    method @androidx.compose.runtime.Composable public long getBottomAppBarFabColor();
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getContainerElevation();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float ContainerElevation;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property @androidx.compose.runtime.Composable public final long bottomAppBarFabColor;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.BottomAppBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class BottomSheetDefaults {
+    method @androidx.compose.runtime.Composable public void DragHandle(optional androidx.compose.ui.Modifier modifier, optional float width, optional float height, optional androidx.compose.ui.graphics.Shape shape, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getExpandedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getMinimizedShape();
+    method @androidx.compose.runtime.Composable public long getScrimColor();
+    method public float getSheetPeekHeight();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape ExpandedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape MinimizedShape;
+    property @androidx.compose.runtime.Composable public final long ScrimColor;
+    property public final float SheetPeekHeight;
+    field public static final androidx.compose.material3.BottomSheetDefaults INSTANCE;
+  }
+
+  public final class BottomSheetScaffoldKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void BottomSheetScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> sheetContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.BottomSheetScaffoldState scaffoldState, optional float sheetPeekHeight, optional androidx.compose.ui.graphics.Shape sheetShape, optional long sheetContainerColor, optional long sheetContentColor, optional float sheetTonalElevation, optional float sheetShadowElevation, optional kotlin.jvm.functions.Function0<kotlin.Unit>? sheetDragHandle, optional boolean sheetSwipeEnabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? topBar, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarHostState,kotlin.Unit> snackbarHost, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomSheetScaffoldState rememberBottomSheetScaffoldState(optional androidx.compose.material3.SheetState bottomSheetState, optional androidx.compose.material3.SnackbarHostState snackbarHostState);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SheetState rememberStandardBottomSheetState(optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class BottomSheetScaffoldState {
+    ctor public BottomSheetScaffoldState(androidx.compose.material3.SheetState bottomSheetState, androidx.compose.material3.SnackbarHostState snackbarHostState);
+    method public androidx.compose.material3.SheetState getBottomSheetState();
+    method public androidx.compose.material3.SnackbarHostState getSnackbarHostState();
+    property public final androidx.compose.material3.SheetState bottomSheetState;
+    property public final androidx.compose.material3.SnackbarHostState snackbarHostState;
+  }
+
+  @androidx.compose.runtime.Immutable public final class ButtonColors {
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors buttonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation buttonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors elevatedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation elevatedButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors filledTonalButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation filledTonalButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method public androidx.compose.foundation.layout.PaddingValues getButtonWithIconContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledTonalShape();
+    method public float getIconSize();
+    method public float getIconSpacing();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke getOutlinedButtonBorder();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonWithIconContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTextShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors outlinedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors textButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ButtonWithIconContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property public final float IconSize;
+    property public final float IconSpacing;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonWithIconContentPadding;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape filledTonalShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.BorderStroke outlinedButtonBorder;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape textShape;
+    field public static final androidx.compose.material3.ButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class ButtonElevation {
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ElevatedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void TextButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardColors {
+  }
+
+  public final class CardDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors cardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation cardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors elevatedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation elevatedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedCardBorder(optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors outlinedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation outlinedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.CardDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardElevation {
+  }
+
+  public final class CardKt {
+    method @androidx.compose.runtime.Composable public static void Card(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void Card(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.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ElevatedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ElevatedCard(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.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void OutlinedCard(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.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CheckboxColors {
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
+    field public static final androidx.compose.material3.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CheckboxKt {
+    method @androidx.compose.runtime.Composable public static void Checkbox(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.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipBorder {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipElevation {
+  }
+
+  public final class ChipKt {
+    method @androidx.compose.runtime.Composable public static void AssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedAssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ElevatedFilterChip(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipColors colors, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedSuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void FilterChip(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipColors colors, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void InputChip(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? avatar, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipColors colors, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void SuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public final class ColorScheme {
+    ctor public ColorScheme(long primary, long onPrimary, long primaryContainer, long onPrimaryContainer, long inversePrimary, long secondary, long onSecondary, long secondaryContainer, long onSecondaryContainer, long tertiary, long onTertiary, long tertiaryContainer, long onTertiaryContainer, long background, long onBackground, long surface, long onSurface, long surfaceVariant, long onSurfaceVariant, long surfaceTint, long inverseSurface, long inverseOnSurface, long error, long onError, long errorContainer, long onErrorContainer, long outline, long outlineVariant, long scrim);
+    method public androidx.compose.material3.ColorScheme copy(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public long getBackground();
+    method public long getError();
+    method public long getErrorContainer();
+    method public long getInverseOnSurface();
+    method public long getInversePrimary();
+    method public long getInverseSurface();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnErrorContainer();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getScrim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSurface();
+    method public long getSurfaceTint();
+    method public long getSurfaceVariant();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    property public final long background;
+    property public final long error;
+    property public final long errorContainer;
+    property public final long inverseOnSurface;
+    property public final long inversePrimary;
+    property public final long inverseSurface;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onErrorContainer;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long scrim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long surface;
+    property public final long surfaceTint;
+    property public final long surfaceVariant;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+    method public static androidx.compose.material3.ColorScheme darkColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static androidx.compose.material3.ColorScheme lightColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static long surfaceColorAtElevation(androidx.compose.material3.ColorScheme, float elevation);
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class DatePickerColors {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class DatePickerDefaults {
+    method @androidx.compose.runtime.Composable public void DatePickerHeadline(androidx.compose.material3.DatePickerState state, androidx.compose.material3.DatePickerFormatter dateFormatter, optional androidx.compose.ui.Modifier modifier);
+    method @androidx.compose.runtime.Composable public void DatePickerTitle(androidx.compose.material3.DatePickerState state, optional androidx.compose.ui.Modifier modifier);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.DatePickerColors colors(optional long containerColor, optional long titleContentColor, optional long headlineContentColor, optional long weekdayContentColor, optional long subheadContentColor, optional long yearContentColor, optional long currentYearContentColor, optional long selectedYearContentColor, optional long selectedYearContainerColor, optional long dayContentColor, optional long disabledDayContentColor, optional long selectedDayContentColor, optional long disabledSelectedDayContentColor, optional long selectedDayContainerColor, optional long disabledSelectedDayContainerColor, optional long todayContentColor, optional long todayDateBorderColor, optional long dayInSelectionRangeContentColor, optional long dayInSelectionRangeContainerColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method public float getTonalElevation();
+    method public kotlin.ranges.IntRange getYearRange();
+    property public final float TonalElevation;
+    property public final kotlin.ranges.IntRange YearRange;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.DatePickerDefaults INSTANCE;
+    field public static final String YearAbbrMonthDaySkeleton = "yMMMd";
+    field public static final String YearMonthSkeleton = "yMMMM";
+    field public static final String YearMonthWeekdayDaySkeleton = "yMMMMEEEEd";
+  }
+
+  public final class DatePickerDialog_androidKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DatePickerDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function0<kotlin.Unit> confirmButton, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissButton, optional androidx.compose.ui.graphics.Shape shape, optional float tonalElevation, optional androidx.compose.material3.DatePickerColors colors, optional androidx.compose.ui.window.DialogProperties properties, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class DatePickerFormatter {
+    ctor public DatePickerFormatter(optional String yearSelectionSkeleton, optional String selectedDateSkeleton, optional String selectedDateDescriptionSkeleton);
+  }
+
+  public final class DatePickerKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DatePicker(androidx.compose.material3.DatePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DatePickerFormatter dateFormatter, optional kotlin.jvm.functions.Function1<? super java.lang.Long,java.lang.Boolean> dateValidator, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? headline, optional boolean showModeToggle, optional androidx.compose.material3.DatePickerColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.DatePickerState rememberDatePickerState(optional Long? initialSelectedDateMillis, optional Long? initialDisplayedMonthMillis, optional kotlin.ranges.IntRange yearRange, optional int initialDisplayMode);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class DatePickerState {
+    ctor public DatePickerState(Long? initialSelectedDateMillis, Long? initialDisplayedMonthMillis, kotlin.ranges.IntRange yearRange, int initialDisplayMode);
+    method public int getDisplayMode();
+    method public Long? getSelectedDateMillis();
+    method public void setDisplayMode(int);
+    method public void setSelection(Long? dateMillis);
+    property public final int displayMode;
+    property public final Long? selectedDateMillis;
+    field public static final androidx.compose.material3.DatePickerState.Companion Companion;
+  }
+
+  public static final class DatePickerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DatePickerState,?> Saver();
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class DateRangePickerDefaults {
+    method @androidx.compose.runtime.Composable public void DateRangePickerHeadline(androidx.compose.material3.DateRangePickerState state, androidx.compose.material3.DatePickerFormatter dateFormatter, optional androidx.compose.ui.Modifier modifier);
+    method @androidx.compose.runtime.Composable public void DateRangePickerTitle(androidx.compose.material3.DateRangePickerState state, optional androidx.compose.ui.Modifier modifier);
+    field public static final androidx.compose.material3.DateRangePickerDefaults INSTANCE;
+  }
+
+  public final class DateRangePickerKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DateRangePicker(androidx.compose.material3.DateRangePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DatePickerFormatter dateFormatter, optional kotlin.jvm.functions.Function1<? super java.lang.Long,java.lang.Boolean> dateValidator, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? headline, optional boolean showModeToggle, optional androidx.compose.material3.DatePickerColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.DateRangePickerState rememberDateRangePickerState(optional Long? initialSelectedStartDateMillis, optional Long? initialSelectedEndDateMillis, optional Long? initialDisplayedMonthMillis, optional kotlin.ranges.IntRange yearRange, optional int initialDisplayMode);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class DateRangePickerState {
+    ctor public DateRangePickerState(Long? initialSelectedStartDateMillis, Long? initialSelectedEndDateMillis, Long? initialDisplayedMonthMillis, kotlin.ranges.IntRange yearRange, int initialDisplayMode);
+    method public int getDisplayMode();
+    method public Long? getSelectedEndDateMillis();
+    method public Long? getSelectedStartDateMillis();
+    method public void setDisplayMode(int);
+    method public void setSelection(Long? startDateMillis, Long? endDateMillis);
+    property public final int displayMode;
+    property public final Long? selectedEndDateMillis;
+    property public final Long? selectedStartDateMillis;
+    field public static final androidx.compose.material3.DateRangePickerState.Companion Companion;
+  }
+
+  public static final class DateRangePickerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DateRangePickerState,?> Saver();
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public enum DismissDirection {
+    method public static androidx.compose.material3.DismissDirection valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.DismissDirection[] values();
+    enum_constant public static final androidx.compose.material3.DismissDirection EndToStart;
+    enum_constant public static final androidx.compose.material3.DismissDirection StartToEnd;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class DismissState {
+    ctor public DismissState(androidx.compose.material3.DismissValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DismissValue,java.lang.Boolean> confirmValueChange, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.unit.Density,? super java.lang.Float,java.lang.Float> positionalThreshold);
+    method public suspend Object? dismiss(androidx.compose.material3.DismissDirection direction, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.compose.material3.DismissValue getCurrentValue();
+    method public androidx.compose.material3.DismissDirection? getDismissDirection();
+    method public float getProgress();
+    method public androidx.compose.material3.DismissValue getTargetValue();
+    method public boolean isDismissed(androidx.compose.material3.DismissDirection direction);
+    method public float requireOffset();
+    method public suspend Object? reset(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? snapTo(androidx.compose.material3.DismissValue targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final androidx.compose.material3.DismissValue currentValue;
+    property public final androidx.compose.material3.DismissDirection? dismissDirection;
+    property public final float progress;
+    property public final androidx.compose.material3.DismissValue targetValue;
+    field public static final androidx.compose.material3.DismissState.Companion Companion;
+  }
+
+  public static final class DismissState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DismissState,androidx.compose.material3.DismissValue> Saver(kotlin.jvm.functions.Function1<? super androidx.compose.material3.DismissValue,java.lang.Boolean> confirmValueChange, kotlin.jvm.functions.Function2<? super androidx.compose.ui.unit.Density,? super java.lang.Float,java.lang.Float> positionalThreshold);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public enum DismissValue {
+    method public static androidx.compose.material3.DismissValue valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.DismissValue[] values();
+    enum_constant public static final androidx.compose.material3.DismissValue Default;
+    enum_constant public static final androidx.compose.material3.DismissValue DismissedToEnd;
+    enum_constant public static final androidx.compose.material3.DismissValue DismissedToStart;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class DisplayMode {
+    field public static final androidx.compose.material3.DisplayMode.Companion Companion;
+  }
+
+  public static final class DisplayMode.Companion {
+    method public int getInput();
+    method public int getPicker();
+    property public final int Input;
+    property public final int Picker;
+  }
+
+  public final class DividerDefaults {
+    method @androidx.compose.runtime.Composable public long getColor();
+    method public float getThickness();
+    property public final float Thickness;
+    property @androidx.compose.runtime.Composable public final long color;
+    field public static final androidx.compose.material3.DividerDefaults INSTANCE;
+  }
+
+  public final class DividerKt {
+    method @androidx.compose.runtime.Composable public static void Divider(optional androidx.compose.ui.Modifier modifier, optional float thickness, optional long color);
+  }
+
+  public final class DrawerDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getDismissibleDrawerElevation();
+    method public float getMaximumDrawerWidth();
+    method public float getModalDrawerElevation();
+    method public float getPermanentDrawerElevation();
+    method @androidx.compose.runtime.Composable public long getScrimColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float DismissibleDrawerElevation;
+    property public final float MaximumDrawerWidth;
+    property public final float ModalDrawerElevation;
+    property public final float PermanentDrawerElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long scrimColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.DrawerDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class DrawerState {
+    ctor public DrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+    method public suspend Object? animateTo(androidx.compose.material3.DrawerValue targetValue, androidx.compose.animation.core.AnimationSpec<java.lang.Float> anim, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? close(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.compose.material3.DrawerValue getCurrentValue();
+    method public androidx.compose.runtime.State<java.lang.Float> getOffset();
+    method public androidx.compose.material3.DrawerValue getTargetValue();
+    method public boolean isAnimationRunning();
+    method public boolean isClosed();
+    method public boolean isOpen();
+    method public suspend Object? open(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? snapTo(androidx.compose.material3.DrawerValue targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final androidx.compose.material3.DrawerValue currentValue;
+    property public final boolean isAnimationRunning;
+    property public final boolean isClosed;
+    property public final boolean isOpen;
+    property public final androidx.compose.runtime.State<java.lang.Float> offset;
+    property public final androidx.compose.material3.DrawerValue targetValue;
+    field public static final androidx.compose.material3.DrawerState.Companion Companion;
+  }
+
+  public static final class DrawerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DrawerState,androidx.compose.material3.DrawerValue> Saver(kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public enum DrawerValue {
+    method public static androidx.compose.material3.DrawerValue valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.DrawerValue[] values();
+    enum_constant public static final androidx.compose.material3.DrawerValue Closed;
+    enum_constant public static final androidx.compose.material3.DrawerValue Open;
+  }
+
+  public final class DynamicTonalPaletteKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicDarkColorScheme(android.content.Context context);
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicLightColorScheme(android.content.Context context);
+  }
+
+  @kotlin.RequiresOptIn(message="This material API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3Api {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public interface ExposedDropdownMenuBoxScope {
+    method @androidx.compose.runtime.Composable public default void ExposedDropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method public androidx.compose.ui.Modifier exposedDropdownSize(androidx.compose.ui.Modifier, optional boolean matchTextFieldWidth);
+    method public androidx.compose.ui.Modifier menuAnchor(androidx.compose.ui.Modifier);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class ExposedDropdownMenuDefaults {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void TrailingIcon(boolean expanded);
+    method public androidx.compose.foundation.layout.PaddingValues getItemContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors outlinedTextFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long errorTextColor, optional long containerColor, optional long errorContainerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedBorderColor, optional long unfocusedBorderColor, optional long disabledBorderColor, optional long errorBorderColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor, optional long errorPlaceholderColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors outlinedTextFieldColors(optional long textColor, optional long disabledTextColor, optional long containerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedBorderColor, optional long unfocusedBorderColor, optional long disabledBorderColor, optional long errorBorderColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long placeholderColor, optional long disabledPlaceholderColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors textFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long errorTextColor, optional long containerColor, optional long errorContainerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedIndicatorColor, optional long unfocusedIndicatorColor, optional long disabledIndicatorColor, optional long errorIndicatorColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor, optional long errorPlaceholderColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors textFieldColors(optional long textColor, optional long disabledTextColor, optional long containerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedIndicatorColor, optional long unfocusedIndicatorColor, optional long disabledIndicatorColor, optional long errorIndicatorColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long placeholderColor, optional long disabledPlaceholderColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ItemContentPadding;
+    field public static final androidx.compose.material3.ExposedDropdownMenuDefaults INSTANCE;
+  }
+
+  public final class ExposedDropdownMenuKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ExposedDropdownMenuBox(boolean expanded, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onExpandedChange, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.ExposedDropdownMenuBoxScope,kotlin.Unit> content);
+  }
+
+  @kotlin.jvm.JvmInline public final value class FabPosition {
+    field public static final androidx.compose.material3.FabPosition.Companion Companion;
+  }
+
+  public static final class FabPosition.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    property public final int Center;
+    property public final int End;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class FilterChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipColors elevatedFilterChipColors(optional long containerColor, optional long labelColor, optional long iconColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor, optional long selectedContainerColor, optional long disabledSelectedContainerColor, optional long selectedLabelColor, optional long selectedLeadingIconColor, optional long selectedTrailingIconColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipElevation elevatedFilterChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipBorder filterChipBorder(optional long borderColor, optional long selectedBorderColor, optional long disabledBorderColor, optional long disabledSelectedBorderColor, optional float borderWidth, optional float selectedBorderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipColors filterChipColors(optional long containerColor, optional long labelColor, optional long iconColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor, optional long selectedContainerColor, optional long disabledSelectedContainerColor, optional long selectedLabelColor, optional long selectedLeadingIconColor, optional long selectedTrailingIconColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipElevation filterChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.FilterChipDefaults INSTANCE;
+  }
+
+  public final class FloatingActionButtonDefaults {
+    method public androidx.compose.material3.FloatingActionButtonElevation bottomAppBarFabElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation elevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getExtendedFabShape();
+    method public float getLargeIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getLargeShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSmallShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation loweredElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    property public final float LargeIconSize;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape extendedFabShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape largeShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape smallShape;
+    field public static final androidx.compose.material3.FloatingActionButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public class FloatingActionButtonElevation {
+  }
+
+  public final class FloatingActionButtonKt {
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors filledIconToggleButtonColors(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.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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.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(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.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors outlinedIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
+    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;
+    field public static final androidx.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(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 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 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);
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconToggleButtonColors {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class InputChipDefaults {
+    method public float getAvatarSize();
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipBorder inputChipBorder(optional long borderColor, optional long selectedBorderColor, optional long disabledBorderColor, optional long disabledSelectedBorderColor, optional float borderWidth, optional float selectedBorderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipColors inputChipColors(optional long containerColor, optional long labelColor, optional long leadingIconColor, optional long trailingIconColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor, optional long selectedContainerColor, optional long disabledSelectedContainerColor, optional long selectedLabelColor, optional long selectedLeadingIconColor, optional long selectedTrailingIconColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SelectableChipElevation inputChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property public final float AvatarSize;
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.InputChipDefaults INSTANCE;
+  }
+
+  public final class InteractiveComponentSizeKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> getLocalMinimumInteractiveComponentEnforcement();
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> getLocalMinimumTouchTargetEnforcement();
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+    property @androidx.compose.material3.ExperimentalMaterial3Api public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> LocalMinimumInteractiveComponentEnforcement;
+    property @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Boolean> LocalMinimumTouchTargetEnforcement;
+  }
+
+  @androidx.compose.runtime.Immutable public final class ListItemColors {
+  }
+
+  public final class ListItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ListItemColors colors(optional long containerColor, optional long headlineColor, optional long leadingIconColor, optional long overlineColor, optional long supportingColor, optional long trailingIconColor, optional long disabledHeadlineColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContainerColor();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContentColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long containerColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long contentColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.ListItemDefaults INSTANCE;
+  }
+
+  public final class ListItemKt {
+    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);
+  }
+
+  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();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Typography typography;
+    field public static final androidx.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    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);
+  }
+
+  public final class MenuDefaults {
+    method public androidx.compose.foundation.layout.PaddingValues getDropdownMenuItemContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.MenuItemColors itemColors(optional long textColor, optional long leadingIconColor, optional long trailingIconColor, optional long disabledTextColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    property public final androidx.compose.foundation.layout.PaddingValues DropdownMenuItemContentPadding;
+    field public static final androidx.compose.material3.MenuDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class MenuItemColors {
+  }
+
+  public final class ModalBottomSheetKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ModalBottomSheet(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SheetState sheetState, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional float tonalElevation, optional long scrimColor, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dragHandle, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SheetState rememberModalBottomSheetState(optional boolean skipPartiallyExpanded, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange);
+  }
+
+  public final class NavigationBarDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationBarItemColors {
+  }
+
+  public final class NavigationBarItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationBarItemDefaults INSTANCE;
+  }
+
+  public final class NavigationBarKt {
+    method @androidx.compose.runtime.Composable public static void NavigationBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationBarItem(androidx.compose.foundation.layout.RowScope, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationBarItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public interface NavigationDrawerItemColors {
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> badgeColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> containerColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> iconColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> textColor(boolean selected);
+  }
+
+  public final class NavigationDrawerItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationDrawerItemColors colors(optional long selectedContainerColor, optional long unselectedContainerColor, optional long selectedIconColor, optional long unselectedIconColor, optional long selectedTextColor, optional long unselectedTextColor, optional long selectedBadgeColor, optional long unselectedBadgeColor);
+    method public androidx.compose.foundation.layout.PaddingValues getItemPadding();
+    property public final androidx.compose.foundation.layout.PaddingValues ItemPadding;
+    field public static final androidx.compose.material3.NavigationDrawerItemDefaults INSTANCE;
+  }
+
+  public final class NavigationDrawerKt {
+    method @androidx.compose.runtime.Composable public static void DismissibleDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DismissibleNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationDrawerItem(kotlin.jvm.functions.Function0<kotlin.Unit> label, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? badge, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.NavigationDrawerItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void PermanentDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void PermanentNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static androidx.compose.material3.DrawerState rememberDrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public final class NavigationRailDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationRailDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationRailItemColors {
+  }
+
+  public final class NavigationRailItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationRailItemDefaults INSTANCE;
+  }
+
+  public final class NavigationRailKt {
+    method @androidx.compose.runtime.Composable public static void NavigationRail(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? header, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationRailItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationRailItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class OutlinedTextFieldKt {
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,? extends kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void OutlinedTextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,? extends kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class PlainTooltipState {
+    ctor public PlainTooltipState();
+    method public suspend Object? dismiss(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public boolean isVisible();
+    method public suspend Object? show(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public boolean isVisible;
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method @androidx.compose.runtime.Composable public long getCircularColor();
+    method public int getCircularDeterminateStrokeCap();
+    method public int getCircularIndeterminateStrokeCap();
+    method public float getCircularStrokeWidth();
+    method @androidx.compose.runtime.Composable public long getCircularTrackColor();
+    method @androidx.compose.runtime.Composable public long getLinearColor();
+    method public int getLinearStrokeCap();
+    method @androidx.compose.runtime.Composable public long getLinearTrackColor();
+    method public androidx.compose.animation.core.SpringSpec<java.lang.Float> getProgressAnimationSpec();
+    property public final int CircularDeterminateStrokeCap;
+    property public final int CircularIndeterminateStrokeCap;
+    property public final float CircularStrokeWidth;
+    property public final int LinearStrokeCap;
+    property public final androidx.compose.animation.core.SpringSpec<java.lang.Float> ProgressAnimationSpec;
+    property @androidx.compose.runtime.Composable public final long circularColor;
+    property @androidx.compose.runtime.Composable public final long circularTrackColor;
+    property @androidx.compose.runtime.Composable public final long linearColor;
+    property @androidx.compose.runtime.Composable public final long linearTrackColor;
+    field public static final androidx.compose.material3.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class ProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+  }
+
+  @androidx.compose.runtime.Immutable public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.RadioButtonColors colors(optional long selectedColor, optional long unselectedColor, optional long disabledSelectedColor, optional long disabledUnselectedColor);
+    field public static final androidx.compose.material3.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.RadioButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable @androidx.compose.runtime.Stable public final class RichTooltipColors {
+    ctor public RichTooltipColors(long containerColor, long contentColor, long titleContentColor, long actionContentColor);
+    method public long getActionContentColor();
+    method public long getContainerColor();
+    method public long getContentColor();
+    method public long getTitleContentColor();
+    property public final long actionContentColor;
+    property public final long containerColor;
+    property public final long contentColor;
+    property public final long titleContentColor;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class RichTooltipState {
+    ctor public RichTooltipState();
+    method public suspend Object? dismiss(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public boolean isVisible();
+    method public suspend Object? show(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public boolean isVisible;
+  }
+
+  public final class ScaffoldDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getContentWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets contentWindowInsets;
+    field public static final androidx.compose.material3.ScaffoldDefaults INSTANCE;
+  }
+
+  public final class ScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> snackbarHost, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, optional androidx.compose.foundation.layout.WindowInsets contentWindowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class SearchBarColors {
+    method public long getContainerColor();
+    method public long getDividerColor();
+    method public androidx.compose.material3.TextFieldColors getInputFieldColors();
+    property public final long containerColor;
+    property public final long dividerColor;
+    property public final androidx.compose.material3.TextFieldColors inputFieldColors;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class SearchBarDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SearchBarColors colors(optional long containerColor, optional long dividerColor, optional androidx.compose.material3.TextFieldColors inputFieldColors);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getDockedShape();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFullScreenShape();
+    method public float getInputFieldHeight();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getInputFieldShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors inputFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors! inputFieldColors(optional long textColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long placeholderColor, optional long disabledPlaceholderColor);
+    property public final float Elevation;
+    property public final float InputFieldHeight;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape dockedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape fullScreenShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape inputFieldShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.SearchBarDefaults INSTANCE;
+  }
+
+  public final class SearchBarKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DockedSearchBar(String query, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onQueryChange, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onSearch, boolean active, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onActiveChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SearchBarColors colors, optional float tonalElevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void SearchBar(String query, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onQueryChange, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onSearch, boolean active, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onActiveChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SearchBarColors colors, optional float tonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class SelectableChipBorder {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class SelectableChipColors {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class SelectableChipElevation {
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Small;
+    field public static final androidx.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.material3.Shapes copy(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape small;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class SheetState {
+    ctor public SheetState(boolean skipPartiallyExpanded, optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange);
+    method public suspend Object? expand(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.compose.material3.SheetValue getCurrentValue();
+    method public boolean getHasExpandedState();
+    method public boolean getHasPartiallyExpandedState();
+    method public androidx.compose.material3.SheetValue getTargetValue();
+    method public suspend Object? hide(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public boolean isVisible();
+    method public suspend Object? partialExpand(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public float requireOffset();
+    method public suspend Object? show(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final androidx.compose.material3.SheetValue currentValue;
+    property public final boolean hasExpandedState;
+    property public final boolean hasPartiallyExpandedState;
+    property public final boolean isVisible;
+    property public final androidx.compose.material3.SheetValue targetValue;
+    field public static final androidx.compose.material3.SheetState.Companion Companion;
+  }
+
+  public static final class SheetState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.SheetState,androidx.compose.material3.SheetValue> Saver(boolean skipPartiallyExpanded, kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public enum SheetValue {
+    method public static androidx.compose.material3.SheetValue valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SheetValue[] values();
+    enum_constant public static final androidx.compose.material3.SheetValue Expanded;
+    enum_constant public static final androidx.compose.material3.SheetValue Hidden;
+    enum_constant public static final androidx.compose.material3.SheetValue PartiallyExpanded;
+  }
+
+  @androidx.compose.runtime.Immutable public final class SliderColors {
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderDefaults {
+    method @androidx.compose.runtime.Composable public void Thumb(androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled, optional long thumbSize);
+    method @androidx.compose.runtime.Composable public void Track(androidx.compose.material3.SliderPositions sliderPositions, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SliderColors colors(optional long thumbColor, optional long activeTrackColor, optional long activeTickColor, optional long inactiveTrackColor, optional long inactiveTickColor, optional long disabledThumbColor, optional long disabledActiveTrackColor, optional long disabledActiveTickColor, optional long disabledInactiveTrackColor, optional long disabledInactiveTickColor);
+    field public static final androidx.compose.material3.SliderDefaults INSTANCE;
+  }
+
+  public final class SliderKt {
+    method @androidx.compose.runtime.Composable public static void RangeSlider(kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> value, kotlin.jvm.functions.Function1<? super kotlin.ranges.ClosedFloatingPointRange<java.lang.Float>,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void RangeSlider(kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> value, kotlin.jvm.functions.Function1<? super kotlin.ranges.ClosedFloatingPointRange<java.lang.Float>,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource startInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource endInteractionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SliderPositions,kotlin.Unit> startThumb, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SliderPositions,kotlin.Unit> endThumb, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SliderPositions,kotlin.Unit> track, optional int steps);
+    method @androidx.compose.runtime.Composable public static void Slider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void Slider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SliderPositions,kotlin.Unit> thumb, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SliderPositions,kotlin.Unit> track, optional int steps);
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderPositions {
+    ctor public SliderPositions(optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> initialActiveRange, optional float[] initialTickFractions);
+    method public kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> getActiveRange();
+    method public float[] getTickFractions();
+    property public final kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> activeRange;
+    property public final float[] tickFractions;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarData {
+    method public void dismiss();
+    method public androidx.compose.material3.SnackbarVisuals getVisuals();
+    method public void performAction();
+    property public abstract androidx.compose.material3.SnackbarVisuals visuals;
+  }
+
+  public final class SnackbarDefaults {
+    method @androidx.compose.runtime.Composable public long getActionColor();
+    method @androidx.compose.runtime.Composable public long getActionContentColor();
+    method @androidx.compose.runtime.Composable public long getColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method @androidx.compose.runtime.Composable public long getDismissActionContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property @androidx.compose.runtime.Composable public final long actionColor;
+    property @androidx.compose.runtime.Composable public final long actionContentColor;
+    property @androidx.compose.runtime.Composable public final long color;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    property @androidx.compose.runtime.Composable public final long dismissActionContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SnackbarDefaults INSTANCE;
+  }
+
+  public enum SnackbarDuration {
+    method public static androidx.compose.material3.SnackbarDuration valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarDuration[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Indefinite;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Long;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Short;
+  }
+
+  public final class SnackbarHostKt {
+    method @androidx.compose.runtime.Composable public static void SnackbarHost(androidx.compose.material3.SnackbarHostState hostState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarData,kotlin.Unit> snackbar);
+  }
+
+  @androidx.compose.runtime.Stable public final class SnackbarHostState {
+    ctor public SnackbarHostState();
+    method public androidx.compose.material3.SnackbarData? getCurrentSnackbarData();
+    method public suspend Object? showSnackbar(String message, optional String? actionLabel, optional boolean withDismissAction, optional androidx.compose.material3.SnackbarDuration duration, optional kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    method public suspend Object? showSnackbar(androidx.compose.material3.SnackbarVisuals visuals, kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    property public final androidx.compose.material3.SnackbarData? currentSnackbarData;
+  }
+
+  public final class SnackbarKt {
+    method @androidx.compose.runtime.Composable public static void Snackbar(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissAction, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionContentColor, optional long dismissActionContentColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Snackbar(androidx.compose.material3.SnackbarData snackbarData, optional androidx.compose.ui.Modifier modifier, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionColor, optional long actionContentColor, optional long dismissActionContentColor);
+  }
+
+  public enum SnackbarResult {
+    method public static androidx.compose.material3.SnackbarResult valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarResult[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarResult ActionPerformed;
+    enum_constant public static final androidx.compose.material3.SnackbarResult Dismissed;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarVisuals {
+    method public String? getActionLabel();
+    method public androidx.compose.material3.SnackbarDuration getDuration();
+    method public String getMessage();
+    method public boolean getWithDismissAction();
+    property public abstract String? actionLabel;
+    property public abstract androidx.compose.material3.SnackbarDuration duration;
+    property public abstract String message;
+    property public abstract boolean withDismissAction;
+  }
+
+  public final class SuggestionChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedSuggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedSuggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder suggestionChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors suggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation suggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SuggestionChipDefaults INSTANCE;
+  }
+
+  public final class SurfaceKt {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(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 long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> getLocalAbsoluteTonalElevation();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> LocalAbsoluteTonalElevation;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class SwipeToDismissDefaults {
+    method public kotlin.jvm.functions.Function2<androidx.compose.ui.unit.Density,java.lang.Float,java.lang.Float> getFixedPositionalThreshold();
+    property public final kotlin.jvm.functions.Function2<androidx.compose.ui.unit.Density,java.lang.Float,java.lang.Float> FixedPositionalThreshold;
+    field public static final androidx.compose.material3.SwipeToDismissDefaults INSTANCE;
+  }
+
+  public final class SwipeToDismissKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void SwipeToDismiss(androidx.compose.material3.DismissState state, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> background, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> dismissContent, optional androidx.compose.ui.Modifier modifier, optional java.util.Set<? extends androidx.compose.material3.DismissDirection> directions);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.DismissState rememberDismissState(optional androidx.compose.material3.DismissValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DismissValue,java.lang.Boolean> confirmValueChange, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.unit.Density,? super java.lang.Float,java.lang.Float> positionalThreshold);
+  }
+
+  @androidx.compose.runtime.Immutable public final class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedTrackColor, optional long checkedBorderColor, optional long checkedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedBorderColor, optional long uncheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledCheckedBorderColor, optional long disabledCheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedBorderColor, optional long disabledUncheckedIconColor);
+    method public float getIconSize();
+    property public final float IconSize;
+    field public static final androidx.compose.material3.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? thumbContent, optional boolean enabled, optional androidx.compose.material3.SwitchColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class TabKt {
+    method @androidx.compose.runtime.Composable public static void LeadingIconTab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TabPosition {
+    method public float getLeft();
+    method public float getRight();
+    method public float getWidth();
+    property public final float left;
+    property public final float right;
+    property public final float width;
+  }
+
+  public final class TabRowDefaults {
+    method @androidx.compose.runtime.Composable public void Indicator(optional androidx.compose.ui.Modifier modifier, optional float height, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method public androidx.compose.ui.Modifier tabIndicatorOffset(androidx.compose.ui.Modifier, androidx.compose.material3.TabPosition currentTabPosition);
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    field public static final androidx.compose.material3.TabRowDefaults INSTANCE;
+  }
+
+  public final class TabRowKt {
+    method @androidx.compose.runtime.Composable public static void ScrollableTabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float edgePadding, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+    method @androidx.compose.runtime.Composable public static void TabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldDefaults {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void FilledContainerBox(boolean enabled, boolean isError, androidx.compose.foundation.interaction.InteractionSource interactionSource, androidx.compose.material3.TextFieldColors colors, optional androidx.compose.ui.graphics.Shape shape);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void OutlinedBorderContainerBox(boolean enabled, boolean isError, androidx.compose.foundation.interaction.InteractionSource interactionSource, androidx.compose.material3.TextFieldColors colors, optional androidx.compose.ui.graphics.Shape shape, optional float focusedBorderThickness, optional float unfocusedBorderThickness);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void OutlinedTextFieldDecorationBox(String value, kotlin.jvm.functions.Function0<kotlin.Unit> innerTextField, boolean enabled, boolean singleLine, androidx.compose.ui.text.input.VisualTransformation visualTransformation, androidx.compose.foundation.interaction.InteractionSource interactionSource, optional boolean isError, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional androidx.compose.material3.TextFieldColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function0<kotlin.Unit> container);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void OutlinedTextFieldDecorationBox(String value, kotlin.jvm.functions.Function0<? extends kotlin.Unit> innerTextField, boolean enabled, boolean singleLine, androidx.compose.ui.text.input.VisualTransformation visualTransformation, androidx.compose.foundation.interaction.InteractionSource interactionSource, optional boolean isError, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional androidx.compose.material3.TextFieldColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit> container);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void TextFieldDecorationBox(String value, kotlin.jvm.functions.Function0<kotlin.Unit> innerTextField, boolean enabled, boolean singleLine, androidx.compose.ui.text.input.VisualTransformation visualTransformation, androidx.compose.foundation.interaction.InteractionSource interactionSource, optional boolean isError, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function0<kotlin.Unit> container);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public void TextFieldDecorationBox(String value, kotlin.jvm.functions.Function0<? extends kotlin.Unit> innerTextField, boolean enabled, boolean singleLine, androidx.compose.ui.text.input.VisualTransformation visualTransformation, androidx.compose.foundation.interaction.InteractionSource interactionSource, optional boolean isError, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit> container);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledShape();
+    method public float getFocusedBorderThickness();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method public float getUnfocusedBorderThickness();
+    method @androidx.compose.material3.ExperimentalMaterial3Api public androidx.compose.ui.Modifier indicatorLine(androidx.compose.ui.Modifier, boolean enabled, boolean isError, androidx.compose.foundation.interaction.InteractionSource interactionSource, androidx.compose.material3.TextFieldColors colors, optional float focusedIndicatorLineThickness, optional float unfocusedIndicatorLineThickness);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors outlinedTextFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long errorTextColor, optional long containerColor, optional long errorContainerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedBorderColor, optional long unfocusedBorderColor, optional long disabledBorderColor, optional long errorBorderColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor, optional long errorPlaceholderColor, optional long focusedSupportingTextColor, optional long unfocusedSupportingTextColor, optional long disabledSupportingTextColor, optional long errorSupportingTextColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors outlinedTextFieldColors(optional long textColor, optional long disabledTextColor, optional long containerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedBorderColor, optional long unfocusedBorderColor, optional long disabledBorderColor, optional long errorBorderColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long placeholderColor, optional long disabledPlaceholderColor, optional long focusedSupportingTextColor, optional long unfocusedSupportingTextColor, optional long disabledSupportingTextColor, optional long errorSupportingTextColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method public androidx.compose.foundation.layout.PaddingValues outlinedTextFieldPadding(optional float start, optional float top, optional float end, optional float bottom);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors textFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long errorTextColor, optional long containerColor, optional long errorContainerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedIndicatorColor, optional long unfocusedIndicatorColor, optional long disabledIndicatorColor, optional long errorIndicatorColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor, optional long errorPlaceholderColor, optional long focusedSupportingTextColor, optional long unfocusedSupportingTextColor, optional long disabledSupportingTextColor, optional long errorSupportingTextColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors textFieldColors(optional long textColor, optional long disabledTextColor, optional long containerColor, optional long cursorColor, optional long errorCursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedIndicatorColor, optional long unfocusedIndicatorColor, optional long disabledIndicatorColor, optional long errorIndicatorColor, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long errorLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long errorTrailingIconColor, optional long focusedLabelColor, optional long unfocusedLabelColor, optional long disabledLabelColor, optional long errorLabelColor, optional long placeholderColor, optional long disabledPlaceholderColor, optional long focusedSupportingTextColor, optional long unfocusedSupportingTextColor, optional long disabledSupportingTextColor, optional long errorSupportingTextColor, optional long focusedPrefixColor, optional long unfocusedPrefixColor, optional long disabledPrefixColor, optional long errorPrefixColor, optional long focusedSuffixColor, optional long unfocusedSuffixColor, optional long disabledSuffixColor, optional long errorSuffixColor);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithLabelPadding(optional float start, optional float end, optional float top, optional float bottom);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithoutLabelPadding(optional float start, optional float top, optional float end, optional float bottom);
+    property public final float FocusedBorderThickness;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final float UnfocusedBorderThickness;
+    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;
+    field public static final androidx.compose.material3.TextFieldDefaults INSTANCE;
+  }
+
+  public final class TextFieldKt {
+    method @androidx.compose.runtime.Composable public static void TextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void TextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,? extends kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,? extends kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<? extends kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class TimePickerColors {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TimePickerDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TimePickerColors colors(optional long clockDialColor, optional long clockDialSelectedContentColor, optional long clockDialUnselectedContentColor, optional long selectorColor, optional long containerColor, optional long periodSelectorBorderColor, optional long periodSelectorSelectedContainerColor, optional long periodSelectorUnselectedContainerColor, optional long periodSelectorSelectedContentColor, optional long periodSelectorUnselectedContentColor, optional long timeSelectorSelectedContainerColor, optional long timeSelectorUnselectedContainerColor, optional long timeSelectorSelectedContentColor, optional long timeSelectorUnselectedContentColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public int layoutType();
+    field public static final androidx.compose.material3.TimePickerDefaults INSTANCE;
+  }
+
+  public final class TimePickerKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TimeInput(androidx.compose.material3.TimePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.TimePickerColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TimePicker(androidx.compose.material3.TimePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.TimePickerColors colors, optional int layoutType);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TimePickerState rememberTimePickerState(optional int initialHour, optional int initialMinute, optional boolean is24Hour);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TimePickerLayoutType {
+    field public static final androidx.compose.material3.TimePickerLayoutType.Companion Companion;
+  }
+
+  public static final class TimePickerLayoutType.Companion {
+    method public int getHorizontal();
+    method public int getVertical();
+    property public final int Horizontal;
+    property public final int Vertical;
+  }
+
+  @androidx.compose.runtime.Stable public final class TimePickerState {
+    ctor public TimePickerState(int initialHour, int initialMinute, boolean is24Hour);
+    method public int getHour();
+    method public int getMinute();
+    method public boolean is24hour();
+    method public suspend Object? settle(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final int hour;
+    property public final boolean is24hour;
+    property public final int minute;
+    field public static final androidx.compose.material3.TimePickerState.Companion Companion;
+  }
+
+  public static final class TimePickerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TimePickerState,?> Saver();
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public interface TooltipBoxScope {
+    method public androidx.compose.ui.Modifier tooltipAnchor(androidx.compose.ui.Modifier);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class TooltipDefaults {
+    method @androidx.compose.runtime.Composable public long getPlainTooltipContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getPlainTooltipContainerShape();
+    method @androidx.compose.runtime.Composable public long getPlainTooltipContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRichTooltipContainerShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors(optional long containerColor, optional long contentColor, optional long titleContentColor, optional long actionContentColor);
+    property @androidx.compose.runtime.Composable public final long plainTooltipContainerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape plainTooltipContainerShape;
+    property @androidx.compose.runtime.Composable public final long plainTooltipContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape richTooltipContainerShape;
+    field public static final androidx.compose.material3.TooltipDefaults INSTANCE;
+  }
+
+  public final class TooltipKt {
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PlainTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.PlainTooltipState tooltipState, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void RichTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> text, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.RichTooltipState tooltipState, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.RichTooltipColors colors, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarColors {
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class TopAppBarDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior enterAlwaysScrollBehavior(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 @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 @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior pinnedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors smallTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    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 @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.TopAppBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface TopAppBarScrollBehavior {
+    method public androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? getFlingAnimationSpec();
+    method public androidx.compose.ui.input.nestedscroll.NestedScrollConnection getNestedScrollConnection();
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float>? getSnapAnimationSpec();
+    method public androidx.compose.material3.TopAppBarState getState();
+    method public boolean isPinned();
+    property public abstract androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec;
+    property public abstract boolean isPinned;
+    property public abstract androidx.compose.ui.input.nestedscroll.NestedScrollConnection nestedScrollConnection;
+    property public abstract androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec;
+    property public abstract androidx.compose.material3.TopAppBarState state;
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarState {
+    ctor public TopAppBarState(float initialHeightOffsetLimit, float initialHeightOffset, float initialContentOffset);
+    method public float getCollapsedFraction();
+    method public float getContentOffset();
+    method public float getHeightOffset();
+    method public float getHeightOffsetLimit();
+    method public float getOverlappedFraction();
+    method public void setContentOffset(float);
+    method public void setHeightOffset(float);
+    method public void setHeightOffsetLimit(float);
+    property public final float collapsedFraction;
+    property public final float contentOffset;
+    property public final float heightOffset;
+    property public final float heightOffsetLimit;
+    property public final float overlappedFraction;
+    field public static final androidx.compose.material3.TopAppBarState.Companion Companion;
+  }
+
+  public static final class TopAppBarState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,?> getSaver();
+    property public final androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,?> Saver;
+  }
+
+  @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);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    method public androidx.compose.ui.text.TextStyle getHeadlineLarge();
+    method public androidx.compose.ui.text.TextStyle getHeadlineMedium();
+    method public androidx.compose.ui.text.TextStyle getHeadlineSmall();
+    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 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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    property public final androidx.compose.ui.text.TextStyle headlineLarge;
+    property public final androidx.compose.ui.text.TextStyle headlineMedium;
+    property public final androidx.compose.ui.text.TextStyle headlineSmall;
+    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 titleLarge;
+    property public final androidx.compose.ui.text.TextStyle titleMedium;
+    property public final androidx.compose.ui.text.TextStyle titleSmall;
+  }
+
+}
+
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index 2cc9b86..30eb84f 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -96,7 +96,7 @@
   }
 
   public final class BottomSheetScaffoldKt {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void BottomSheetScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> sheetContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.BottomSheetScaffoldState scaffoldState, optional float sheetPeekHeight, optional androidx.compose.ui.graphics.Shape sheetShape, optional long sheetContainerColor, optional long sheetContentColor, optional float sheetTonalElevation, optional kotlin.jvm.functions.Function0<kotlin.Unit>? sheetDragHandle, optional boolean sheetSwipeEnabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? topBar, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarHostState,kotlin.Unit> snackbarHost, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void BottomSheetScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> sheetContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.BottomSheetScaffoldState scaffoldState, optional float sheetPeekHeight, optional androidx.compose.ui.graphics.Shape sheetShape, optional long sheetContainerColor, optional long sheetContentColor, optional float sheetTonalElevation, optional float sheetShadowElevation, optional kotlin.jvm.functions.Function0<kotlin.Unit>? sheetDragHandle, optional boolean sheetSwipeEnabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? topBar, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarHostState,kotlin.Unit> snackbarHost, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
     method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomSheetScaffoldState rememberBottomSheetScaffoldState(optional androidx.compose.material3.SheetState bottomSheetState, optional androidx.compose.material3.SnackbarHostState snackbarHostState);
     method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SheetState rememberStandardBottomSheetState(optional androidx.compose.material3.SheetValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SheetValue,java.lang.Boolean> confirmValueChange);
   }
@@ -858,16 +858,16 @@
     property public final androidx.compose.material3.TextFieldColors inputFieldColors;
   }
 
-  public final class SearchBarDefaults {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.SearchBarColors colors(optional long containerColor, optional long dividerColor, optional androidx.compose.material3.TextFieldColors inputFieldColors);
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class SearchBarDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SearchBarColors colors(optional long containerColor, optional long dividerColor, optional androidx.compose.material3.TextFieldColors inputFieldColors);
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getDockedShape();
     method public float getElevation();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFullScreenShape();
     method public float getInputFieldHeight();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getInputFieldShape();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors inputFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor);
-    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors! inputFieldColors(optional long textColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long placeholderColor, optional long disabledPlaceholderColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors inputFieldColors(optional long focusedTextColor, optional long unfocusedTextColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long focusedPlaceholderColor, optional long unfocusedPlaceholderColor, optional long disabledPlaceholderColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TextFieldColors! inputFieldColors(optional long textColor, optional long disabledTextColor, optional long cursorColor, optional androidx.compose.foundation.text.selection.TextSelectionColors selectionColors, optional long focusedLeadingIconColor, optional long unfocusedLeadingIconColor, optional long disabledLeadingIconColor, optional long focusedTrailingIconColor, optional long unfocusedTrailingIconColor, optional long disabledTrailingIconColor, optional long placeholderColor, optional long disabledPlaceholderColor);
     property public final float Elevation;
     property public final float InputFieldHeight;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape dockedShape;
@@ -1177,15 +1177,27 @@
 
   @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TimePickerDefaults {
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TimePickerColors colors(optional long clockDialColor, optional long clockDialSelectedContentColor, optional long clockDialUnselectedContentColor, optional long selectorColor, optional long containerColor, optional long periodSelectorBorderColor, optional long periodSelectorSelectedContainerColor, optional long periodSelectorUnselectedContainerColor, optional long periodSelectorSelectedContentColor, optional long periodSelectorUnselectedContentColor, optional long timeSelectorSelectedContainerColor, optional long timeSelectorUnselectedContainerColor, optional long timeSelectorSelectedContentColor, optional long timeSelectorUnselectedContentColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public int layoutType();
     field public static final androidx.compose.material3.TimePickerDefaults INSTANCE;
   }
 
   public final class TimePickerKt {
     method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TimeInput(androidx.compose.material3.TimePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.TimePickerColors colors);
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TimePicker(androidx.compose.material3.TimePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.TimePickerColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TimePicker(androidx.compose.material3.TimePickerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.TimePickerColors colors, optional int layoutType);
     method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TimePickerState rememberTimePickerState(optional int initialHour, optional int initialMinute, optional boolean is24Hour);
   }
 
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TimePickerLayoutType {
+    field public static final androidx.compose.material3.TimePickerLayoutType.Companion Companion;
+  }
+
+  public static final class TimePickerLayoutType.Companion {
+    method public int getHorizontal();
+    method public int getVertical();
+    property public final int Horizontal;
+    property public final int Vertical;
+  }
+
   @androidx.compose.runtime.Stable public final class TimePickerState {
     ctor public TimePickerState(int initialHour, int initialMinute, boolean is24Hour);
     method public int getHour();
diff --git a/compose/material3/material3/api/res-1.1.0-beta01.txt b/compose/material3/material3/api/res-1.1.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compose/material3/material3/api/res-1.1.0-beta01.txt
diff --git a/compose/material3/material3/api/restricted_1.1.0-beta01.txt b/compose/material3/material3/api/restricted_1.1.0-beta01.txt
new file mode 100644
index 0000000..7e2de6f
--- /dev/null
+++ b/compose/material3/material3/api/restricted_1.1.0-beta01.txt
@@ -0,0 +1,856 @@
+// Signature format: 4.0
+package androidx.compose.material3 {
+
+  public final class AlertDialogDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getIconContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public long getTextContentColor();
+    method @androidx.compose.runtime.Composable public long getTitleContentColor();
+    method public float getTonalElevation();
+    property public final float TonalElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long iconContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final long textContentColor;
+    property @androidx.compose.runtime.Composable public final long titleContentColor;
+    field public static final androidx.compose.material3.AlertDialogDefaults INSTANCE;
+  }
+
+  public final class AndroidAlertDialog_androidKt {
+    method @androidx.compose.runtime.Composable public static void AlertDialog(kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, kotlin.jvm.functions.Function0<kotlin.Unit> confirmButton, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissButton, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long iconContentColor, optional long titleContentColor, optional long textContentColor, optional float tonalElevation, optional androidx.compose.ui.window.DialogProperties properties);
+  }
+
+  public final class AndroidMenu_androidKt {
+    method @androidx.compose.runtime.Composable public static void DropdownMenu(boolean expanded, kotlin.jvm.functions.Function0<kotlin.Unit> onDismissRequest, optional androidx.compose.ui.Modifier modifier, optional long offset, optional androidx.compose.ui.window.PopupProperties properties, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DropdownMenuItem(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional boolean enabled, optional androidx.compose.material3.MenuItemColors colors, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class AppBarKt {
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? floatingActionButton, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets);
+    method @androidx.compose.runtime.Composable public static void BottomAppBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
+  public final class AssistChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder assistChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors assistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation assistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedAssistChipColors(optional long containerColor, optional long labelColor, optional long leadingIconContentColor, optional long trailingIconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledLeadingIconContentColor, optional long disabledTrailingIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedAssistChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.AssistChipDefaults INSTANCE;
+  }
+
+  public final class BottomAppBarDefaults {
+    method @androidx.compose.runtime.Composable public long getBottomAppBarFabColor();
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getContainerElevation();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float ContainerElevation;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property @androidx.compose.runtime.Composable public final long bottomAppBarFabColor;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.BottomAppBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class ButtonColors {
+  }
+
+  public final class ButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors buttonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation buttonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors elevatedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation elevatedButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors filledTonalButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonElevation filledTonalButtonElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float disabledElevation);
+    method public androidx.compose.foundation.layout.PaddingValues getButtonWithIconContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledTonalShape();
+    method public float getIconSize();
+    method public float getIconSpacing();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke getOutlinedButtonBorder();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonContentPadding();
+    method public androidx.compose.foundation.layout.PaddingValues getTextButtonWithIconContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTextShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors outlinedButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ButtonColors textButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    property public final androidx.compose.foundation.layout.PaddingValues ButtonWithIconContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues ContentPadding;
+    property public final float IconSize;
+    property public final float IconSpacing;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonContentPadding;
+    property public final androidx.compose.foundation.layout.PaddingValues TextButtonWithIconContentPadding;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape filledTonalShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.BorderStroke outlinedButtonBorder;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape textShape;
+    field public static final androidx.compose.material3.ButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class ButtonElevation {
+  }
+
+  public final class ButtonKt {
+    method @androidx.compose.runtime.Composable public static void Button(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ElevatedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void FilledTonalButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void TextButton(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.ButtonColors colors, optional androidx.compose.material3.ButtonElevation? elevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardColors {
+  }
+
+  public final class CardDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors cardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation cardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors elevatedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation elevatedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.BorderStroke outlinedCardBorder(optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardColors outlinedCardColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CardElevation outlinedCardElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.CardDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class CardElevation {
+  }
+
+  public final class CardKt {
+    method @androidx.compose.runtime.Composable public static void Card(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, 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 static void ElevatedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void OutlinedCard(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.CardColors colors, optional androidx.compose.material3.CardElevation elevation, optional androidx.compose.foundation.BorderStroke border, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class CheckboxColors {
+  }
+
+  public final class CheckboxDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.CheckboxColors colors(optional long checkedColor, optional long uncheckedColor, optional long checkmarkColor, optional long disabledCheckedColor, optional long disabledUncheckedColor, optional long disabledIndeterminateColor);
+    field public static final androidx.compose.material3.CheckboxDefaults INSTANCE;
+  }
+
+  public final class CheckboxKt {
+    method @androidx.compose.runtime.Composable public static void Checkbox(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.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void TriStateCheckbox(androidx.compose.ui.state.ToggleableState state, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.CheckboxColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipBorder {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class ChipElevation {
+  }
+
+  public final class ChipKt {
+    method @androidx.compose.runtime.Composable public static void AssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedAssistChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void ElevatedSuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void SuggestionChip(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> label, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipColors colors, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public final class ColorScheme {
+    ctor public ColorScheme(long primary, long onPrimary, long primaryContainer, long onPrimaryContainer, long inversePrimary, long secondary, long onSecondary, long secondaryContainer, long onSecondaryContainer, long tertiary, long onTertiary, long tertiaryContainer, long onTertiaryContainer, long background, long onBackground, long surface, long onSurface, long surfaceVariant, long onSurfaceVariant, long surfaceTint, long inverseSurface, long inverseOnSurface, long error, long onError, long errorContainer, long onErrorContainer, long outline, long outlineVariant, long scrim);
+    method public androidx.compose.material3.ColorScheme copy(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public long getBackground();
+    method public long getError();
+    method public long getErrorContainer();
+    method public long getInverseOnSurface();
+    method public long getInversePrimary();
+    method public long getInverseSurface();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnErrorContainer();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getScrim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSurface();
+    method public long getSurfaceTint();
+    method public long getSurfaceVariant();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    property public final long background;
+    property public final long error;
+    property public final long errorContainer;
+    property public final long inverseOnSurface;
+    property public final long inversePrimary;
+    property public final long inverseSurface;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onErrorContainer;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long scrim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long surface;
+    property public final long surfaceTint;
+    property public final long surfaceVariant;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+    method public static androidx.compose.material3.ColorScheme darkColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static androidx.compose.material3.ColorScheme lightColorScheme(optional long primary, optional long onPrimary, optional long primaryContainer, optional long onPrimaryContainer, optional long inversePrimary, optional long secondary, optional long onSecondary, optional long secondaryContainer, optional long onSecondaryContainer, optional long tertiary, optional long onTertiary, optional long tertiaryContainer, optional long onTertiaryContainer, optional long background, optional long onBackground, optional long surface, optional long onSurface, optional long surfaceVariant, optional long onSurfaceVariant, optional long surfaceTint, optional long inverseSurface, optional long inverseOnSurface, optional long error, optional long onError, optional long errorContainer, optional long onErrorContainer, optional long outline, optional long outlineVariant, optional long scrim);
+    method public static long surfaceColorAtElevation(androidx.compose.material3.ColorScheme, float elevation);
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  public final class DividerDefaults {
+    method @androidx.compose.runtime.Composable public long getColor();
+    method public float getThickness();
+    property public final float Thickness;
+    property @androidx.compose.runtime.Composable public final long color;
+    field public static final androidx.compose.material3.DividerDefaults INSTANCE;
+  }
+
+  public final class DividerKt {
+    method @androidx.compose.runtime.Composable public static void Divider(optional androidx.compose.ui.Modifier modifier, optional float thickness, optional long color);
+  }
+
+  public final class DrawerDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getDismissibleDrawerElevation();
+    method public float getMaximumDrawerWidth();
+    method public float getModalDrawerElevation();
+    method public float getPermanentDrawerElevation();
+    method @androidx.compose.runtime.Composable public long getScrimColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float DismissibleDrawerElevation;
+    property public final float MaximumDrawerWidth;
+    property public final float ModalDrawerElevation;
+    property public final float PermanentDrawerElevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long scrimColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.DrawerDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class DrawerState {
+    ctor public DrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+    method public suspend Object? animateTo(androidx.compose.material3.DrawerValue targetValue, androidx.compose.animation.core.AnimationSpec<java.lang.Float> anim, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? close(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.compose.material3.DrawerValue getCurrentValue();
+    method public androidx.compose.runtime.State<java.lang.Float> getOffset();
+    method public androidx.compose.material3.DrawerValue getTargetValue();
+    method public boolean isAnimationRunning();
+    method public boolean isClosed();
+    method public boolean isOpen();
+    method public suspend Object? open(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? snapTo(androidx.compose.material3.DrawerValue targetValue, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final androidx.compose.material3.DrawerValue currentValue;
+    property public final boolean isAnimationRunning;
+    property public final boolean isClosed;
+    property public final boolean isOpen;
+    property public final androidx.compose.runtime.State<java.lang.Float> offset;
+    property public final androidx.compose.material3.DrawerValue targetValue;
+    field public static final androidx.compose.material3.DrawerState.Companion Companion;
+  }
+
+  public static final class DrawerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.DrawerState,androidx.compose.material3.DrawerValue> Saver(kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public enum DrawerValue {
+    method public static androidx.compose.material3.DrawerValue valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.DrawerValue[] values();
+    enum_constant public static final androidx.compose.material3.DrawerValue Closed;
+    enum_constant public static final androidx.compose.material3.DrawerValue Open;
+  }
+
+  public final class DynamicTonalPaletteKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicDarkColorScheme(android.content.Context context);
+    method @RequiresApi(android.os.Build.VERSION_CODES.S) public static androidx.compose.material3.ColorScheme dynamicLightColorScheme(android.content.Context context);
+  }
+
+  @kotlin.jvm.JvmInline public final value class FabPosition {
+    field public static final androidx.compose.material3.FabPosition.Companion Companion;
+  }
+
+  public static final class FabPosition.Companion {
+    method public int getCenter();
+    method public int getEnd();
+    property public final int Center;
+    property public final int End;
+  }
+
+  public final class FloatingActionButtonDefaults {
+    method public androidx.compose.material3.FloatingActionButtonElevation bottomAppBarFabElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation elevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getExtendedFabShape();
+    method public float getLargeIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getLargeShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSmallShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.FloatingActionButtonElevation loweredElevation(optional float defaultElevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation);
+    property public final float LargeIconSize;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape extendedFabShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape largeShape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape smallShape;
+    field public static final androidx.compose.material3.FloatingActionButtonDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public class FloatingActionButtonElevation {
+  }
+
+  public final class FloatingActionButtonKt {
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconButtonColors {
+  }
+
+  public final class IconButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors filledIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconToggleButtonColors filledIconToggleButtonColors(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.material3.IconButtonColors filledTonalIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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.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(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.foundation.BorderStroke outlinedIconButtonBorder(boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.IconButtonColors outlinedIconButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor);
+    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(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
+    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;
+    field public static final androidx.compose.material3.IconButtonDefaults INSTANCE;
+  }
+
+  public final class IconButtonKt {
+    method @androidx.compose.runtime.Composable public static void FilledIconButton(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 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 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);
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  @androidx.compose.runtime.Immutable public final class IconToggleButtonColors {
+  }
+
+  public final class InteractiveComponentSizeKt {
+    method public static androidx.compose.ui.Modifier minimumInteractiveComponentSize(androidx.compose.ui.Modifier);
+  }
+
+  @androidx.compose.runtime.Immutable public final class ListItemColors {
+  }
+
+  public final class ListItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ListItemColors colors(optional long containerColor, optional long headlineColor, optional long leadingIconColor, optional long overlineColor, optional long supportingColor, optional long trailingIconColor, optional long disabledHeadlineColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContainerColor();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public long getContentColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.graphics.Shape getShape();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long containerColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final long contentColor;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.ListItemDefaults INSTANCE;
+  }
+
+  public final class ListItemKt {
+    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);
+  }
+
+  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();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.compose.material3.Typography typography;
+    field public static final androidx.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    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);
+  }
+
+  public final class MenuDefaults {
+    method public androidx.compose.foundation.layout.PaddingValues getDropdownMenuItemContentPadding();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.MenuItemColors itemColors(optional long textColor, optional long leadingIconColor, optional long trailingIconColor, optional long disabledTextColor, optional long disabledLeadingIconColor, optional long disabledTrailingIconColor);
+    property public final androidx.compose.foundation.layout.PaddingValues DropdownMenuItemContentPadding;
+    field public static final androidx.compose.material3.MenuDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class MenuItemColors {
+  }
+
+  public final class NavigationBarDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method public float getElevation();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property public final float Elevation;
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationBarDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationBarItemColors {
+  }
+
+  public final class NavigationBarItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationBarItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationBarItemDefaults INSTANCE;
+  }
+
+  public final class NavigationBarKt {
+    method @androidx.compose.runtime.Composable public static void NavigationBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationBarItem(androidx.compose.foundation.layout.RowScope, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationBarItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public interface NavigationDrawerItemColors {
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> badgeColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> containerColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> iconColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> textColor(boolean selected);
+  }
+
+  public final class NavigationDrawerItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationDrawerItemColors colors(optional long selectedContainerColor, optional long unselectedContainerColor, optional long selectedIconColor, optional long unselectedIconColor, optional long selectedTextColor, optional long unselectedTextColor, optional long selectedBadgeColor, optional long unselectedBadgeColor);
+    method public androidx.compose.foundation.layout.PaddingValues getItemPadding();
+    property public final androidx.compose.foundation.layout.PaddingValues ItemPadding;
+    field public static final androidx.compose.material3.NavigationDrawerItemDefaults INSTANCE;
+  }
+
+  public final class NavigationDrawerKt {
+    method @androidx.compose.runtime.Composable public static void DismissibleDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void DismissibleNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ModalNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationDrawerItem(kotlin.jvm.functions.Function0<kotlin.Unit> label, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? badge, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.NavigationDrawerItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void PermanentDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void PermanentNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static androidx.compose.material3.DrawerState rememberDrawerState(androidx.compose.material3.DrawerValue initialValue, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.DrawerValue,java.lang.Boolean> confirmStateChange);
+  }
+
+  public final class NavigationRailDefaults {
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final long ContainerColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.NavigationRailDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Stable public final class NavigationRailItemColors {
+  }
+
+  public final class NavigationRailItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor, optional long disabledIconColor, optional long disabledTextColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationRailItemColors colors(optional long selectedIconColor, optional long selectedTextColor, optional long indicatorColor, optional long unselectedIconColor, optional long unselectedTextColor);
+    field public static final androidx.compose.material3.NavigationRailItemDefaults INSTANCE;
+  }
+
+  public final class NavigationRailKt {
+    method @androidx.compose.runtime.Composable public static void NavigationRail(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? header, optional androidx.compose.foundation.layout.WindowInsets windowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void NavigationRailItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.material3.NavigationRailItemColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class OutlinedTextFieldKt {
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void OutlinedTextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  public final class ProgressIndicatorDefaults {
+    method @androidx.compose.runtime.Composable public long getCircularColor();
+    method public int getCircularDeterminateStrokeCap();
+    method public int getCircularIndeterminateStrokeCap();
+    method public float getCircularStrokeWidth();
+    method @androidx.compose.runtime.Composable public long getCircularTrackColor();
+    method @androidx.compose.runtime.Composable public long getLinearColor();
+    method public int getLinearStrokeCap();
+    method @androidx.compose.runtime.Composable public long getLinearTrackColor();
+    method public androidx.compose.animation.core.SpringSpec<java.lang.Float> getProgressAnimationSpec();
+    property public final int CircularDeterminateStrokeCap;
+    property public final int CircularIndeterminateStrokeCap;
+    property public final float CircularStrokeWidth;
+    property public final int LinearStrokeCap;
+    property public final androidx.compose.animation.core.SpringSpec<java.lang.Float> ProgressAnimationSpec;
+    property @androidx.compose.runtime.Composable public final long circularColor;
+    property @androidx.compose.runtime.Composable public final long circularTrackColor;
+    property @androidx.compose.runtime.Composable public final long linearColor;
+    property @androidx.compose.runtime.Composable public final long linearTrackColor;
+    field public static final androidx.compose.material3.ProgressIndicatorDefaults INSTANCE;
+  }
+
+  public final class ProgressIndicatorKt {
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @Deprecated @androidx.compose.runtime.Composable public static void CircularProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor, optional int strokeCap);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+    method @Deprecated @androidx.compose.runtime.Composable public static void LinearProgressIndicator(optional androidx.compose.ui.Modifier modifier, optional long color, optional long trackColor);
+  }
+
+  @androidx.compose.runtime.Immutable public final class RadioButtonColors {
+  }
+
+  public final class RadioButtonDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.RadioButtonColors colors(optional long selectedColor, optional long unselectedColor, optional long disabledSelectedColor, optional long disabledUnselectedColor);
+    field public static final androidx.compose.material3.RadioButtonDefaults INSTANCE;
+  }
+
+  public final class RadioButtonKt {
+    method @androidx.compose.runtime.Composable public static void RadioButton(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.material3.RadioButtonColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class ScaffoldDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getContentWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets contentWindowInsets;
+    field public static final androidx.compose.material3.ScaffoldDefaults INSTANCE;
+  }
+
+  public final class ScaffoldKt {
+    method @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> snackbarHost, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, optional androidx.compose.foundation.layout.WindowInsets contentWindowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape Small;
+    field public static final androidx.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.material3.Shapes copy(optional androidx.compose.foundation.shape.CornerBasedShape extraSmall, optional androidx.compose.foundation.shape.CornerBasedShape small, optional androidx.compose.foundation.shape.CornerBasedShape medium, optional androidx.compose.foundation.shape.CornerBasedShape large, optional androidx.compose.foundation.shape.CornerBasedShape extraLarge);
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
+    method public androidx.compose.foundation.shape.CornerBasedShape getLarge();
+    method public androidx.compose.foundation.shape.CornerBasedShape getMedium();
+    method public androidx.compose.foundation.shape.CornerBasedShape getSmall();
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraLarge;
+    property public final androidx.compose.foundation.shape.CornerBasedShape extraSmall;
+    property public final androidx.compose.foundation.shape.CornerBasedShape large;
+    property public final androidx.compose.foundation.shape.CornerBasedShape medium;
+    property public final androidx.compose.foundation.shape.CornerBasedShape small;
+  }
+
+  @androidx.compose.runtime.Immutable public final class SliderColors {
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderDefaults {
+    method @androidx.compose.runtime.Composable public void Thumb(androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled, optional long thumbSize);
+    method @androidx.compose.runtime.Composable public void Track(androidx.compose.material3.SliderPositions sliderPositions, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.SliderColors colors, optional boolean enabled);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SliderColors colors(optional long thumbColor, optional long activeTrackColor, optional long activeTickColor, optional long inactiveTrackColor, optional long inactiveTickColor, optional long disabledThumbColor, optional long disabledActiveTrackColor, optional long disabledActiveTickColor, optional long disabledInactiveTrackColor, optional long disabledInactiveTickColor);
+    field public static final androidx.compose.material3.SliderDefaults INSTANCE;
+  }
+
+  public final class SliderKt {
+    method @androidx.compose.runtime.Composable public static void RangeSlider(kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> value, kotlin.jvm.functions.Function1<? super kotlin.ranges.ClosedFloatingPointRange<java.lang.Float>,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors);
+    method @androidx.compose.runtime.Composable public static void Slider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional int steps, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished, optional androidx.compose.material3.SliderColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  @androidx.compose.runtime.Stable public final class SliderPositions {
+    ctor public SliderPositions(optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> initialActiveRange, optional float[] initialTickFractions);
+    method public kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> getActiveRange();
+    method public float[] getTickFractions();
+    property public final kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> activeRange;
+    property public final float[] tickFractions;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarData {
+    method public void dismiss();
+    method public androidx.compose.material3.SnackbarVisuals getVisuals();
+    method public void performAction();
+    property public abstract androidx.compose.material3.SnackbarVisuals visuals;
+  }
+
+  public final class SnackbarDefaults {
+    method @androidx.compose.runtime.Composable public long getActionColor();
+    method @androidx.compose.runtime.Composable public long getActionContentColor();
+    method @androidx.compose.runtime.Composable public long getColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method @androidx.compose.runtime.Composable public long getDismissActionContentColor();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    property @androidx.compose.runtime.Composable public final long actionColor;
+    property @androidx.compose.runtime.Composable public final long actionContentColor;
+    property @androidx.compose.runtime.Composable public final long color;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    property @androidx.compose.runtime.Composable public final long dismissActionContentColor;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SnackbarDefaults INSTANCE;
+  }
+
+  public enum SnackbarDuration {
+    method public static androidx.compose.material3.SnackbarDuration valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarDuration[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Indefinite;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Long;
+    enum_constant public static final androidx.compose.material3.SnackbarDuration Short;
+  }
+
+  public final class SnackbarHostKt {
+    method @androidx.compose.runtime.Composable public static void SnackbarHost(androidx.compose.material3.SnackbarHostState hostState, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.SnackbarData,kotlin.Unit> snackbar);
+  }
+
+  @androidx.compose.runtime.Stable public final class SnackbarHostState {
+    ctor public SnackbarHostState();
+    method public androidx.compose.material3.SnackbarData? getCurrentSnackbarData();
+    method public suspend Object? showSnackbar(String message, optional String? actionLabel, optional boolean withDismissAction, optional androidx.compose.material3.SnackbarDuration duration, optional kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    method public suspend Object? showSnackbar(androidx.compose.material3.SnackbarVisuals visuals, kotlin.coroutines.Continuation<? super androidx.compose.material3.SnackbarResult>);
+    property public final androidx.compose.material3.SnackbarData? currentSnackbarData;
+  }
+
+  public final class SnackbarKt {
+    method @androidx.compose.runtime.Composable public static void Snackbar(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional kotlin.jvm.functions.Function0<kotlin.Unit>? dismissAction, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionContentColor, optional long dismissActionContentColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Snackbar(androidx.compose.material3.SnackbarData snackbarData, optional androidx.compose.ui.Modifier modifier, optional boolean actionOnNewLine, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional long actionColor, optional long actionContentColor, optional long dismissActionContentColor);
+  }
+
+  public enum SnackbarResult {
+    method public static androidx.compose.material3.SnackbarResult valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.SnackbarResult[] values();
+    enum_constant public static final androidx.compose.material3.SnackbarResult ActionPerformed;
+    enum_constant public static final androidx.compose.material3.SnackbarResult Dismissed;
+  }
+
+  @androidx.compose.runtime.Stable public interface SnackbarVisuals {
+    method public String? getActionLabel();
+    method public androidx.compose.material3.SnackbarDuration getDuration();
+    method public String getMessage();
+    method public boolean getWithDismissAction();
+    property public abstract String? actionLabel;
+    property public abstract androidx.compose.material3.SnackbarDuration duration;
+    property public abstract String message;
+    property public abstract boolean withDismissAction;
+  }
+
+  public final class SuggestionChipDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors elevatedSuggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation elevatedSuggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    method public float getHeight();
+    method public float getIconSize();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipBorder suggestionChipBorder(optional long borderColor, optional long disabledBorderColor, optional float borderWidth);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipColors suggestionChipColors(optional long containerColor, optional long labelColor, optional long iconContentColor, optional long disabledContainerColor, optional long disabledLabelColor, optional long disabledIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.ChipElevation suggestionChipElevation(optional float elevation, optional float pressedElevation, optional float focusedElevation, optional float hoveredElevation, optional float draggedElevation, optional float disabledElevation);
+    property public final float Height;
+    property public final float IconSize;
+    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
+    field public static final androidx.compose.material3.SuggestionChipDefaults INSTANCE;
+  }
+
+  public final class SurfaceKt {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable public static void Surface(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, 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 @androidx.compose.runtime.NonRestartableComposable public static void Surface(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 long color, optional long contentColor, optional float tonalElevation, optional float shadowElevation, optional androidx.compose.foundation.BorderStroke? border, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> getLocalAbsoluteTonalElevation();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> LocalAbsoluteTonalElevation;
+  }
+
+  @androidx.compose.runtime.Immutable public final class SwitchColors {
+  }
+
+  public final class SwitchDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.SwitchColors colors(optional long checkedThumbColor, optional long checkedTrackColor, optional long checkedBorderColor, optional long checkedIconColor, optional long uncheckedThumbColor, optional long uncheckedTrackColor, optional long uncheckedBorderColor, optional long uncheckedIconColor, optional long disabledCheckedThumbColor, optional long disabledCheckedTrackColor, optional long disabledCheckedBorderColor, optional long disabledCheckedIconColor, optional long disabledUncheckedThumbColor, optional long disabledUncheckedTrackColor, optional long disabledUncheckedBorderColor, optional long disabledUncheckedIconColor);
+    method public float getIconSize();
+    property public final float IconSize;
+    field public static final androidx.compose.material3.SwitchDefaults INSTANCE;
+  }
+
+  public final class SwitchKt {
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onCheckedChange, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? thumbContent, optional boolean enabled, optional androidx.compose.material3.SwitchColors colors, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+  }
+
+  public final class TabKt {
+    method @androidx.compose.runtime.Composable public static void LeadingIconTab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? text, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @androidx.compose.runtime.Composable public static void Tab(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional long selectedContentColor, optional long unselectedContentColor, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TabPosition {
+    method public float getLeft();
+    method public float getRight();
+    method public float getWidth();
+    property public final float left;
+    property public final float right;
+    property public final float width;
+  }
+
+  public final class TabRowDefaults {
+    method @androidx.compose.runtime.Composable public void Indicator(optional androidx.compose.ui.Modifier modifier, optional float height, optional long color);
+    method @androidx.compose.runtime.Composable public long getContainerColor();
+    method @androidx.compose.runtime.Composable public long getContentColor();
+    method public androidx.compose.ui.Modifier tabIndicatorOffset(androidx.compose.ui.Modifier, androidx.compose.material3.TabPosition currentTabPosition);
+    property @androidx.compose.runtime.Composable public final long containerColor;
+    property @androidx.compose.runtime.Composable public final long contentColor;
+    field public static final androidx.compose.material3.TabRowDefaults INSTANCE;
+  }
+
+  public final class TabRowKt {
+    method @androidx.compose.runtime.Composable public static void ScrollableTabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float edgePadding, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+    method @androidx.compose.runtime.Composable public static void TabRow(int selectedTabIndex, optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super java.util.List<androidx.compose.material3.TabPosition>,kotlin.Unit> indicator, optional kotlin.jvm.functions.Function0<kotlin.Unit> divider, kotlin.jvm.functions.Function0<kotlin.Unit> tabs);
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldColors {
+  }
+
+  @androidx.compose.runtime.Immutable public final class TextFieldDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFilledShape();
+    method public float getFocusedBorderThickness();
+    method public float getMinHeight();
+    method public float getMinWidth();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
+    method public float getUnfocusedBorderThickness();
+    method public androidx.compose.foundation.layout.PaddingValues outlinedTextFieldPadding(optional float start, optional float top, optional float end, optional float bottom);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithLabelPadding(optional float start, optional float end, optional float top, optional float bottom);
+    method public androidx.compose.foundation.layout.PaddingValues textFieldWithoutLabelPadding(optional float start, optional float top, optional float end, optional float bottom);
+    property public final float FocusedBorderThickness;
+    property public final float MinHeight;
+    property public final float MinWidth;
+    property public final float UnfocusedBorderThickness;
+    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;
+    field public static final androidx.compose.material3.TextFieldDefaults INSTANCE;
+  }
+
+  public final class TextFieldKt {
+    method @androidx.compose.runtime.Composable public static void TextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+    method @androidx.compose.runtime.Composable public static void TextField(androidx.compose.ui.text.input.TextFieldValue value, kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.input.TextFieldValue,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,? extends androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,? extends kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @androidx.compose.runtime.Stable public final class TimePickerState {
+    ctor public TimePickerState(int initialHour, int initialMinute, boolean is24Hour);
+    method public int getHour();
+    method public int getMinute();
+    method public boolean is24hour();
+    method public suspend Object? settle(kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public final int hour;
+    property public final boolean is24hour;
+    property public final int minute;
+    field public static final androidx.compose.material3.TimePickerState.Companion Companion;
+  }
+
+  public static final class TimePickerState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TimePickerState,?> Saver();
+  }
+
+  @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);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    method public androidx.compose.ui.text.TextStyle getHeadlineLarge();
+    method public androidx.compose.ui.text.TextStyle getHeadlineMedium();
+    method public androidx.compose.ui.text.TextStyle getHeadlineSmall();
+    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 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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    property public final androidx.compose.ui.text.TextStyle headlineLarge;
+    property public final androidx.compose.ui.text.TextStyle headlineMedium;
+    property public final androidx.compose.ui.text.TextStyle headlineSmall;
+    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 titleLarge;
+    property public final androidx.compose.ui.text.TextStyle titleMedium;
+    property public final androidx.compose.ui.text.TextStyle titleSmall;
+  }
+
+}
+
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index e6d7e92..7e2de6f 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -578,22 +578,6 @@
     method @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> snackbarHost, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, optional androidx.compose.foundation.layout.WindowInsets contentWindowInsets, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
   }
 
-  public final class SearchBarDefaults {
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getDockedShape();
-    method public float getElevation();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getFullScreenShape();
-    method public float getInputFieldHeight();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getInputFieldShape();
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property public final float Elevation;
-    property public final float InputFieldHeight;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape dockedShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape fullScreenShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape inputFieldShape;
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.SearchBarDefaults INSTANCE;
-  }
-
   public final class ShapeDefaults {
     method public androidx.compose.foundation.shape.CornerBasedShape getExtraLarge();
     method public androidx.compose.foundation.shape.CornerBasedShape getExtraSmall();
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt
index bebe797..96ec1a0 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt
@@ -42,7 +42,6 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.semantics.isContainer
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.tooling.preview.Preview
@@ -56,12 +55,6 @@
 fun SearchBarSample() {
     var text by rememberSaveable { mutableStateOf("") }
     var active by rememberSaveable { mutableStateOf(false) }
-    val focusManager = LocalFocusManager.current
-
-    fun closeSearchBar() {
-        focusManager.clearFocus()
-        active = false
-    }
 
     Box(Modifier.fillMaxSize()) {
         // Talkback focus order sorts based on x and y position before considering z-index. The
@@ -72,11 +65,10 @@
                 modifier = Modifier.align(Alignment.TopCenter),
                 query = text,
                 onQueryChange = { text = it },
-                onSearch = { closeSearchBar() },
+                onSearch = { active = false },
                 active = active,
                 onActiveChange = {
                     active = it
-                    if (!active) focusManager.clearFocus()
                 },
                 placeholder = { Text("Hinted search text") },
                 leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
@@ -95,7 +87,7 @@
                             leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) },
                             modifier = Modifier.clickable {
                                 text = resultText
-                                closeSearchBar()
+                                active = false
                             }
                         )
                     }
@@ -122,12 +114,6 @@
 fun DockedSearchBarSample() {
     var text by rememberSaveable { mutableStateOf("") }
     var active by rememberSaveable { mutableStateOf(false) }
-    val focusManager = LocalFocusManager.current
-
-    fun closeSearchBar() {
-        focusManager.clearFocus()
-        active = false
-    }
 
     Box(Modifier.fillMaxSize()) {
         // Talkback focus order sorts based on x and y position before considering z-index. The
@@ -138,12 +124,9 @@
                 modifier = Modifier.align(Alignment.TopCenter).padding(top = 8.dp),
                 query = text,
                 onQueryChange = { text = it },
-                onSearch = { closeSearchBar() },
+                onSearch = { active = false },
                 active = active,
-                onActiveChange = {
-                    active = it
-                    if (!active) focusManager.clearFocus()
-                },
+                onActiveChange = { active = it },
                 placeholder = { Text("Hinted search text") },
                 leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
                 trailingIcon = { Icon(Icons.Default.MoreVert, contentDescription = null) },
@@ -161,7 +144,7 @@
                             leadingContent = { Icon(Icons.Filled.Star, contentDescription = null) },
                             modifier = Modifier.clickable {
                                 text = resultText
-                                closeSearchBar()
+                                active = false
                             }
                         )
                     }
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TimePickerSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TimePickerSamples.kt
index 94a3911..e811231 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TimePickerSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TimePickerSamples.kt
@@ -22,17 +22,17 @@
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.IntrinsicSize
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 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.layout.width
-import androidx.compose.material.Button
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Keyboard
 import androidx.compose.material.icons.outlined.Schedule
+import androidx.compose.material3.Button
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
@@ -54,10 +54,13 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.semantics.isContainer
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.Dialog
 import androidx.compose.ui.window.DialogProperties
+import androidx.compose.ui.zIndex
 import java.text.SimpleDateFormat
 import java.util.Calendar
 import java.util.Locale
@@ -162,11 +165,7 @@
 
     if (showTimePicker) {
         TimePickerDialog(
-            title = if (showingPicker.value) {
-                "Select Time "
-            } else {
-                "Enter Time"
-            },
+            title = if (showingPicker.value) { "Select Time " } else { "Enter Time" },
             onCancel = { showTimePicker = false },
             onConfirm = {
                 val cal = Calendar.getInstance()
@@ -179,28 +178,43 @@
                 showTimePicker = false
             },
             toggle = {
-                if (configuration.screenHeightDp > 540) {
-                    IconButton(
-                        modifier = Modifier.offset(x = -(8.dp)),
-                        onClick = { showingPicker.value = !showingPicker.value }) {
-                        val icon = if (showingPicker.value) {
-                            Icons.Outlined.Keyboard
-                        } else {
-                            Icons.Outlined.Schedule
-                        }
-                        Icon(
-                            icon,
-                            contentDescription = if (showingPicker.value) {
-                                "Switch to Text Input"
+                if (configuration.screenHeightDp > 400) {
+                    // Make this take the entire viewport. This will guarantee that Screen readers
+                    // focus the toggle first.
+                    Box(
+                        Modifier
+                            .fillMaxSize()
+                            .semantics { isContainer = true }
+                    ) {
+                        IconButton(
+                            modifier = Modifier
+                                // This is a workaround so that the Icon comes up first
+                                // in the talkback traversal order. So that users of a11y
+                                // services can use the text input. When talkback traversal
+                                // order is customizable we can remove this.
+                                .size(64.dp, 72.dp)
+                                .align(Alignment.BottomStart)
+                                .zIndex(5f),
+                            onClick = { showingPicker.value = !showingPicker.value }) {
+                            val icon = if (showingPicker.value) {
+                                Icons.Outlined.Keyboard
                             } else {
-                                "Switch to Touch Input"
+                                Icons.Outlined.Schedule
                             }
-                        )
+                            Icon(
+                                icon,
+                                contentDescription = if (showingPicker.value) {
+                                    "Switch to Text Input"
+                                } else {
+                                    "Switch to Touch Input"
+                                }
+                            )
+                        }
                     }
                 }
             }
         ) {
-            if (showingPicker.value && configuration.screenHeightDp > 540) {
+            if (showingPicker.value && configuration.screenHeightDp > 400) {
                 TimePicker(state = state)
             } else {
                 TimeInput(state = state)
@@ -214,23 +228,27 @@
     title: String = "Select Time",
     onCancel: () -> Unit,
     onConfirm: () -> Unit,
-    toggle: @Composable RowScope.() -> Unit = {},
+    toggle: @Composable () -> Unit = {},
     content: @Composable () -> Unit,
 ) {
     Dialog(
         onDismissRequest = onCancel,
-        properties = DialogProperties(usePlatformDefaultWidth = false),
+        properties = DialogProperties(
+            usePlatformDefaultWidth = false
+        ),
     ) {
         Surface(
             shape = MaterialTheme.shapes.extraLarge,
             tonalElevation = 6.dp,
             modifier = Modifier
                 .width(IntrinsicSize.Min)
+                .height(IntrinsicSize.Min)
                 .background(
                     shape = MaterialTheme.shapes.extraLarge,
                     color = MaterialTheme.colorScheme.surface
                 ),
         ) {
+            toggle()
             Column(
                 modifier = Modifier.padding(24.dp),
                 horizontalAlignment = Alignment.CenterHorizontally
@@ -248,7 +266,6 @@
                         .height(40.dp)
                         .fillMaxWidth()
                 ) {
-                    toggle()
                     Spacer(modifier = Modifier.weight(1f))
                     TextButton(
                         onClick = onCancel
diff --git a/compose/material3/material3/src/androidAndroidTest/AndroidManifest.xml b/compose/material3/material3/src/androidAndroidTest/AndroidManifest.xml
index e650e97..cf97ceb 100644
--- a/compose/material3/material3/src/androidAndroidTest/AndroidManifest.xml
+++ b/compose/material3/material3/src/androidAndroidTest/AndroidManifest.xml
@@ -16,7 +16,8 @@
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
-    <application>
+    <application
+        android:supportsRtl="true">
         <activity
             android:name="androidx.compose.material3.MaterialWindowInsetsActivity"
             android:windowSoftInputMode="adjustResize"
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/AlertDialogScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/AlertDialogScreenshotTest.kt
index b773b27..ec36cd9 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/AlertDialogScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/AlertDialogScreenshotTest.kt
@@ -19,10 +19,13 @@
 import android.os.Build
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.isDialog
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
@@ -69,7 +72,7 @@
             )
         }
 
-        assertAppBarAgainstGolden(goldenIdentifier = "alertDialog_lightTheme")
+        assertAlertDialogAgainstGolden(goldenIdentifier = "alertDialog_lightTheme")
     }
 
     @Test
@@ -99,7 +102,7 @@
             )
         }
 
-        assertAppBarAgainstGolden(goldenIdentifier = "alertDialog_darkTheme")
+        assertAlertDialogAgainstGolden(goldenIdentifier = "alertDialog_darkTheme")
     }
 
     @Test
@@ -130,7 +133,7 @@
             )
         }
 
-        assertAppBarAgainstGolden(goldenIdentifier = "alertDialog_withIcon_lightTheme")
+        assertAlertDialogAgainstGolden(goldenIdentifier = "alertDialog_withIcon_lightTheme")
     }
 
     @Test
@@ -161,10 +164,41 @@
             )
         }
 
-        assertAppBarAgainstGolden(goldenIdentifier = "alertDialog_withIcon_darkTheme")
+        assertAlertDialogAgainstGolden(goldenIdentifier = "alertDialog_withIcon_darkTheme")
     }
 
-    private fun assertAppBarAgainstGolden(goldenIdentifier: String) {
+    @Test
+    fun alertDialog_rtl() {
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                AlertDialog(
+                    onDismissRequest = {},
+                    title = {
+                        Text(text = "Title")
+                    },
+                    text = {
+                        Text(
+                            "This area typically contains the supportive text " +
+                                "which presents the details regarding the Dialog's purpose."
+                        )
+                    },
+                    confirmButton = {
+                        TextButton(onClick = { /* doSomething() */ }) {
+                            Text("Confirm")
+                        }
+                    },
+                    dismissButton = {
+                        TextButton(onClick = { /* doSomething() */ }) {
+                            Text("Dismiss")
+                        }
+                    }
+                )
+            }
+        }
+        assertAlertDialogAgainstGolden(goldenIdentifier = "alertDialog_rtl")
+    }
+
+    private fun assertAlertDialogAgainstGolden(goldenIdentifier: String) {
         composeTestRule.onNode(isDialog())
             .captureToImage()
             .assertAgainstGolden(screenshotRule, goldenIdentifier)
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
index d3fcf7f..5dc6547 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/BottomSheetScaffoldTest.kt
@@ -28,29 +28,38 @@
 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.foundation.layout.requiredHeight
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.material3.tokens.SheetBottomTokens
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.shadow
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.asAndroidBitmap
+import androidx.compose.ui.graphics.compositeOver
 import androidx.compose.ui.layout.LayoutCoordinates
 import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.layout.positionInRoot
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsActions
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.StateRestorationTester
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onParent
 import androidx.compose.ui.test.performSemanticsAction
@@ -166,7 +175,10 @@
                             .requiredHeight(sheetHeight)
                             .testTag(sheetTag))
                 },
-                sheetDragHandle = { Box(Modifier.testTag(dragHandleTag).size(dragHandleSize)) },
+                sheetDragHandle = { Box(
+                    Modifier
+                        .testTag(dragHandleTag)
+                        .size(dragHandleSize)) },
                 sheetPeekHeight = peekHeight
             ) {
                 Text("Content")
@@ -200,7 +212,10 @@
                             .requiredHeight(sheetHeight)
                             .testTag(sheetTag))
                 },
-                sheetDragHandle = { Box(Modifier.testTag(dragHandleTag).size(dragHandleSize)) },
+                sheetDragHandle = { Box(
+                    Modifier
+                        .testTag(dragHandleTag)
+                        .size(dragHandleSize)) },
                 sheetPeekHeight = peekHeight
             ) {
                 Text("Content")
@@ -566,4 +581,95 @@
             rule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
         }
     }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun bottomSheetScaffold_slotsPositionedAppropriately() {
+        val topBarHeight = 56.dp
+        val expectedDragHandleVerticalPadding = 22.dp
+        val hostState = SnackbarHostState()
+        var snackbarSize: IntSize? = null
+        var snackbarPosition: Offset? = null
+        var density: Density? = null
+        var dragHandleContentDescription = ""
+        var dragHandleColor: Color = Color.Unspecified
+        var surface: Color = Color.Unspecified
+        val dragHandleShape: Shape = RectangleShape
+
+        rule.setContent {
+            dragHandleContentDescription = getString(Strings.BottomSheetDragHandleDescription)
+            dragHandleColor = SheetBottomTokens.DockedDragHandleColor.toColor()
+                .copy(SheetBottomTokens.DockedDragHandleOpacity)
+            surface = MaterialTheme.colorScheme.surface
+            density = LocalDensity.current
+            BottomSheetScaffold(
+                sheetContent = {
+                    Box(
+                        Modifier
+                            .height(sheetHeight)
+                            .fillMaxWidth()
+                            .testTag(sheetTag)
+                        )
+                    },
+                sheetPeekHeight = peekHeight,
+                sheetDragHandle = {
+                    BottomSheetDefaults.DragHandle(
+                        shape = dragHandleShape,
+                    )
+                },
+                topBar = {
+                    Box(modifier = Modifier
+                        .height(topBarHeight)
+                        .fillMaxWidth()
+                        .testTag("TopBar")
+                    )
+                },
+                snackbarHost = {
+                    SnackbarHost(
+                        hostState = hostState,
+                        modifier = Modifier
+                            .onGloballyPositioned {
+                                snackbarSize = it.size
+                                snackbarPosition = it.positionInRoot()
+                            },
+                    )
+                },
+            ) {
+                Box(Modifier.padding(it)) {
+                    Text("Scaffold Content", Modifier.testTag("ScaffoldContent"))
+                }
+            }
+        }
+        // Assert that the drag handle has vertical padding of 22.dp
+        rule
+            .onNodeWithContentDescription(dragHandleContentDescription)
+            .captureToImage()
+            .assertShape(
+                density = rule.density,
+                horizontalPadding = 0.dp,
+                verticalPadding = 22.dp,
+                backgroundColor = dragHandleColor.compositeOver(surface),
+                shapeColor = dragHandleColor.compositeOver(surface),
+                shape = dragHandleShape
+            )
+        // Assert sheet content is positioned at the sheet peek height + drag handle height + 22.dp
+        // top and bottom padding.
+        rule.onNodeWithTag(sheetTag).assertTopPositionInRootIsEqualTo(
+            rule.rootHeight() - peekHeight +
+                (expectedDragHandleVerticalPadding * 2) + SheetBottomTokens.DockedDragHandleHeight
+        )
+        // Assert TopBar is placed at the top of the app.
+        rule.onNodeWithTag("TopBar").assertTopPositionInRootIsEqualTo(0.dp)
+        // Assert TopBar is sized appropriately.
+        rule.onNodeWithTag("TopBar").assertHeightIsEqualTo(topBarHeight)
+        rule.onNodeWithTag("TopBar").assertWidthIsEqualTo(rule.rootWidth())
+        // Assert scaffold content consumes TopBar height for padding.
+        rule.onNodeWithTag("ScaffoldContent").assertTopPositionInRootIsEqualTo(topBarHeight)
+
+        // Assert snackbar is placed above bottom sheet when partially expanded.
+        val snackbarBottomOffset = snackbarPosition!!.y + snackbarSize!!.height.toFloat()
+        val expectedSnackbarBottomOffset =
+            with(density!!) { rule.rootHeight().toPx() - peekHeight.toPx() - snackbarSize!!.height }
+        assertThat(snackbarBottomOffset).isWithin(1f).of(expectedSnackbarBottomOffset)
+    }
 }
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
index 8b38b9b..086476e 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangePickerTest.kt
@@ -110,18 +110,22 @@
         }
     }
 
-    @Test(expected = IllegalArgumentException::class)
     fun state_initWithEqualStartAndEndDates() {
+        lateinit var dateRangePickerState: DateRangePickerState
         rule.setMaterialContent(lightColorScheme()) {
-            // Expecting this to throw an exception when the start and end dates are the same.
-            rememberDateRangePickerState(
+            dateRangePickerState = rememberDateRangePickerState(
+                // 04/12/2022
+                initialSelectedStartDateMillis = 1649721600000L,
                 // 04/12/2022 + a few added milliseconds to ensure that the state is initialized
                 // with a canonical date.
-                initialSelectedStartDateMillis = 1649721600000L + 1000,
-                // 04/12/2022
-                initialSelectedEndDateMillis = 1649721600000L
+                initialSelectedEndDateMillis = 1649721600000L + 1000
             )
         }
+        with(dateRangePickerState) {
+            // Start and end are expected to be equal.
+            assertThat(selectedStartDateMillis).isEqualTo(1649721600000L)
+            assertThat(selectedEndDateMillis).isEqualTo(1649721600000L)
+        }
     }
 
     @Test(expected = IllegalArgumentException::class)
@@ -274,6 +278,61 @@
         }
     }
 
+    /**
+     * Tests that clicking the same date twice creates a single-day range, and that clicking it
+     * a third time resets the end date.
+     */
+    @Test
+    fun dateSelection_sameDateForStartAndEnd() {
+        lateinit var dateRangePickerState: DateRangePickerState
+        rule.setMaterialContent(lightColorScheme()) {
+            val monthInUtcMillis = dayInUtcMilliseconds(year = 2019, month = 3, dayOfMonth = 1)
+            dateRangePickerState = rememberDateRangePickerState(
+                initialDisplayedMonthMillis = monthInUtcMillis
+            )
+            DateRangePicker(state = dateRangePickerState)
+        }
+
+        val node = rule.onAllNodes(hasText("15", substring = true) and hasClickAction()).onFirst()
+        // First date selection: Select the 15th day of the first displayed month in the list.
+        node.performClick()
+        // Second date selection - click the same node.
+        node.performClick()
+
+        // Assert the state holds a valid start and end dates for the same date.
+        rule.runOnIdle {
+            assertThat(dateRangePickerState.selectedStartDateMillis).isEqualTo(
+                dayInUtcMilliseconds(
+                    year = 2019,
+                    month = 3,
+                    dayOfMonth = 15
+                )
+            )
+            assertThat(dateRangePickerState.selectedEndDateMillis).isEqualTo(
+                dayInUtcMilliseconds(
+                    year = 2019,
+                    month = 3,
+                    dayOfMonth = 15
+                )
+            )
+        }
+
+        // Click the node again to reset the end date.
+        node.performClick()
+
+        // Assert the state now holds just a start date.
+        rule.runOnIdle {
+            assertThat(dateRangePickerState.selectedStartDateMillis).isEqualTo(
+                dayInUtcMilliseconds(
+                    year = 2019,
+                    month = 3,
+                    dayOfMonth = 15
+                )
+            )
+            assertThat(dateRangePickerState.selectedEndDateMillis).isNull()
+        }
+    }
+
     @Test
     fun state_resetSelections() {
         lateinit var defaultStartSelectionHeadline: String
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
index ae46835..fa4a4be 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
@@ -76,6 +76,7 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.MediumTest
@@ -86,7 +87,6 @@
 import com.nhaarman.mockitokotlin2.eq
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.verify
-import kotlin.math.max
 import kotlin.math.roundToInt
 import org.junit.Rule
 import org.junit.Test
@@ -227,39 +227,58 @@
 
     @Test
     fun testOutlinedTextField_labelPosition_initial_singleLine() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    singleLine = true,
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                singleLine = true,
+                label = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is centered, plus additional padding allowance on top
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                ((ExpectedMinimumTextFieldHeight - MinTextLineHeight) / 2 +
+                    OutlinedTextFieldTopPadding).toPx()
             )
-            // label is centered in 56.dp default container, plus additional 8.dp padding on top
-            val minimumHeight = ExpectedMinimumTextFieldHeight.roundToPx()
-            assertThat(labelPosition.value?.y).isEqualTo(
-                ((minimumHeight - labelSize.value!!.height) / 2f).roundToInt() + 8.dp.roundToPx()
+        }
+    }
+
+    @Test
+    fun testOutlinedTextField_labelPosition_initial_withDefaultHeight() {
+        val labelPosition = Ref<Offset>()
+        rule.setMaterialContent(lightColorScheme()) {
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
+        }
+
+        rule.runOnIdleWithDensity {
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + default padding + label padding allowance
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                (ExpectedPadding + OutlinedTextFieldTopPadding).toPx()
             )
         }
     }
@@ -268,22 +287,22 @@
     fun testOutlinedTextField_labelPosition_initial_withMultiLineLabel() {
         val textFieldWidth = 200.dp
         val labelSize = Ref<IntSize>()
+        val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    modifier = Modifier.requiredWidth(textFieldWidth),
-                    label = {
-                        Text(
-                            text = "long long long long long long long long long long long long",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                modifier = Modifier.requiredWidth(textFieldWidth),
+                label = {
+                    Text(
+                        text = "long long long long long long long long long long long long",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelSize.value = it.size
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
@@ -292,50 +311,20 @@
             assertThat(labelSize.value?.height).isGreaterThan(0)
             assertThat(labelSize.value?.width)
                 .isEqualTo(textFieldWidth.roundToPx() - 2 * ExpectedPadding.roundToPx())
-        }
-    }
 
-    @Test
-    fun testOutlinedTextField_labelPosition_initial_withDefaultHeight() {
-        val labelSize = Ref<IntSize>()
-        val labelPosition = Ref<Offset>()
-        rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
-        }
-
-        rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            // label is aligned to the top with padding, plus additional 8.dp padding on top
-            assertThat(labelPosition.value?.y).isEqualTo(
-                TextFieldPadding.roundToPx() + 8.dp.roundToPx()
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + default padding + label padding allowance
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                (ExpectedPadding + OutlinedTextFieldTopPadding).toPx()
             )
         }
     }
 
     @Test
     fun testOutlinedTextField_labelPosition_whenFocused() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
+        val labelSize = MinFocusedLabelLineHeight
 
         rule.setMaterialContent(lightColorScheme()) {
             OutlinedTextField(
@@ -343,11 +332,10 @@
                 value = "",
                 onValueChange = {},
                 label = {
-                    Text(
-                        text = "label",
-                        modifier = Modifier.onGloballyPositioned {
+                    Box(Modifier
+                        .size(MinFocusedLabelLineHeight)
+                        .onGloballyPositioned {
                             labelPosition.value = it.positionInRoot()
-                            labelSize.value = it.size
                         }
                     )
                 }
@@ -358,15 +346,10 @@
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            // label position
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                getLabelPosition(labelSize.roundToPx()).toFloat()
             )
-            assertThat(labelPosition.value?.y).isEqualTo(getLabelPosition(labelSize))
         }
     }
 
@@ -374,22 +357,22 @@
     fun testOutlinedTextField_labelPosition_whenFocused_withMultiLineLabel() {
         val textFieldWidth = 200.dp
         val labelSize = Ref<IntSize>()
+        val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    modifier = Modifier.testTag(TextFieldTag).requiredWidth(textFieldWidth),
-                    label = {
-                        Text(
-                            text = "long long long long long long long long long long long long",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                modifier = Modifier.testTag(TextFieldTag).requiredWidth(textFieldWidth),
+                label = {
+                    Text(
+                        text = "long long long long long long long long long long long long",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelSize.value = it.size
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         // click to focus
@@ -399,8 +382,15 @@
             // label size
             assertThat(labelSize.value).isNotNull()
             assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width)
-                .isEqualTo(textFieldWidth.roundToPx() - 2 * ExpectedPadding.roundToPx())
+            assertThat(labelSize.value?.width!!.toFloat()).isWithin(1f).of(
+                (textFieldWidth - ExpectedPadding * 2).toPx()
+            )
+
+            // label position
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                getLabelPosition(labelSize.value!!.height).toFloat()
+            )
         }
     }
 
@@ -455,18 +445,17 @@
 
     @Test
     fun testOutlinedTextField_labelPosition_whenInput() {
-        val labelSize = Ref<IntSize>()
+        val labelSize = MinFocusedLabelLineHeight
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
             OutlinedTextField(
                 value = "input",
                 onValueChange = {},
                 label = {
-                    Text(
-                        text = "label",
-                        modifier = Modifier.onGloballyPositioned {
+                    Box(Modifier
+                        .size(labelSize)
+                        .onGloballyPositioned {
                             labelPosition.value = it.positionInRoot()
-                            labelSize.value = it.size
                         }
                     )
                 }
@@ -474,15 +463,11 @@
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
             // label position
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                getLabelPosition(labelSize.roundToPx()).toFloat()
             )
-            assertThat(labelPosition.value?.y).isEqualTo(getLabelPosition(labelSize))
         }
     }
 
@@ -513,7 +498,7 @@
 
     @Test
     fun testOutlinedTextField_placeholderPosition_withLabel() {
-        val placeholderSize = Ref<IntSize>()
+        val placeholderSize = MinTextLineHeight
         val placeholderPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
             Box {
@@ -521,13 +506,12 @@
                     modifier = Modifier.testTag(TextFieldTag),
                     value = "",
                     onValueChange = {},
-                    label = { Text("label") },
+                    label = { Box(Modifier.size(MinFocusedLabelLineHeight)) },
                     placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(placeholderSize)
+                            .onGloballyPositioned {
                                 placeholderPosition.value = it.positionInRoot()
-                                placeholderSize.value = it.size
                             }
                         )
                     }
@@ -538,57 +522,38 @@
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(placeholderSize.value).isNotNull()
-            assertThat(placeholderSize.value?.height).isGreaterThan(0)
-            assertThat(placeholderSize.value?.width).isGreaterThan(0)
-            // position
-            assertThat(placeholderPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            // placeholder is aligned to the top with padding, plus additional 8.dp padding on top
-            assertThat(placeholderPosition.value?.y).isEqualTo(
-                TextFieldPadding.roundToPx() + 8.dp.roundToPx()
+            assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(
+                (ExpectedPadding + OutlinedTextFieldTopPadding).toPx()
             )
         }
     }
 
     @Test
     fun testOutlinedTextField_placeholderPosition_whenNoLabel() {
-        val placeholderSize = Ref<IntSize>()
+        val placeholderSize = MinTextLineHeight
         val placeholderPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    modifier = Modifier.testTag(TextFieldTag),
-                    value = "",
-                    onValueChange = {},
-                    placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.onGloballyPositioned {
-                                placeholderPosition.value = it.positionInRoot()
-                                placeholderSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            OutlinedTextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                placeholder = {
+                    Box(Modifier
+                        .size(placeholderSize)
+                        .onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
         // click to focus
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(placeholderSize.value).isNotNull()
-            assertThat(placeholderSize.value?.height).isGreaterThan(0)
-            assertThat(placeholderSize.value?.width).isGreaterThan(0)
-            // position
-            assertThat(placeholderPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            // placeholder is placed with fixed padding
-            assertThat(placeholderPosition.value?.y).isEqualTo(TextFieldPadding.roundToPx())
+            assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
@@ -597,22 +562,20 @@
         val placeholderSize = Ref<IntSize>()
         val placeholderPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Column {
-                OutlinedTextField(
-                    modifier = Modifier.testTag(TextFieldTag),
-                    value = "input",
-                    onValueChange = {},
-                    placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.onGloballyPositioned {
-                                placeholderPosition.value = it.positionInRoot()
-                                placeholderSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            OutlinedTextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "input",
+                onValueChange = {},
+                placeholder = {
+                    Text(
+                        text = "placeholder",
+                        modifier = Modifier.onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                            placeholderSize.value = it.size
+                        }
+                    )
+                }
+            )
         }
 
         // click to focus
@@ -644,6 +607,61 @@
     }
 
     @Test
+    fun testOutlinedTextField_labelAndPlaceholderPosition_whenSmallerThanMinimumHeight() {
+        val labelSize = 10.dp
+        val labelPosition = Ref<Offset>()
+        val placeholderSize = 20.dp
+        val placeholderPosition = Ref<Offset>()
+        rule.setMaterialContent(lightColorScheme()) {
+            OutlinedTextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(labelSize)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                placeholder = {
+                    Box(Modifier
+                        .size(placeholderSize)
+                        .onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
+        }
+
+        // click to focus
+        rule.onNodeWithTag(TextFieldTag).performClick()
+
+        rule.runOnIdleWithDensity {
+            // size
+            assertThat(labelSize).isLessThan(MinFocusedLabelLineHeight)
+            assertThat(placeholderSize).isLessThan(MinTextLineHeight)
+
+            // label position
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                getLabelPosition(labelSize.roundToPx()).toFloat()
+            )
+
+            // placeholder position
+            assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // placeholder y position is top + default padding + label padding allowance, then
+            // centered within allocated space
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(
+                (ExpectedPadding + OutlinedTextFieldTopPadding +
+                    (MinTextLineHeight - placeholderSize) / 2).toPx()
+            )
+        }
+    }
+
+    @Test
     fun testOutlinedTextField_trailingAndLeading_sizeAndPosition_defaultIcon() {
         val textFieldWidth = 300.dp
         val leadingPosition = Ref<Offset>()
@@ -841,11 +859,10 @@
     @Test
     fun testOutlinedTextField_prefixAndSuffixPosition_withLabel() {
         val textFieldWidth = 300.dp
-        val textFieldHeight = 60.dp
-        val labelSize = Ref<IntSize>()
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -853,29 +870,21 @@
                 OutlinedTextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(textFieldWidth, textFieldHeight),
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelSize.value = it.size
-                            }
-                        )
-                    },
+                    modifier = Modifier.width(textFieldWidth),
+                    label = { Box(Modifier.size(MinFocusedLabelLineHeight)) },
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     }
@@ -888,14 +897,16 @@
                 // prefix
                 assertThat(prefixPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
                 assertThat(prefixPosition.value?.y).isWithin(1f).of(
-                    (ExpectedPadding + 8.dp).toPx())
+                    (ExpectedPadding + OutlinedTextFieldTopPadding).toPx()
+                )
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (textFieldWidth - ExpectedPadding - suffixSize.value!!.width.toDp()).toPx()
+                    (textFieldWidth - ExpectedPadding - suffixSize).toPx()
                 )
                 assertThat(suffixPosition.value?.y).isWithin(1f).of(
-                    (ExpectedPadding + 8.dp).toPx())
+                    (ExpectedPadding + OutlinedTextFieldTopPadding).toPx()
+                )
             }
         }
     }
@@ -903,10 +914,10 @@
     @Test
     fun testOutlinedTextField_prefixAndSuffixPosition_whenNoLabel() {
         val textFieldWidth = 300.dp
-        val textFieldHeight = 60.dp
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -914,21 +925,20 @@
                 OutlinedTextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(textFieldWidth, textFieldHeight),
+                    modifier = Modifier.width(textFieldWidth),
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     }
@@ -944,7 +954,7 @@
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (textFieldWidth - ExpectedPadding - suffixSize.value!!.width.toDp()).toPx()
+                    (textFieldWidth - ExpectedPadding - suffixSize).toPx()
                 )
                 assertThat(suffixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
             }
@@ -954,10 +964,10 @@
     @Test
     fun testOutlinedTextField_prefixAndSuffixPosition_withIcons() {
         val textFieldWidth = 300.dp
-        val textFieldHeight = 60.dp
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -965,21 +975,20 @@
                 OutlinedTextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(textFieldWidth, textFieldHeight),
+                    modifier = Modifier.width(textFieldWidth),
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     },
@@ -995,13 +1004,13 @@
 
                 // prefix
                 assertThat(prefixPosition.value?.x).isWithin(1f).of(
-                    (ExpectedPadding + IconPadding + iconSize).toPx())
+                    (ExpectedPadding + IconPadding + iconSize).toPx()
+                )
                 assertThat(prefixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (textFieldWidth - IconPadding - iconSize - ExpectedPadding -
-                        suffixSize.value!!.width.toDp()).toPx()
+                    (textFieldWidth - IconPadding - iconSize - ExpectedPadding - suffixSize).toPx()
                 )
                 assertThat(suffixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
             }
@@ -1012,28 +1021,26 @@
     fun testOutlinedTextField_labelPositionX_initial_withTrailingAndLeading() {
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                            }
-                        )
-                    },
-                    trailingIcon = { Icon(Icons.Default.Favorite, null) },
-                    leadingIcon = { Icon(Icons.Default.Favorite, null) }
-                )
-            }
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Text(
+                        text = "label",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                trailingIcon = { Icon(Icons.Default.Favorite, null) },
+                leadingIcon = { Icon(Icons.Default.Favorite, null) }
+            )
         }
 
         rule.runOnIdleWithDensity {
             val iconSize = 24.dp // default icon size
-            assertThat(labelPosition.value?.x).isEqualTo(
-                (ExpectedPadding + IconPadding + iconSize).roundToPx().toFloat()
+            assertThat(labelPosition.value?.x).isWithin(1f).of(
+                (ExpectedPadding + IconPadding + iconSize).toPx()
             )
         }
     }
@@ -1042,28 +1049,24 @@
     fun testOutlinedTextField_labelPositionX_initial_withNullTrailingAndLeading() {
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                OutlinedTextField(
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                            }
-                        )
-                    },
-                    trailingIcon = null,
-                    leadingIcon = null
-                )
-            }
+            OutlinedTextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Text(
+                        text = "label",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                trailingIcon = null,
+                leadingIcon = null
+            )
         }
 
         rule.runOnIdleWithDensity {
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
@@ -1106,21 +1109,16 @@
 
     @Test
     fun testOutlinedTextField_supportingText_position() {
-        val tfSize = Ref<IntSize>()
-        val supportingSize = Ref<IntSize>()
         val supportingPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
             OutlinedTextField(
                 value = "",
                 onValueChange = {},
-                modifier = Modifier.onGloballyPositioned {
-                    tfSize.value = it.size
-                },
+                textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                 supportingText = {
-                    Text(
-                        text = "Supporting",
-                        modifier = Modifier.onGloballyPositioned {
-                            supportingSize.value = it.size
+                    Box(Modifier
+                        .size(MinSupportingTextLineHeight)
+                        .onGloballyPositioned {
                             supportingPosition.value = it.positionInRoot()
                         }
                     )
@@ -1129,11 +1127,9 @@
         }
 
         rule.runOnIdleWithDensity {
-            assertThat(supportingPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(supportingPosition.value?.y).isEqualTo(
-                tfSize.value!!.height - supportingSize.value!!.height
+            assertThat(supportingPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(supportingPosition.value?.y).isWithin(1f).of(
+                (ExpectedMinimumTextFieldHeight + SupportingTopPadding).toPx()
             )
         }
     }
@@ -1277,7 +1273,7 @@
     }
 
     @Test
-    fun testErrorSemantics_defaultMessage() {
+    fun testOutlinedTextField_errorSemantics_defaultMessage() {
         lateinit var errorMessage: String
         rule.setMaterialContent(lightColorScheme()) {
             OutlinedTextField(
@@ -1296,7 +1292,7 @@
     }
 
     @Test
-    fun testErrorSemantics_messageOverridable() {
+    fun testOutlinedTextField_errorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
         rule.setMaterialContent(lightColorScheme()) {
             val isError = remember { mutableStateOf(true) }
@@ -1602,7 +1598,7 @@
                     OutlinedTextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") }
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                     )
                     Divider(Modifier.fillMaxHeight())
                 }
@@ -1626,7 +1622,7 @@
                     OutlinedTextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") },
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                         leadingIcon = { Icon(Icons.Default.Favorite, null) }
                     )
                     Divider(Modifier.fillMaxHeight())
@@ -1651,7 +1647,7 @@
                     OutlinedTextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") },
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                         trailingIcon = { Icon(Icons.Default.Favorite, null) }
                     )
                     Divider(Modifier.fillMaxHeight())
@@ -1697,11 +1693,11 @@
         }
     }
 
-    private fun getLabelPosition(labelSize: Ref<IntSize>): Int {
-        val labelHalfHeight = labelSize.value!!.height / 2
+    private fun getLabelPosition(labelHeight: Int): Int {
+        val labelHalfHeight = labelHeight / 2
         val paddingTop = with(rule.density) { OutlinedTextFieldTopPadding.toPx() }
-        // vertical position is the default padding - half height
-        // in case negative position, fix to 0
-        return max(paddingTop - labelHalfHeight, 0f).roundToInt()
+        // Vertical position is the default padding - half height.
+        // This can be negative, meaning default padding is not enough for the focused label.
+        return (paddingTop - labelHalfHeight).roundToInt()
     }
 }
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SearchBarTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SearchBarTest.kt
index 8b99b74..54fcb26 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SearchBarTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/SearchBarTest.kt
@@ -33,6 +33,8 @@
 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.assertIsNotFocused
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
@@ -60,7 +62,7 @@
     private val BackTestTag = "Back"
 
     @Test
-    fun searchBar_becomesActiveOnClick_andInactiveOnBack() {
+    fun searchBar_becomesActiveAndFocusedOnClick_andInactiveAndUnfocusedOnBack() {
         rule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.fillMaxSize()) {
                 val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
@@ -88,9 +90,12 @@
 
         rule.onNodeWithTag(SearchBarTestTag).performClick()
         rule.onNodeWithTag(BackTestTag).assertIsDisplayed()
+        // onNodeWithText instead of onNodeWithTag to access the underlying text field
+        rule.onNodeWithText("Query").assertIsFocused()
 
         rule.onNodeWithTag(BackTestTag).performClick()
         rule.onNodeWithTag(BackTestTag).assertDoesNotExist()
+        rule.onNodeWithText("Query").assertIsNotFocused()
     }
 
     @Test
@@ -204,7 +209,7 @@
     }
 
     @Test
-    fun dockedSearchBar_becomesActiveOnClick_andInactiveOnBack() {
+    fun dockedSearchBar_becomesActiveAndFocusedOnClick_andInactiveAndUnfocusedOnBack() {
         rule.setMaterialContent(lightColorScheme()) {
             Column(Modifier.fillMaxSize()) {
                 val dispatcher = LocalOnBackPressedDispatcherOwner.current!!.onBackPressedDispatcher
@@ -232,9 +237,12 @@
 
         rule.onNodeWithTag(SearchBarTestTag).performClick()
         rule.onNodeWithTag(BackTestTag).assertIsDisplayed()
+        // onNodeWithText instead of onNodeWithTag to access the underlying text field
+        rule.onNodeWithText("Query").assertIsFocused()
 
         rule.onNodeWithTag(BackTestTag).performClick()
         rule.onNodeWithTag(BackTestTag).assertDoesNotExist()
+        rule.onNodeWithText("Query").assertIsNotFocused()
     }
 
     @Test
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
index 447e330..4b994e6 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
@@ -31,7 +31,6 @@
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
@@ -126,7 +125,7 @@
     val rule = createComposeRule()
 
     @Test
-    fun testTextField_minimumHeight() {
+    fun testTextField_setSmallHeight() {
         rule.setMaterialContentForSizeAssertions {
             TextField(
                 value = "input",
@@ -150,6 +149,18 @@
     }
 
     @Test
+    fun testTextField_defaultHeight() {
+        rule.setMaterialContentForSizeAssertions {
+            TextField(
+                value = "",
+                onValueChange = {},
+                textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
+            )
+        }
+            .assertHeightIsEqualTo(ExpectedDefaultTextFieldHeight)
+    }
+
+    @Test
     fun testTextField_defaultWidth() {
         rule.setMaterialContentForSizeAssertions {
             TextField(
@@ -322,293 +333,207 @@
 
     @Test
     fun testTextField_labelPosition_initial_singleLine() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "",
-                    onValueChange = {},
-                    singleLine = true,
-                    label = {
-                        Text(
-                            text = "label",
-                            fontSize = 10.sp,
-                            modifier = Modifier
-                                .onGloballyPositioned {
-                                    labelPosition.value = it.positionInRoot()
-                                    labelSize.value = it.size
-                                }
-                        )
-                    },
-                    modifier = Modifier.height(56.dp)
-                )
-            }
+            TextField(
+                value = "",
+                onValueChange = {},
+                singleLine = true,
+                label = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            // centered position
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(labelPosition.value?.y).isEqualTo(
-                ((ExpectedDefaultTextFieldHeight.roundToPx() - labelSize.value!!.height) / 2f)
-                    .roundToInt().toFloat()
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is centered
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                (ExpectedDefaultTextFieldHeight - MinTextLineHeight).toPx() / 2f
             )
         }
     }
 
     @Test
     fun testTextField_labelPosition_initial_withDefaultHeight() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            fontSize = 10.sp,
-                            modifier = Modifier
-                                .onGloballyPositioned {
-                                    labelPosition.value = it.positionInRoot()
-                                    labelSize.value = it.size
-                                }
-                        )
-                    },
-                    modifier = Modifier.height(56.dp)
-                )
-            }
+            TextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            // centered position
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(labelPosition.value?.y).isEqualTo(
-                ExpectedPadding.roundToPx()
-            )
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + padding
+            assertThat(labelPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
     @Test
     fun testTextField_labelPosition_initial_withCustomHeight() {
         val height = 80.dp
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "",
-                    onValueChange = {},
-                    modifier = Modifier.height(height),
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            TextField(
+                value = "",
+                onValueChange = {},
+                modifier = Modifier.height(height),
+                label = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(labelPosition.value?.y).isEqualTo(
-                ExpectedPadding.roundToPx()
-            )
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + padding
+            assertThat(labelPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
     @Test
     fun testTextField_labelPosition_whenFocused() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    modifier = Modifier.testTag(TextFieldTag),
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(MinFocusedLabelLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         // click to focus
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(labelPosition.value?.y).isEqualTo(
-                TextFieldWithLabelVerticalPadding.roundToPx().toFloat()
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + (different) padding
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                TextFieldWithLabelVerticalPadding.toPx()
             )
         }
     }
 
     @Test
     fun testTextField_labelPosition_whenInput() {
-        val labelSize = Ref<IntSize>()
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "input",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                                labelSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            TextField(
+                value = "input",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(MinFocusedLabelLineHeight)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(labelSize.value?.height).isGreaterThan(0)
-            assertThat(labelSize.value?.width).isGreaterThan(0)
-
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(labelPosition.value?.y).isEqualTo(
-                TextFieldWithLabelVerticalPadding.roundToPx().toFloat()
+            // x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + (different) padding
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                TextFieldWithLabelVerticalPadding.toPx()
             )
         }
     }
 
     @Test
     fun testTextField_placeholderPosition_withLabel() {
-        val labelSize = Ref<IntSize>()
-        val placeholderSize = Ref<IntSize>()
         val placeholderPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    modifier = Modifier
-                        .height(60.dp)
-                        .testTag(TextFieldTag),
-                    value = "",
-                    onValueChange = {},
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelSize.value = it.size
-                            }
-                        )
-                    },
-                    placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.onGloballyPositioned {
-                                placeholderPosition.value = it.positionInRoot()
-                                placeholderSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                label = { Box(Modifier.size(MinFocusedLabelLineHeight)) },
+                placeholder = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
+
         // click to focus
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(labelSize.value).isNotNull()
-            assertThat(placeholderSize.value).isNotNull()
-            assertThat(placeholderSize.value?.height).isGreaterThan(0)
-            assertThat(placeholderSize.value?.width).isGreaterThan(0)
-            // placeholder's position
+            // x position is start + padding
             assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
-            assertThat(placeholderPosition.value?.y).isWithin(1f)
-                .of(
-                    TextFieldWithLabelVerticalPadding.toPx() +
-                        labelSize.value!!.height.toFloat()
-                )
+            // y position is top + padding + label height
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(
+                (TextFieldWithLabelVerticalPadding + MinFocusedLabelLineHeight).toPx()
+            )
         }
     }
 
     @Test
     fun testTextField_placeholderPosition_whenNoLabel() {
-        val placeholderSize = Ref<IntSize>()
         val placeholderPosition = Ref<Offset>()
-        val height = 60.dp
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    modifier = Modifier.height(height).testTag(TextFieldTag),
-                    value = "",
-                    onValueChange = {},
-                    placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.requiredHeight(20.dp)
-                                .onGloballyPositioned {
-                                    placeholderPosition.value = it.positionInRoot()
-                                    placeholderSize.value = it.size
-                                }
-                        )
-                    }
-                )
-            }
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                placeholder = {
+                    Box(Modifier
+                        .size(MinTextLineHeight)
+                        .onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
         }
+
         // click to focus
         rule.onNodeWithTag(TextFieldTag).performClick()
 
         rule.runOnIdleWithDensity {
-            // size
-            assertThat(placeholderSize.value).isNotNull()
-            assertThat(placeholderSize.value?.height).isEqualTo(20.dp.roundToPx())
-            assertThat(placeholderSize.value?.width).isGreaterThan(0)
-            // centered position
-            assertThat(placeholderPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(placeholderPosition.value?.y).isEqualTo(
-                TextFieldPadding.roundToPx()
-            )
+            // x position is start + padding
+            assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // y position is top + padding
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
@@ -617,23 +542,20 @@
         val placeholderSize = Ref<IntSize>()
         val placeholderPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Column {
-                TextField(
-                    modifier = Modifier.testTag(TextFieldTag),
-                    value = "input",
-                    onValueChange = {},
-
-                    placeholder = {
-                        Text(
-                            text = "placeholder",
-                            modifier = Modifier.onGloballyPositioned {
-                                placeholderPosition.value = it.positionInRoot()
-                                placeholderSize.value = it.size
-                            }
-                        )
-                    }
-                )
-            }
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "input",
+                onValueChange = {},
+                placeholder = {
+                    Text(
+                        text = "placeholder",
+                        modifier = Modifier.onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                            placeholderSize.value = it.size
+                        }
+                    )
+                }
+            )
         }
 
         // click to focus
@@ -665,6 +587,63 @@
     }
 
     @Test
+    fun testTextField_labelAndPlaceholderPosition_whenSmallerThanMinimumHeight() {
+        val labelSize = 10.dp
+        val labelPosition = Ref<Offset>()
+        val placeholderSize = 20.dp
+        val placeholderPosition = Ref<Offset>()
+        rule.setMaterialContent(lightColorScheme()) {
+            TextField(
+                modifier = Modifier.testTag(TextFieldTag),
+                value = "",
+                onValueChange = {},
+                label = {
+                    Box(Modifier
+                        .size(labelSize)
+                        .onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                placeholder = {
+                    Box(Modifier
+                        .size(placeholderSize)
+                        .onGloballyPositioned {
+                            placeholderPosition.value = it.positionInRoot()
+                        }
+                    )
+                }
+            )
+        }
+
+        // click to focus
+        rule.onNodeWithTag(TextFieldTag).performClick()
+
+        rule.runOnIdleWithDensity {
+            // size
+            assertThat(labelSize).isLessThan(MinFocusedLabelLineHeight)
+            assertThat(placeholderSize).isLessThan(MinTextLineHeight)
+
+            // label x position is start + padding
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // label y position is top + padding, then centered within allocated space
+            assertThat(labelPosition.value?.y).isWithin(1f).of(
+                (TextFieldWithLabelVerticalPadding + (MinFocusedLabelLineHeight - labelSize) / 2)
+                    .toPx()
+            )
+
+            // placeholder x position is start + padding
+            assertThat(placeholderPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            // placeholder y position is top + padding + label height, then centered within
+            // allocated space
+            assertThat(placeholderPosition.value?.y).isWithin(1f).of(
+                (TextFieldWithLabelVerticalPadding + MinFocusedLabelLineHeight +
+                    (MinTextLineHeight - placeholderSize) / 2).toPx()
+            )
+        }
+    }
+
+    @Test
     fun testTextField_trailingAndLeading_sizeAndPosition_defaultIcon() {
         val textFieldHeight = 60.dp
         val leadingPosition = Ref<Offset>()
@@ -868,11 +847,10 @@
 
     @Test
     fun testTextField_prefixAndSuffixPosition_withLabel() {
-        val textFieldHeight = 60.dp
-        val labelSize = Ref<IntSize>()
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -880,29 +858,21 @@
                 TextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(TextFieldWidth, textFieldHeight),
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelSize.value = it.size
-                            }
-                        )
-                    },
+                    modifier = Modifier.width(TextFieldWidth),
+                    label = { Box(Modifier.size(MinFocusedLabelLineHeight)) },
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     }
@@ -914,33 +884,27 @@
             with(density) {
                 // prefix
                 assertThat(prefixPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
-                assertThat(prefixPosition.value?.y)
-                    .isWithin(1f)
-                    .of(
-                        TextFieldWithLabelVerticalPadding.toPx() +
-                            labelSize.value!!.height.toFloat()
-                    )
+                assertThat(prefixPosition.value?.y).isWithin(1f).of(
+                    (TextFieldWithLabelVerticalPadding + MinFocusedLabelLineHeight).toPx()
+                )
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (TextFieldWidth - ExpectedPadding - suffixSize.value!!.width.toDp()).toPx()
+                    (TextFieldWidth - ExpectedPadding - suffixSize).toPx()
                 )
-                assertThat(suffixPosition.value?.y)
-                    .isWithin(1f)
-                    .of(
-                        TextFieldWithLabelVerticalPadding.toPx() +
-                            labelSize.value!!.height.toFloat()
-                    )
+                assertThat(suffixPosition.value?.y).isWithin(1f).of(
+                    (TextFieldWithLabelVerticalPadding + MinFocusedLabelLineHeight).toPx()
+                )
             }
         }
     }
 
     @Test
     fun testTextField_prefixAndSuffixPosition_whenNoLabel() {
-        val textFieldHeight = 60.dp
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -948,21 +912,20 @@
                 TextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(TextFieldWidth, textFieldHeight),
+                    modifier = Modifier.width(TextFieldWidth),
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     }
@@ -978,7 +941,7 @@
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (TextFieldWidth - ExpectedPadding - suffixSize.value!!.width.toDp()).toPx()
+                    (TextFieldWidth - ExpectedPadding - suffixSize).toPx()
                 )
                 assertThat(suffixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
             }
@@ -987,10 +950,10 @@
 
     @Test
     fun testTextField_prefixAndSuffixPosition_withIcons() {
-        val textFieldHeight = 60.dp
         val prefixPosition = Ref<Offset>()
+        val prefixSize = MinTextLineHeight
         val suffixPosition = Ref<Offset>()
-        val suffixSize = Ref<IntSize>()
+        val suffixSize = MinTextLineHeight
         val density = Density(2f)
 
         rule.setMaterialContent(lightColorScheme()) {
@@ -998,21 +961,20 @@
                 TextField(
                     value = "text",
                     onValueChange = {},
-                    modifier = Modifier.size(TextFieldWidth, textFieldHeight),
+                    modifier = Modifier.width(TextFieldWidth),
                     prefix = {
-                        Text(
-                            text = "P",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(prefixSize)
+                            .onGloballyPositioned {
                                 prefixPosition.value = it.positionInRoot()
                             }
                         )
                     },
                     suffix = {
-                        Text(
-                            text = "S",
-                            modifier = Modifier.onGloballyPositioned {
+                        Box(Modifier
+                            .size(suffixSize)
+                            .onGloballyPositioned {
                                 suffixPosition.value = it.positionInRoot()
-                                suffixSize.value = it.size
                             }
                         )
                     },
@@ -1028,13 +990,13 @@
 
                 // prefix
                 assertThat(prefixPosition.value?.x).isWithin(1f).of(
-                    (ExpectedPadding + IconPadding + iconSize).toPx())
+                    (ExpectedPadding + IconPadding + iconSize).toPx()
+                )
                 assertThat(prefixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
 
                 // suffix
                 assertThat(suffixPosition.value?.x).isWithin(1f).of(
-                    (TextFieldWidth - IconPadding - iconSize - ExpectedPadding -
-                        suffixSize.value!!.width.toDp()).toPx()
+                    (TextFieldWidth - IconPadding - iconSize - ExpectedPadding - suffixSize).toPx()
                 )
                 assertThat(suffixPosition.value?.y).isWithin(1f).of(ExpectedPadding.toPx())
             }
@@ -1043,64 +1005,54 @@
 
     @Test
     fun testTextField_labelPositionX_initial_withTrailingAndLeading() {
-        val height = 60.dp
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "",
-                    onValueChange = {},
-                    modifier = Modifier.height(height),
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                            }
-                        )
-                    },
-                    trailingIcon = { Icon(Icons.Default.Favorite, null) },
-                    leadingIcon = { Icon(Icons.Default.Favorite, null) }
-                )
-            }
+            TextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Text(
+                        text = "label",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                trailingIcon = { Icon(Icons.Default.Favorite, null) },
+                leadingIcon = { Icon(Icons.Default.Favorite, null) }
+            )
         }
 
         rule.runOnIdleWithDensity {
             val iconSize = 24.dp // default icon size
-            assertThat(labelPosition.value?.x).isEqualTo(
-                (ExpectedPadding + IconPadding + iconSize).roundToPx().toFloat()
+            assertThat(labelPosition.value?.x).isWithin(1f).of(
+                (ExpectedPadding + IconPadding + iconSize).toPx()
             )
         }
     }
 
     @Test
     fun testTextField_labelPositionX_initial_withNullTrailingAndLeading() {
-        val height = 60.dp
         val labelPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
-            Box {
-                TextField(
-                    value = "",
-                    onValueChange = {},
-                    modifier = Modifier.height(height),
-                    label = {
-                        Text(
-                            text = "label",
-                            modifier = Modifier.onGloballyPositioned {
-                                labelPosition.value = it.positionInRoot()
-                            }
-                        )
-                    },
-                    trailingIcon = null,
-                    leadingIcon = null
-                )
-            }
+            TextField(
+                value = "",
+                onValueChange = {},
+                label = {
+                    Text(
+                        text = "label",
+                        modifier = Modifier.onGloballyPositioned {
+                            labelPosition.value = it.positionInRoot()
+                        }
+                    )
+                },
+                trailingIcon = null,
+                leadingIcon = null
+            )
         }
 
         rule.runOnIdleWithDensity {
-            assertThat(labelPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
+            assertThat(labelPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
         }
     }
 
@@ -1142,22 +1094,17 @@
     }
 
     @Test
-    fun testTextField_supportingText_position() {
-        val tfSize = Ref<IntSize>()
-        val supportingSize = Ref<IntSize>()
+    fun testTextField_supportingTextPosition_withDefaultHeight() {
         val supportingPosition = Ref<Offset>()
         rule.setMaterialContent(lightColorScheme()) {
             TextField(
                 value = "",
                 onValueChange = {},
-                modifier = Modifier.onGloballyPositioned {
-                    tfSize.value = it.size
-                },
+                textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                 supportingText = {
-                    Text(
-                        text = "Supporting",
-                        modifier = Modifier.onGloballyPositioned {
-                            supportingSize.value = it.size
+                    Box(Modifier
+                        .size(MinSupportingTextLineHeight)
+                        .onGloballyPositioned {
                             supportingPosition.value = it.positionInRoot()
                         }
                     )
@@ -1166,11 +1113,9 @@
         }
 
         rule.runOnIdleWithDensity {
-            assertThat(supportingPosition.value?.x).isEqualTo(
-                ExpectedPadding.roundToPx().toFloat()
-            )
-            assertThat(supportingPosition.value?.y).isEqualTo(
-                tfSize.value!!.height - supportingSize.value!!.height
+            assertThat(supportingPosition.value?.x).isWithin(1f).of(ExpectedPadding.toPx())
+            assertThat(supportingPosition.value?.y).isWithin(1f).of(
+                (ExpectedDefaultTextFieldHeight + SupportingTopPadding).toPx()
             )
         }
     }
@@ -1374,7 +1319,7 @@
     @Test
     @LargeTest
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    fun testTransformedTextIsUsed_toDefineLabelPosition() {
+    fun testTextField_transformedTextIsUsed_toDefineLabelPosition() {
         // if non-transformed value were used to check if the text input is empty, the label
         // wouldn't be aligned to the top, as a result it would be obscured by text
         val prefixTransformation = VisualTransformation { text ->
@@ -1410,7 +1355,7 @@
     @Test
     @LargeTest
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-    fun testTransformedTextIsUsed_toDefineIfPlaceholderNeeded() {
+    fun testTextField_transformedTextIsUsed_toDefineIfPlaceholderNeeded() {
         // if original value were used to check if the text input is empty, the placeholder would be
         // displayed on top of the text
         val prefixTransformation = VisualTransformation { text ->
@@ -1454,7 +1399,7 @@
     }
 
     @Test
-    fun testErrorSemantics_defaultMessage() {
+    fun testTextField_errorSemantics_defaultMessage() {
         lateinit var errorMessage: String
         rule.setMaterialContent(lightColorScheme()) {
             TextField(
@@ -1471,10 +1416,10 @@
     }
 
     @Test
-    fun testErrorSemantics_messageOverridable() {
+    fun testTextField_errorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
         rule.setMaterialContent(lightColorScheme()) {
-            var isError = remember { mutableStateOf(true) }
+            val isError = remember { mutableStateOf(true) }
             TextField(
                 value = "test",
                 onValueChange = {},
@@ -1732,7 +1677,7 @@
                     TextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") }
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                     )
                     Divider(Modifier.fillMaxHeight())
                 }
@@ -1756,7 +1701,7 @@
                     TextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") },
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                         leadingIcon = { Icon(Icons.Default.Favorite, null) }
                     )
                     Divider(Modifier.fillMaxHeight())
@@ -1781,7 +1726,7 @@
                     TextField(
                         value = text.value,
                         onValueChange = { text.value = it },
-                        placeholder = { Text("placeholder") },
+                        textStyle = TextStyle(fontSize = 1.sp), // ensure text size is minimum
                         trailingIcon = { Icon(Icons.Default.Favorite, null) }
                     )
                     Divider(Modifier.fillMaxHeight())
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TimePickerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TimePickerTest.kt
index b26f237..fb31d63 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TimePickerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TimePickerTest.kt
@@ -17,19 +17,26 @@
 package androidx.compose.material3
 
 import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
 import android.os.Build
 import android.text.format.DateFormat
-import androidx.compose.ui.platform.LocalContext
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.semantics.SemanticsProperties.SelectableGroup
 import androidx.compose.ui.test.ExperimentalTestApi
 import androidx.compose.ui.test.SemanticsMatcher.Companion.expectValue
 import androidx.compose.ui.test.SemanticsMatcher.Companion.keyIsDefined
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
 import androidx.compose.ui.test.assert
 import androidx.compose.ui.test.assertAll
+import androidx.compose.ui.test.assertContentDescriptionContains
 import androidx.compose.ui.test.assertCountEquals
 import androidx.compose.ui.test.assertHasClickAction
 import androidx.compose.ui.test.assertIsNotSelected
@@ -49,6 +56,7 @@
 import androidx.compose.ui.test.onAllNodesWithContentDescription
 import androidx.compose.ui.test.onAllNodesWithText
 import androidx.compose.ui.test.onChildren
+import androidx.compose.ui.test.onFirst
 import androidx.compose.ui.test.onLast
 import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithText
@@ -61,6 +69,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
 import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
 import com.android.dx.mockito.inline.extended.MockedMethod
@@ -79,15 +88,45 @@
     val rule = createComposeRule()
 
     @Test
+    fun timePicker_vertical_layout() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val newConfiguration = Configuration(LocalConfiguration.current)
+            newConfiguration.screenHeightDp = 800
+            newConfiguration.screenWidthDp = 500
+            CompositionLocalProvider(LocalConfiguration provides newConfiguration) {
+                assertThat(defaultTimePickerLayoutType).isEqualTo(TimePickerLayoutType.Vertical)
+            }
+        }
+    }
+
+    @Test
+    fun timePicker_horizontal_layout() {
+        rule.setMaterialContent(lightColorScheme()) {
+            val newConfiguration = Configuration(LocalConfiguration.current)
+            newConfiguration.screenHeightDp = 500
+            newConfiguration.screenWidthDp = 800
+            CompositionLocalProvider(LocalConfiguration provides newConfiguration) {
+                assertThat(defaultTimePickerLayoutType).isEqualTo(TimePickerLayoutType.Horizontal)
+            }
+        }
+    }
+
+    @Test
     fun timePicker_initialState() {
         val state = TimePickerState(initialHour = 14, initialMinute = 23, is24Hour = false)
         rule.setMaterialContent(lightColorScheme()) {
             TimePicker(state)
         }
 
-        rule.onAllNodesWithText("23").assertCountEquals(1)
+       rule.onNodeWithTimeValue(
+           number = 2,
+           selection = Selection.Hour,
+       ).assertIsSelected()
 
-        rule.onNodeWithText("02").assertIsSelected()
+        rule.onNodeWithTimeValue(
+            number = 23,
+            selection = Selection.Minute,
+        ).assertExists()
 
         rule.onNodeWithText("AM").assertExists()
 
@@ -101,9 +140,14 @@
             TimePicker(state)
         }
 
-        rule.onNodeWithText("23").performClick()
+        rule.onNodeWithTimeValue(
+            number = 23,
+            selection = Selection.Minute,
+        ).performClick()
 
-        rule.onNodeWithText("55").assertExists()
+        rule.runOnIdle {
+            assertThat(state.selection).isEqualTo(Selection.Minute)
+        }
     }
 
     @Test
@@ -113,7 +157,7 @@
             TimePicker(state)
         }
 
-        rule.onNodeWithText("6").performClick()
+        rule.onNodeWithTimeValue(number = 6, selection = Selection.Hour).performClick()
 
         // shows 06 in display
         rule.onNodeWithText("06").assertExists()
@@ -327,12 +371,17 @@
 
         rule.onNodeWithText("14")
             .assert(isFocusable())
+            .assertContentDescriptionContains("for hour")
             .assert(hasImeAction(ImeAction.Next))
             .assert(isFocused())
 
         rule.onAllNodesWithText("23")
             .filterToOne(isSelectable())
             .assert(isNotSelected())
+            .performClick()
+
+        rule.onNodeWithText("23")
+            .assertContentDescriptionContains("for minutes")
     }
 
     @OptIn(ExperimentalComposeUiApi::class, ExperimentalTestApi::class)
@@ -479,7 +528,7 @@
         }
 
         repeat(24) { number ->
-            rule.onNodeWithText(number.toString()).performClick()
+            rule.onNodeWithTimeValue(number, Selection.Hour, is24Hour = true).performClick()
             rule.runOnIdle {
                 state.selection = Selection.Hour
                 assertThat(state.hour).isEqualTo(number)
@@ -506,11 +555,78 @@
                 else -> number
             }
 
-            rule.onNodeWithText("$hour").performClick()
+            rule.onNodeWithTimeValue(hour, Selection.Hour).performClick()
             rule.runOnIdle {
                 state.selection = Selection.Hour
                 assertThat(state.hour).isEqualTo(number)
             }
         }
     }
+
+    @Test
+    fun clockFace_24HourMinutes_everyValue() {
+        val state = TimePickerState(initialHour = 10, initialMinute = 23, is24Hour = true)
+        state.selection = Selection.Minute
+        rule.setMaterialContent(lightColorScheme()) {
+            ClockFace(state, TimePickerDefaults.colors())
+        }
+
+        repeat(11) { number ->
+            rule.onNodeWithTimeValue(
+                number * 5,
+                Selection.Minute,
+                is24Hour = true
+            ).performClick()
+            rule.runOnIdle {
+                assertThat(state.minute).isEqualTo(number * 5)
+            }
+        }
+    }
+
+    @Test
+    fun clockFace_12HourMinutes_everyValue() {
+        val state = TimePickerState(initialHour = 10, initialMinute = 23, is24Hour = false)
+        state.selection = Selection.Minute
+        rule.setMaterialContent(lightColorScheme()) {
+            ClockFace(state, TimePickerDefaults.colors())
+        }
+
+        repeat(11) { number ->
+            rule.onNodeWithTimeValue(number * 5, Selection.Minute).performClick()
+            rule.runOnIdle {
+                assertThat(state.minute).isEqualTo(number * 5)
+            }
+        }
+    }
+
+    private fun contentDescriptionForValue(
+        resources: Resources,
+        selection: Selection,
+        is24Hour: Boolean,
+        number: Int
+    ): String {
+
+        val id = if (selection == Selection.Minute) {
+            R.string.time_picker_minute_suffix
+        } else if (is24Hour) {
+            R.string.time_picker_hour_24h_suffix
+        } else {
+            R.string.time_picker_hour_suffix
+        }
+
+        return resources.getString(id, number)
+    }
+
+    private fun SemanticsNodeInteractionsProvider.onNodeWithTimeValue(
+        number: Int,
+        selection: Selection,
+        is24Hour: Boolean = false,
+    ): SemanticsNodeInteraction = onAllNodesWithContentDescription(
+        contentDescriptionForValue(
+            InstrumentationRegistry.getInstrumentation().context.resources,
+            selection,
+            is24Hour,
+            number
+        )
+    ).onFirst()
 }
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.android.kt
similarity index 65%
copy from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
copy to compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.android.kt
index 6f365ff..f3ed0e3 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.android.kt
@@ -16,9 +16,12 @@
 
 package androidx.compose.material3
 
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual val is24HourFormat: Boolean
-    @Composable
-    @ReadOnlyComposable get() = false
\ No newline at end of file
+private const val DefaultIncludeFontPadding = true
+
+@Suppress("DEPRECATION")
+private val DefaultPlatformTextStyle = PlatformTextStyle(
+    includeFontPadding = DefaultIncludeFontPadding
+)
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = DefaultPlatformTextStyle
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/SearchBar.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/SearchBar.kt
index 1c4cbf3..22914d0 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/SearchBar.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/SearchBar.kt
@@ -59,6 +59,7 @@
 import androidx.compose.material3.tokens.SearchViewTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.derivedStateOf
@@ -82,6 +83,7 @@
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.onClick
 import androidx.compose.ui.semantics.semantics
@@ -101,6 +103,7 @@
 import androidx.compose.ui.zIndex
 import kotlin.math.max
 import kotlin.math.min
+import kotlinx.coroutines.delay
 
 /**
  * <a href="https://m3.material.io/components/search/overview" class="external" target="_blank">Material Design search</a>.
@@ -177,6 +180,7 @@
         animationSpec = if (active) AnimationEnterFloatSpec else AnimationExitFloatSpec
     )
 
+    val focusManager = LocalFocusManager.current
     val density = LocalDensity.current
 
     val defaultInputFieldShape = SearchBarDefaults.inputFieldShape
@@ -276,6 +280,15 @@
         }
     }
 
+    LaunchedEffect(active) {
+        if (!active) {
+            // Not strictly needed according to the motion spec, but since the animation already has
+            // a delay, this works around b/261632544.
+            delay(AnimationDelayMillis.toLong())
+            focusManager.clearFocus()
+        }
+    }
+
     BackHandler(enabled = active) {
         onActiveChange(false)
     }
@@ -344,6 +357,8 @@
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
     content: @Composable ColumnScope.() -> Unit,
 ) {
+    val focusManager = LocalFocusManager.current
+
     Surface(
         shape = shape,
         color = colors.containerColor,
@@ -389,6 +404,15 @@
         }
     }
 
+    LaunchedEffect(active) {
+        if (!active) {
+            // Not strictly needed according to the motion spec, but since the animation already has
+            // a delay, this works around b/261632544.
+            delay(AnimationDelayMillis.toLong())
+            focusManager.clearFocus()
+        }
+    }
+
     BackHandler(enabled = active) {
         onActiveChange(false)
     }
@@ -469,6 +493,7 @@
 /**
  * Defaults used in [SearchBar] and [DockedSearchBar].
  */
+@ExperimentalMaterial3Api
 object SearchBarDefaults {
     /** Default elevation for a search bar. */
     val Elevation: Dp = SearchBarTokens.ContainerElevation
@@ -497,7 +522,6 @@
      * @param dividerColor the color of the divider between the input field and the search results
      * @param inputFieldColors the colors of the input field
      */
-    @ExperimentalMaterial3Api
     @Composable
     fun colors(
         containerColor: Color = SearchBarTokens.ContainerColor.toColor(),
@@ -533,7 +557,6 @@
      * @param unfocusedPlaceholderColor the placeholder color for this input field when not focused
      * @param disabledPlaceholderColor the placeholder color for this input field when disabled
      */
-    @ExperimentalMaterial3Api
     @Composable
     fun inputFieldColors(
         focusedTextColor: Color = SearchBarTokens.InputTextColor.toColor(),
@@ -573,7 +596,6 @@
         )
 
     @Deprecated("Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
-    @ExperimentalMaterial3Api
     @Composable
     fun inputFieldColors(
         textColor: Color = SearchBarTokens.InputTextColor.toColor(),
@@ -681,6 +703,7 @@
 }
 
 // Measurement specs
+@OptIn(ExperimentalMaterial3Api::class)
 private val SearchBarCornerRadius: Dp = InputFieldHeight / 2
 internal val DockedActiveTableMinHeight: Dp = 240.dp
 private const val DockedActiveTableMaxHeightScreenRatio: Float = 2f / 3f
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
index 65f9107..1ac562f 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/Strings.android.kt
@@ -188,6 +188,10 @@
             androidx.compose.material3.R.string.time_picker_hour)
         Strings.TimePickerMinute -> resources.getString(
             androidx.compose.material3.R.string.time_picker_minute)
+        Strings.TimePickerHourTextField -> resources.getString(
+            androidx.compose.material3.R.string.time_picker_hour_text_field)
+        Strings.TimePickerMinuteTextField -> resources.getString(
+            androidx.compose.material3.R.string.time_picker_minute_text_field)
         Strings.TooltipPaneDescription -> resources.getString(
             androidx.compose.material3.R.string.tooltip_pane_description)
         else -> ""
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TimePicker.android.kt
similarity index 65%
copy from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
copy to compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TimePicker.android.kt
index 6f365ff..002e5a2 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TimePicker.android.kt
@@ -18,7 +18,15 @@
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.platform.LocalConfiguration
 
-internal actual val is24HourFormat: Boolean
+@OptIn(ExperimentalMaterial3Api::class)
+internal actual val defaultTimePickerLayoutType: TimePickerLayoutType
     @Composable
-    @ReadOnlyComposable get() = false
\ No newline at end of file
+    @ReadOnlyComposable get() = with(LocalConfiguration.current) {
+        if (screenHeightDp < screenWidthDp) {
+            TimePickerLayoutType.Horizontal
+        } else {
+            TimePickerLayoutType.Vertical
+        }
+    }
diff --git a/compose/material3/material3/src/androidMain/res/values-af/strings.xml b/compose/material3/material3/src/androidMain/res/values-af/strings.xml
index 580f969..82cb957 100644
--- a/compose/material3/material3/src/androidMain/res/values-af/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-af/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Voer datums in"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ongeldige datumreeksinvoer"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Sleephandvatsel"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Vou onderste blad in"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Maak onderste blad toe"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Vou onderste blad uit"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Nutswenk"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Wys nutswenk"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"nm."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-am/strings.xml b/compose/material3/material3/src/androidMain/res/values-am/strings.xml
index 66ab384..9089850 100644
--- a/compose/material3/material3/src/androidMain/res/values-am/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-am/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"ቀናትን ያስገቡ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"ልክ ያልሆነ የቀን ክልል ግቤት"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"መያዣ ይጎትቱ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"የግርጌ ሉህን ይሰብስቡ"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"የግርጌ ሉህን ይሰብስቡ"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"የግርጌ ሉህ ይዘርጉ"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"የመሣሪያ ጥቆማ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"መሣሪያ ጥቆማን አሳይ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ከሰዓት"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ar/strings.xml b/compose/material3/material3/src/androidMain/res/values-ar/strings.xml
index 033383e..89511f8 100644
--- a/compose/material3/material3/src/androidMain/res/values-ar/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ar/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"إدخال التواريخ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"إدخال نطاق زمني غير صالح"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"مقبض السحب"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"تصغير البطاقة السفلية"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"إغلاق البطاقة السفلية"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"توسيع البطاقة السفلية"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"تلميح"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"إظهار التلميح"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"م"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-as/strings.xml b/compose/material3/material3/src/androidMain/res/values-as/strings.xml
index 4b34266..b6f4a1c 100644
--- a/compose/material3/material3/src/androidMain/res/values-as/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-as/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"তাৰিখ দিয়ক"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"অমান্য তাৰিখৰ পৰিসৰৰ ইনপুট"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ড্ৰেগ হেণ্ডেল"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"তলৰ শ্বীটখন সংকোচন কৰক"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"তলৰ শ্বীটখন অগ্ৰাহ্য কৰক"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"তলৰ শ্বীটখন বিস্তাৰ কৰক"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"টুলটিপ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"টুলটিপ দেখুৱাওক"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"পৰাহ্ন"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-az/strings.xml b/compose/material3/material3/src/androidMain/res/values-az/strings.xml
index 0ca1afe..f30ced8 100644
--- a/compose/material3/material3/src/androidMain/res/values-az/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-az/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Tarixləri daxil edin"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Yanlış tarix aralığı daxiletməsi"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Dəstəyi çəkin"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Aşağıdakı vərəqi yığcamlaşdırın"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Aşağıdakı vərəqi rədd edin"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Aşağıdakı vərəqi genişləndirin"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Alət izahı"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"İpucu göstərin"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-b+sr+Latn/strings.xml b/compose/material3/material3/src/androidMain/res/values-b+sr+Latn/strings.xml
index 0bc4a3a..f8f3864 100644
--- a/compose/material3/material3/src/androidMain/res/values-b+sr+Latn/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-b+sr+Latn/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Unesite datume"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Unos opsega datuma je nevažeći"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Identifikator za prevlačenje"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Skupi donju tabelu"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Odbaci donju tabelu"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Proširi donju tabelu"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Objašnjenje"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Prikaži objašnjenje"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"po"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-be/strings.xml b/compose/material3/material3/src/androidMain/res/values-be/strings.xml
index 6f983e8..54bacc7 100644
--- a/compose/material3/material3/src/androidMain/res/values-be/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-be/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Увядзіце даты"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Уведзены няправільны дыяпазон дат"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Маркер перацягвання"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Згарнуць ніжні аркуш"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Закрыць ніжні аркуш"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Разгарнуць ніжні аркуш"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Падказка"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Паказваць усплывальную падказку"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"пасля паўдня"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-bg/strings.xml b/compose/material3/material3/src/androidMain/res/values-bg/strings.xml
index 9159c1d..a1c440f 100644
--- a/compose/material3/material3/src/androidMain/res/values-bg/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-bg/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Въведете дати"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Въведен е невалиден период от време"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Манипулатор за преместване с плъзгане"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Свиване на долния лист"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Отхвърляне на долния лист"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Разгъване на долния лист"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Подсказка"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Показване на подсказка"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-bn/strings.xml b/compose/material3/material3/src/androidMain/res/values-bn/strings.xml
index 6afcc01..4823cfe 100644
--- a/compose/material3/material3/src/androidMain/res/values-bn/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-bn/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"তারিখ লিখুন"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"তারিখের ব্যাপ্তি সম্পর্কিত ইনপুট ভুল দেওয়া আছে"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"টেনে আনার হ্যান্ডেল"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"স্ক্রিনের নিচে অ্যাটাচ করা শিট আড়াল করুন"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"স্ক্রিনের নিচে অ্যাটাচ করা শিট বাতিল করুন"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"স্ক্রিনের নিচে অ্যাটাচ করা শিট বড় করুন"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"টুলটিপ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"টুলটিপ দেখান"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-bs/strings.xml b/compose/material3/material3/src/androidMain/res/values-bs/strings.xml
index d02537d..85f4c16 100644
--- a/compose/material3/material3/src/androidMain/res/values-bs/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-bs/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Unesite datume"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Nevažeći unos raspona datuma"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Ručica za prevlačenje"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Sužavanje donje tabele"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Odbacivanje donje tabele"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Proširivanje donje tabele"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Skočni opis"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Prikaži skočni opis"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"poslijepodne"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ca/strings.xml b/compose/material3/material3/src/androidMain/res/values-ca/strings.xml
index 82bea54..cea0d2b 100644
--- a/compose/material3/material3/src/androidMain/res/values-ca/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ca/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Introdueix les dates"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"S\'ha introduït un interval de dades no vàlid"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Ansa per arrossegar"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Replega el full inferior"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Ignora el full inferior"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Desplega el full inferior"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Descripció emergent"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Mostra la descripció emergent"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-cs/strings.xml b/compose/material3/material3/src/androidMain/res/values-cs/strings.xml
index 69cd262..5e187c9 100644
--- a/compose/material3/material3/src/androidMain/res/values-cs/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-cs/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Zadejte data"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Neplatné období"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Úchyt pro přetažení"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Sbalit spodní tabulku"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Zavřít spodní tabulku"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Rozbalit spodní tabulku"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Popisek"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Zobrazit popisek"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-da/strings.xml b/compose/material3/material3/src/androidMain/res/values-da/strings.xml
index 5a2d660..fbb4d2b 100644
--- a/compose/material3/material3/src/androidMain/res/values-da/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-da/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Angiv datoer"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ugyldig angivelse af datainterval"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Håndtag"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Skjul felt i bunden"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Luk felt i bunden"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Udvid felt i bunden"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Værktøjstip"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Se værktøjstip"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-de/strings.xml b/compose/material3/material3/src/androidMain/res/values-de/strings.xml
index 1e0e158..9a5b827 100644
--- a/compose/material3/material3/src/androidMain/res/values-de/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-de/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Daten eingeben"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Angegebener Zeitraum ungültig"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Ziehpunkt"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Ansicht am unteren Rand minimieren"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Ansicht am unteren Rand schließen"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Ansicht am unteren Rand maximieren"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Kurzinfo"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Kurzinfo anzeigen"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-el/strings.xml b/compose/material3/material3/src/androidMain/res/values-el/strings.xml
index 97b435b..93d2841 100644
--- a/compose/material3/material3/src/androidMain/res/values-el/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-el/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Εισαγωγή ημερομηνιών"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Μη έγκυρη εισαγωγή εύρους ημερομηνιών"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Λαβή μεταφοράς"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Σύμπτυξη φύλλου κάτω μέρους"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Παράβλεψη φύλλου κάτω μέρους"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Ανάπτυξη φύλλου κάτω μέρους"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Επεξήγηση εργαλείου"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Προβολή επεξήγησης"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ΜΜ"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-es-rUS/strings.xml b/compose/material3/material3/src/androidMain/res/values-es-rUS/strings.xml
index 98f1ffc..add0587 100644
--- a/compose/material3/material3/src/androidMain/res/values-es-rUS/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-es-rUS/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Ingresar fechas"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Se introdujo un período no válido"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Controlador de arrastre"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Contraer la hoja inferior"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Descartar la hoja inferior"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Expandir la hoja inferior"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Información"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Mostrar información"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"p.m."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-es/strings.xml b/compose/material3/material3/src/androidMain/res/values-es/strings.xml
index 48f642b..6590a14 100644
--- a/compose/material3/material3/src/androidMain/res/values-es/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-es/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Introducir fechas"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"El intervalo de fechas no es válido"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Controlador de arrastre"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Contrae la hoja inferior"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Cierra la hoja inferior"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Despliega la hoja inferior"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Descripción emergente"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Mostrar descripción emergente"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-et/strings.xml b/compose/material3/material3/src/androidMain/res/values-et/strings.xml
index 1a05d680..ba913f7 100644
--- a/compose/material3/material3/src/androidMain/res/values-et/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-et/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Sisestage kuupäevad"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Sisestati sobimatu kuupäevavahemik"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Lohistamispide"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Alumise lehe ahendamine"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Alumisest lehest loobumine"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Alumise lehe laiendamine"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Kohtspikker"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Kuva kohtspikker"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-eu/strings.xml b/compose/material3/material3/src/androidMain/res/values-eu/strings.xml
index 43d79354..623117b 100644
--- a/compose/material3/material3/src/androidMain/res/values-eu/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-eu/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Idatzi datak"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Idatzitako data tarteak ez du balio"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Arrastatzeko kontrol-puntua"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Tolestu pantailaren behealdean ainguratutako orria"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Baztertu pantailaren behealdean ainguratutako orria"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Zabaldu pantailaren behealdean ainguratutako orria"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Aholkua"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Erakutsi aholkua"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
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 0ba4c72..5efdeee 100644
--- a/compose/material3/material3/src/androidMain/res/values-fa/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-fa/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"تاریخ‌ها را وارد کنید"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"محدوده تاریخ واردشده نامعتبر است"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"دستگیره کشاندن"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"جمع کردن برگه زیرین"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"رد کردن برگه زیرین"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ازهم باز کردن برگه زیرین"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"نکته‌ابزار"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"نمایش نکته‌ابزار"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ب.ظ."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-fi/strings.xml b/compose/material3/material3/src/androidMain/res/values-fi/strings.xml
index efea19e..4338c71 100644
--- a/compose/material3/material3/src/androidMain/res/values-fi/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-fi/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Lisää päivämäärät"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Virheellinen ajanjakso"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Vetokahva"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Tiivistä alapaneeli"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Hylkää alapaneeli"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Laajenna alapaneeli"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Vihjeteksti"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Näytä vihjeteksti"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"IP"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-fr-rCA/strings.xml b/compose/material3/material3/src/androidMain/res/values-fr-rCA/strings.xml
index 2ce849d..c939248 100644
--- a/compose/material3/material3/src/androidMain/res/values-fr-rCA/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-fr-rCA/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Entrer les dates"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Entrée de période incorrecte"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Poignée de déplacement"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Réduire la zone de contenu dans le bas de l\'écran"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Fermer la zone de contenu dans le bas de l\'écran"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Développer la zone de contenu dans le bas de l\'écran"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Infobulle"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Afficher une infobulle"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-fr/strings.xml b/compose/material3/material3/src/androidMain/res/values-fr/strings.xml
index 5f7e380..3d318c6 100644
--- a/compose/material3/material3/src/androidMain/res/values-fr/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-fr/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Saisir des dates"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Plage de dates non valide"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Poignée de déplacement"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Réduire la bottom sheet"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Fermer la bottom sheet"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Développer la bottom sheet"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Info-bulle"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Afficher l\'info-bulle"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-gl/strings.xml b/compose/material3/material3/src/androidMain/res/values-gl/strings.xml
index a22ec51..c191c2b 100644
--- a/compose/material3/material3/src/androidMain/res/values-gl/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-gl/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Indica as datas"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Indicouse un intervalo de datas que non é válido"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Controlador de arrastre"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Contraer panel inferior"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Pechar panel inferior"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Despregar panel inferior"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Cadro de información"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Mostrar cadro de información"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"pm"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-gu/strings.xml b/compose/material3/material3/src/androidMain/res/values-gu/strings.xml
index b45aabf..7426dc1 100644
--- a/compose/material3/material3/src/androidMain/res/values-gu/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-gu/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"તારીખો દાખલ કરો"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"તારીખની શ્રેણીનું અમાન્ય ઇનપુટ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ઑબ્જેક્ટ ખેંચવાનું હૅન્ડલ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"બોટમ શીટ નાની કરો"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"બોટમ શીટ છોડી દો"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"બોટમ શીટ મોટી કરો"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ટૂલટિપ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ટૂલટિપ બતાવો"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-hi/strings.xml b/compose/material3/material3/src/androidMain/res/values-hi/strings.xml
index 35d585e..e817c02 100644
--- a/compose/material3/material3/src/androidMain/res/values-hi/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-hi/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"तारीखें डालें"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"तारीख की दी गई सीमा गलत है"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"खींचकर छोड़ने वाला हैंडल"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"बॉटम शीट को छोटा करें"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"बॉटम शीट को खारिज करें"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"बॉटम शीट को बड़ा करें"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"टूलटिप"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"टूलटिप देखें"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-hr/strings.xml b/compose/material3/material3/src/androidMain/res/values-hr/strings.xml
index 2f9c3cb..f08bcdc 100644
--- a/compose/material3/material3/src/androidMain/res/values-hr/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-hr/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Unos datuma"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Unos datumskog raspona nije važeći"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Marker za povlačenje"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Sažimanje donje tablice"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Odbacivanje donje tablice"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Proširivanje donje tablice"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Opis"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Prikaži opis"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"Poslijepodne"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-hu/strings.xml b/compose/material3/material3/src/androidMain/res/values-hu/strings.xml
index 500c866..443ee6e 100644
--- a/compose/material3/material3/src/androidMain/res/values-hu/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-hu/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Dátumok megadása"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Érvénytelen a megadott dátum"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Fogópont"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Az alsó lap összecsukása"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Az alsó lap elvetése"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Az alsó lap kibontása"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Elemleírás"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Elemleírás megjelenítése"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"du."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-hy/strings.xml b/compose/material3/material3/src/androidMain/res/values-hy/strings.xml
index 50d319f..43f72bd 100644
--- a/compose/material3/material3/src/androidMain/res/values-hy/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-hy/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Մուտքագրեք ամսաթվերը"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Մուտքագրված ամսաթվերի միջակայքն անվավեր է"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Տեղափոխման նշիչ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Ծալել ներքևի էկրանը"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Փակել ներքևի էկրանը"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Ծավալել ներքևի էկրանը"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Հուշակ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Ցուցադրել հուշում"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-in/strings.xml b/compose/material3/material3/src/androidMain/res/values-in/strings.xml
index cf6645c..27b26ef 100644
--- a/compose/material3/material3/src/androidMain/res/values-in/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-in/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Masukkan tanggal"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Input rentang tanggal tidak valid"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Handel geser"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Menciutkan sheet bawah"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Menutup sheet bawah"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Meluaskan sheet bawah"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Tooltip"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Tampilkan tooltip"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-is/strings.xml b/compose/material3/material3/src/androidMain/res/values-is/strings.xml
index f090921..10ee8ed 100644
--- a/compose/material3/material3/src/androidMain/res/values-is/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-is/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Sláðu inn dagsetningar"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ógilt tímabil fært inn"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Dragkló"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Minnka blað neðst"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Hunsa blað neðst"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Stækka blað neðst"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Ábending"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Sýna ábendingu"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"eh"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-iw/strings.xml b/compose/material3/material3/src/androidMain/res/values-iw/strings.xml
index 095cd13..7813462 100644
--- a/compose/material3/material3/src/androidMain/res/values-iw/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-iw/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"הזנת תאריכים"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"קלט טווח תאריכים לא חוקי"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"נקודת אחיזה לגרירה"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"כיווץ הגיליון התחתון"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"סגירת הגיליון התחתון"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"הרחבת הגיליון התחתון"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"הסבר קצר"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"הצגת הסבר קצר"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ja/strings.xml b/compose/material3/material3/src/androidMain/res/values-ja/strings.xml
index 750d905..c73f641 100644
--- a/compose/material3/material3/src/androidMain/res/values-ja/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ja/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"日付の入力"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"入力された期間は無効です"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ドラッグ ハンドル"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ボトムシートを折りたたみます"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ボトムシートを閉じます"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ボトムシートを開きます"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ツールチップ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ツールチップを表示します"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ka/strings.xml b/compose/material3/material3/src/androidMain/res/values-ka/strings.xml
index f59ba7d..a82d135 100644
--- a/compose/material3/material3/src/androidMain/res/values-ka/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ka/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"თარიღების შეყვანა"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"შეყვანილია თარიღების არასწორი დიაპაზონი"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"სახელური ჩავლებისთვის"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ქვედა ფურცლის ჩაკეცვა"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ქვედა ფურცლის უარყოფა"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ქვედა ფურცლის გაშლა"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"მინიშნება"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"მინიშნების ჩვენება"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-kk/strings.xml b/compose/material3/material3/src/androidMain/res/values-kk/strings.xml
index 0a65d47..7e01f63 100644
--- a/compose/material3/material3/src/androidMain/res/values-kk/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-kk/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Күндерді енгізіңіз"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Жарамсыз күндер аралығы енгізілген."</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Сүйрейтін тетік"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Төменгі парақшаны жию"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Төменгі парақшаны жабу"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Төменгі парақшаны жаю"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Қалқыма көмек"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Қалқыма көмекті көрсету"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"түстен кейін"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-km/strings.xml b/compose/material3/material3/src/androidMain/res/values-km/strings.xml
index b247f86..83a3611 100644
--- a/compose/material3/material3/src/androidMain/res/values-km/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-km/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"បញ្ចូល​កាលបរិច្ឆេទ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"ការបញ្ចូលចន្លោះកាលបរិច្ឆេទមិនត្រឹមត្រូវ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ដង​អូស"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"បង្រួម​សន្លឹកខាងក្រោម"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ច្រានចោល​សន្លឹកខាងក្រោម"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ពង្រីក​សន្លឹកខាងក្រោម"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"កំណត់​ពន្យល់"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"បង្ហាញ​កំណត់​ពន្យល់"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ko/strings.xml b/compose/material3/material3/src/androidMain/res/values-ko/strings.xml
index 24cc091..0abda2e 100644
--- a/compose/material3/material3/src/androidMain/res/values-ko/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ko/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"날짜 입력"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"잘못된 기간 입력"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"드래그 핸들"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"하단 시트 접기"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"하단 시트 닫기"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"하단 시트 펼치기"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"도움말"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"도움말 표시"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"오후"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ky/strings.xml b/compose/material3/material3/src/androidMain/res/values-ky/strings.xml
index d9e1152..b5f50c9 100644
--- a/compose/material3/material3/src/androidMain/res/values-ky/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ky/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Күндөрдү киргизүү"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Даталар диапазону туура эмес тандалды"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Тизменин керектүү жерине сүйрөп баруу"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Ылдыйкы экранды жыйыштыруу"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Ылдыйкы экранды жабуу"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Ылдыйкы экранды жайып көрсөтүү"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Калкып чыгуучу кеңеш"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Калкып чыгуучу кеңешти көрсөтүү"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"түштөн кийин"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-lt/strings.xml b/compose/material3/material3/src/androidMain/res/values-lt/strings.xml
index 2f2b031..7ccb152 100644
--- a/compose/material3/material3/src/androidMain/res/values-lt/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-lt/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Įvesti datas"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Netinkama dienų sekos įvestis"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Vilkimo rankenėlė"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Sutraukti apatinį lapą"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Atsisakyti apatinio lapo"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Išskleisti apatinį lapą"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Patarimas"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Rodyti patarimą"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"popiet"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-lv/strings.xml b/compose/material3/material3/src/androidMain/res/values-lv/strings.xml
index 288096b..88d2a70 100644
--- a/compose/material3/material3/src/androidMain/res/values-lv/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-lv/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Ievadiet datumus"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ievadīts nederīgs datumu diapazons."</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Vilkšanas turis"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Sakļaut ekrāna apakšdaļas lapu"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Noraidīt ekrāna apakšdaļas lapu"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Izvērst ekrāna apakšdaļas lapu"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Rīka padoms"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Rādīt rīka padomu"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ml/strings.xml b/compose/material3/material3/src/androidMain/res/values-ml/strings.xml
index cf41cc2..9036dea 100644
--- a/compose/material3/material3/src/androidMain/res/values-ml/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ml/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"തീയതികൾ നൽകുക"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"തീയതി ശ്രേണി ഇൻപുട്ട് അസാധുവാണ്"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"വലിച്ചിടുന്നതിനുള്ള ഹാൻഡിൽ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ബോട്ടം ഷീറ്റ് ചുരുക്കുക"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ബോട്ടം ഷീറ്റ് ഡിസ്മിസ് ചെയ്യുക"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ബോട്ടം ഷീറ്റ് വികസിപ്പിക്കുക"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ടൂൾടിപ്പ്"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ടൂൾടിപ്പ് കാണിക്കുക"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-mn/strings.xml b/compose/material3/material3/src/androidMain/res/values-mn/strings.xml
index a55fdf6..9e7b213 100644
--- a/compose/material3/material3/src/androidMain/res/values-mn/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-mn/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Огноо оруулах"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Хугацааны интервалын оролт буруу байна"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Чирэх бариул"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Доод хүснэгтийг хураах"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Доод хүснэгтийг хаах"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Доод хүснэгтийг дэлгэх"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Зөвлөмж"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Зөвлөмж харуулах"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ҮХ"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-mr/strings.xml b/compose/material3/material3/src/androidMain/res/values-mr/strings.xml
index 7dd8357..d8dde6e 100644
--- a/compose/material3/material3/src/androidMain/res/values-mr/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-mr/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"तारखा एंटर करा"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"तारीख रेंजचे इनपुट चुकीचे आहे"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ड्रॅग हॅंडल"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"तळाशी असलेली शीट कोलॅप्स करा"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"तळाशी असलेली शीट डिसमिस करा"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"तळाशी असलेली शीट विस्तारीत करा"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"टूलटिप"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"टूलटिप दाखवा"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ms/strings.xml b/compose/material3/material3/src/androidMain/res/values-ms/strings.xml
index 9dcc19d..73a106e 100644
--- a/compose/material3/material3/src/androidMain/res/values-ms/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ms/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Masukkan tarikh"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Input julat tarikh tidak sah"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Pemegang seret"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Kuncupkan helaian bawah"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Ketepikan helaian bawah"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Kembangkan helaian bawah"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Tip alat"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Tunjukkan tip alat"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"P/M"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-my/strings.xml b/compose/material3/material3/src/androidMain/res/values-my/strings.xml
index 09f9c67..cfb334a 100644
--- a/compose/material3/material3/src/androidMain/res/values-my/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-my/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"ရက်စွဲများထည့်ပါ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"ဒေတာအပိုင်းအခြား ထည့်သွင်းမှု မမှန်ပါ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ဖိဆွဲအထိန်း"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"အောက်ခြေအပိုဆောင်း စာမျက်နှာကို ချုံ့သည်"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"အောက်ခြေအပိုဆောင်း စာမျက်နှာကို ပယ်သည်"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"အောက်ခြေအပိုဆောင်း စာမျက်နှာကို ချဲ့သည်"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"အကြံပြုချက်ပြ ပေါ့အပ် ဝင်းဒိုး"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"အကြံပြုချက်ပြ ပေါ့အပ်ဝင်းဒိုး ပြရန်"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-nb/strings.xml b/compose/material3/material3/src/androidMain/res/values-nb/strings.xml
index 3ba360f..dfd307e 100644
--- a/compose/material3/material3/src/androidMain/res/values-nb/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-nb/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Legg inn datoer"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"En ugyldig dataperiode er skrevet inn"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Håndtak"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Skjul feltet nederst"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Lukk feltet nederst"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Vis feltet nederst"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Verktøytips"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Vis verktøytips"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ne/strings.xml b/compose/material3/material3/src/androidMain/res/values-ne/strings.xml
index 9abf195..5a8da54 100644
--- a/compose/material3/material3/src/androidMain/res/values-ne/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ne/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"मितिहरू हाल्नुहोस्"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"मितिको अवैध दायरा तोकियो"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ड्र्याग ह्यान्डल"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"पुछारको पाना कोल्याप्स गर्नुहोस्"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"पुछारको पाना हटाउनुहोस्"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"पुछारको पाना एक्स्पान्ड गर्नुहोस्"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"टुलटिप"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"टुलटिप देखाइयोस्"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-nl/strings.xml b/compose/material3/material3/src/androidMain/res/values-nl/strings.xml
index 2ecf2a7..6511e5e 100644
--- a/compose/material3/material3/src/androidMain/res/values-nl/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-nl/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Datums opgeven"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ongeldige invoer voor periode"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Handgreep voor slepen"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Blad onderaan samenvouwen"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Blad onderaan sluiten"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Blad onderaan uitvouwen"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Tooltip"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Tooltip tonen"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-or/strings.xml b/compose/material3/material3/src/androidMain/res/values-or/strings.xml
index fc09715..2890a40 100644
--- a/compose/material3/material3/src/androidMain/res/values-or/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-or/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"ତାରିଖଗୁଡ଼ିକ ଲେଖନ୍ତୁ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"ଅବୈଧ ତାରିଖ ରେଞ୍ଜ ଇନପୁଟ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ଡ୍ରାଗ ହେଣ୍ଡେଲ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ବଟମ ସିଟକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ବଟମ ସିଟକୁ ଖାରଜ କରନ୍ତୁ"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ବଟମ ସିଟକୁ ବିସ୍ତାର କରନ୍ତୁ"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ଟୁଲଟିପ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ଟୁଲଟିପ ଦେଖାନ୍ତୁ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-pa/strings.xml b/compose/material3/material3/src/androidMain/res/values-pa/strings.xml
index f69dd51..d271de5 100644
--- a/compose/material3/material3/src/androidMain/res/values-pa/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-pa/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"ਤਾਰੀਖਾਂ ਦਾਖਲ ਕਰੋ"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"ਇਨਪੁੱਟ ਕੀਤੀ ਗਈ ਤਾਰੀਖ ਦੀ ਰੇਂਜ ਅਵੈਧ ਹੈ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ਘਸੀਟਣ ਵਾਲਾ ਹੈਂਡਲ"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ਹੇਠਲੀ ਸ਼ੀਟ ਨੂੰ ਸਮੇਟੋ"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ਹੇਠਲੀ ਸ਼ੀਟ ਨੂੰ ਖਾਰਜ ਕਰੋ"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ਹੇਠਲੀ ਸ਼ੀਟ ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ਟੂਲ-ਟਿੱਪ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ਟੂਲ-ਟਿੱਪ ਦਿਖਾਓ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-pl/strings.xml b/compose/material3/material3/src/androidMain/res/values-pl/strings.xml
index 2ecf3ea..8475a5c 100644
--- a/compose/material3/material3/src/androidMain/res/values-pl/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-pl/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Wprowadź daty"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Nieprawidłowy zakres dat"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Uchwyt do przeciągania"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Zwiń planszę dolną"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Zamknij planszę dolną"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Rozwiń planszę dolną"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Etykietka"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Pokaż etykietkę"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ro/strings.xml b/compose/material3/material3/src/androidMain/res/values-ro/strings.xml
index 1bbe278..7119060 100644
--- a/compose/material3/material3/src/androidMain/res/values-ro/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ro/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Introdu datele"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Intervalul de date introdus nu este valid"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Ghidaj de tragere"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Restrânge foaia din partea de jos"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Închide foaia din partea de jos"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Extinde foaia din partea de jos"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Balon explicativ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Afișează balonul explicativ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"p.m."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ru/strings.xml b/compose/material3/material3/src/androidMain/res/values-ru/strings.xml
index 64e4e01..c360133 100644
--- a/compose/material3/material3/src/androidMain/res/values-ru/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ru/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Введите даты"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Указан недопустимый диапазон дат."</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Маркер перемещения"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Свернуть нижний экран"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Закрыть нижний экран"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Развернуть нижний экран"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Подсказка"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Показать подсказку"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-si/strings.xml b/compose/material3/material3/src/androidMain/res/values-si/strings.xml
index b0b144f..62fdacc 100644
--- a/compose/material3/material3/src/androidMain/res/values-si/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-si/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"දින ඇතුළු කරන්න"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"අවලංගු දින පරාස ආදානය"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"ඇදීම් හැඬලය"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"පහළම පත්‍රය හකුළන්න"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"පහළම පත්‍රය අස් කරන්න"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"පහළම පත්‍රය දිග හරින්න"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"මෙවලම් ඉඟිය"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"මෙවලම් ඉඟිය පෙන්වන්න"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ප.ව."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sk/strings.xml b/compose/material3/material3/src/androidMain/res/values-sk/strings.xml
index a9adb7e..71fe757 100644
--- a/compose/material3/material3/src/androidMain/res/values-sk/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sk/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Zadajte dátumy"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Neplatný vstup obdobia"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Presúvadlo"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Zbaliť dolný hárok"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Zavrieť dolný hárok"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Rozbaliť dolný hárok"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Popis"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Zobraziť opis"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sl/strings.xml b/compose/material3/material3/src/androidMain/res/values-sl/strings.xml
index 3bbf720..8242c04 100644
--- a/compose/material3/material3/src/androidMain/res/values-sl/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sl/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Vnesite datume"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Neveljaven vnos obdobja."</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Ročica za vlečenje"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Strnitev razdelka na dnu zaslona"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Opustitev razdelka na dnu zaslona"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Razširitev razdelka na dnu zaslona"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Opis orodja"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Pokaži opis orodja"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"pop."</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sq/strings.xml b/compose/material3/material3/src/androidMain/res/values-sq/strings.xml
index 5c58dff..c2c05db 100644
--- a/compose/material3/material3/src/androidMain/res/values-sq/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sq/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Fut datat"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Hyrje e pavlefshme e diapazonit të datave"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Doreza e zvarritjes"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Palos fletën e poshtme"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Hiq fletën e poshtme"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Zgjero fletën e poshtme"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Këshilla për veglën"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Shfaq këshillat për veglën"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"MD"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sr/strings.xml b/compose/material3/material3/src/androidMain/res/values-sr/strings.xml
index c253b45..5a5e890 100644
--- a/compose/material3/material3/src/androidMain/res/values-sr/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sr/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Унесите датуме"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Унос опсега датума је неважећи"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Идентификатор за превлачење"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Скупи доњу табелу"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Одбаци доњу табелу"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Прошири доњу табелу"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Објашњење"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Прикажи објашњење"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"по"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sv/strings.xml b/compose/material3/material3/src/androidMain/res/values-sv/strings.xml
index 8613182..58487de 100644
--- a/compose/material3/material3/src/androidMain/res/values-sv/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sv/strings.xml
@@ -54,14 +54,10 @@
     <string name="date_range_picker_day_in_range" msgid="9048690781645835833">"Inom intervall"</string>
     <string name="date_range_input_title" msgid="2366412111888449406">"Ange datum"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Ett ogiltigt datumintervall har angetts"</string>
-    <!-- no translation found for bottom_sheet_drag_handle_description (7772321844937772780) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Handtag"</string>
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Komprimera arket på nedre delen av skärmen"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Stäng arket på nedre delen av skärmen"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Utöka arket på nedre delen av skärmen"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Beskrivning"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Visa beskrivning"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"EM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-sw/strings.xml b/compose/material3/material3/src/androidMain/res/values-sw/strings.xml
index e38417d..9052d352 100644
--- a/compose/material3/material3/src/androidMain/res/values-sw/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-sw/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Weka tarehe"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Kipindi kilichowekwa si sahihi"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Aikoni ya buruta"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Kunja safu ya chini"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Ondoa safu ya chini"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Panua safu ya chini"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Kidirisha cha vidokezo"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Onyesha kidirisha cha vidokezo"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"Mchana"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ta/strings.xml b/compose/material3/material3/src/androidMain/res/values-ta/strings.xml
index 0580cfe..a5a16b3 100644
--- a/compose/material3/material3/src/androidMain/res/values-ta/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ta/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"தேதிகளை உள்ளிடுங்கள்"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"தவறான தேதி வரம்பை உள்ளிட்டுள்ளீர்கள்"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"இழுப்பதற்கான ஹேண்டில்"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"கீழ்ப்புறச் சீட்டைச் சுருக்கும்"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"கீழ்ப்புறச் சீட்டை நிராகரிக்கும்"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"கீழ்ப்புறச் சீட்டை விரிவாக்கும்"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"உதவிக்குறிப்பு"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"உதவிக்குறிப்பைக் காட்டு"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-te/strings.xml b/compose/material3/material3/src/androidMain/res/values-te/strings.xml
index 9cfd074..cc04aac 100644
--- a/compose/material3/material3/src/androidMain/res/values-te/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-te/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"తేదీలను ఎంటర్ చేయండి"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"తేదీల పరిధి ఇన్‌పుట్ చెల్లదు"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"లాగే హ్యాండిల్"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"దిగువున ఉన్న షీట్‌ను కుదిస్తుంది"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"దిగువున ఉన్న షీట్‌ను విస్మరిస్తుంది"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"దిగువున ఉన్న షీట్‌ను విస్తరిస్తుంది"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"టూల్‌టిప్"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"టూల్‌టిప్‌ను చూపించు"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-th/strings.xml b/compose/material3/material3/src/androidMain/res/values-th/strings.xml
index 1c1e122..770c897 100644
--- a/compose/material3/material3/src/androidMain/res/values-th/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-th/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"ป้อนวันที่"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"การป้อนข้อมูลช่วงวันที่ไม่ถูกต้อง"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"แฮนเดิลการลาก"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"ยุบ Bottom Sheet"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"ปิด Bottom Sheet"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"ขยาย Bottom Sheet"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"เคล็ดลับเครื่องมือ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"แสดงเคล็ดลับเครื่องมือ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-tl/strings.xml b/compose/material3/material3/src/androidMain/res/values-tl/strings.xml
index 4ec31b1..d9833a9 100644
--- a/compose/material3/material3/src/androidMain/res/values-tl/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-tl/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Maglagay ng mga petsa"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Invalid ang input na hanay ng petsa"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Handle sa pag-drag"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"I-collapse ang bottom sheet"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"I-dismiss ang bottom sheet"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Palawakin ang bottom sheet"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Tooltip"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Ipakita ang tooltip"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-tr/strings.xml b/compose/material3/material3/src/androidMain/res/values-tr/strings.xml
index 61bc807..d000f00 100644
--- a/compose/material3/material3/src/androidMain/res/values-tr/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-tr/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Tarihleri girin"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Geçersiz tarih aralığı girişi"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Sürükleme tutamacı"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Alt sayfayı daralt"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Alt sayfayı kapat"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Alt sayfayı genişlet"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"İpucu"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Araç ipucunu göster"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ÖS"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-uk/strings.xml b/compose/material3/material3/src/androidMain/res/values-uk/strings.xml
index 433711fa..f3116ca 100644
--- a/compose/material3/material3/src/androidMain/res/values-uk/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-uk/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Введіть дати"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Указано недійсний діапазон дат"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Маркер переміщення"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Згорнути нижній екран"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Закрити нижній екран"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Розгорнути нижній екран"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Спливаюча підказка"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Показати підказку"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"ПП"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-ur/strings.xml b/compose/material3/material3/src/androidMain/res/values-ur/strings.xml
index 045d61d..7e599eb 100644
--- a/compose/material3/material3/src/androidMain/res/values-ur/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-ur/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"تواریخ درج کریں"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"تاریخ کی حد کا غلط ان پٹ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"گھسیٹنے کا ہینڈل"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"نیچے کی شیٹ کو سکیڑیں"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"نیچے کی شیٹ کو برخاست کریں"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"نیچے کی شیٹ کو پھیلائیں"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"ٹول ٹپ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"ٹول ٹپ دکھائیں"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"بعد از دوپہر"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-uz/strings.xml b/compose/material3/material3/src/androidMain/res/values-uz/strings.xml
index 2ffa0a5..13b1a45 100644
--- a/compose/material3/material3/src/androidMain/res/values-uz/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-uz/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Sanalarni kiriting"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Kiritilgan muddat yaroqsiz"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Surish dastagi"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Quyi ekranni yigʻish"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Quyi ekranni yopish"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Quyi ekranni yoyish"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Maslahat oynasi"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Maslahat oynasini koʻrsatish"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"TK"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-vi/strings.xml b/compose/material3/material3/src/androidMain/res/values-vi/strings.xml
index 2f65eb9..66379d6 100644
--- a/compose/material3/material3/src/androidMain/res/values-vi/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-vi/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Nhập ngày"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Phạm vi ngày đã nhập không hợp lệ"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Nút kéo"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Thu gọn bảng dưới cùng"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Bỏ qua bảng dưới cùng"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Mở rộng bảng dưới cùng"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Chú giải công cụ"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Hiển thị chú giải công cụ"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"CH"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-zh-rCN/strings.xml b/compose/material3/material3/src/androidMain/res/values-zh-rCN/strings.xml
index 30ebb15..7b469a0 100644
--- a/compose/material3/material3/src/androidMain/res/values-zh-rCN/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-zh-rCN/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"输入日期"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"输入的日期范围无效"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"拖动手柄"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"收起底部动作条"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"关闭底部动作条"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"展开底部动作条"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"提示"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"显示提示"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"下午"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-zh-rHK/strings.xml b/compose/material3/material3/src/androidMain/res/values-zh-rHK/strings.xml
index e906fe1c..9c7cd12 100644
--- a/compose/material3/material3/src/androidMain/res/values-zh-rHK/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-zh-rHK/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"輸入日期"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"輸入的日期範圍無效"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"拖曳控點"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"收合底部功能表"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"關閉底部功能表"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"展開底部功能表"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"提示"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"顯示提示"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"下午"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-zh-rTW/strings.xml b/compose/material3/material3/src/androidMain/res/values-zh-rTW/strings.xml
index c7fb463..20321fe 100644
--- a/compose/material3/material3/src/androidMain/res/values-zh-rTW/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-zh-rTW/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"輸入日期"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"輸入的日期範圍無效"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"拖曳控點"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"收合底部功能表"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"關閉底部功能表"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"展開底部功能表"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"工具提示"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"顯示工具提示"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"下午"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values-zu/strings.xml b/compose/material3/material3/src/androidMain/res/values-zu/strings.xml
index c3c5857..bfb9f8a 100644
--- a/compose/material3/material3/src/androidMain/res/values-zu/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values-zu/strings.xml
@@ -55,12 +55,9 @@
     <string name="date_range_input_title" msgid="2366412111888449406">"Faka izinsuku"</string>
     <string name="date_range_input_invalid_range_input" msgid="1891592555781755601">"Okokufaka kwebanga losuku okungavumelekile"</string>
     <string name="bottom_sheet_drag_handle_description" msgid="7772321844937772780">"Hudula isibambi"</string>
-    <!-- no translation found for bottom_sheet_collapse_description (6128938260108474660) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_dismiss_description (1918297411568599192) -->
-    <skip />
-    <!-- no translation found for bottom_sheet_expand_description (4324434199045499117) -->
-    <skip />
+    <string name="bottom_sheet_collapse_description" msgid="6128938260108474660">"Goqa ishidi eliphansi"</string>
+    <string name="bottom_sheet_dismiss_description" msgid="1918297411568599192">"Chitha ishidi eliphansi"</string>
+    <string name="bottom_sheet_expand_description" msgid="4324434199045499117">"Nweba ishidi eliphansi"</string>
     <string name="tooltip_pane_description" msgid="8191239805703103845">"Ithulithiphu"</string>
     <string name="tooltip_long_press_label" msgid="2732804537909054941">"Bonisa ithulithiphu"</string>
     <string name="time_picker_pm" msgid="2232702812657998674">"PM"</string>
diff --git a/compose/material3/material3/src/androidMain/res/values/strings.xml b/compose/material3/material3/src/androidMain/res/values/strings.xml
index ac0c807..dbd7ceb 100644
--- a/compose/material3/material3/src/androidMain/res/values/strings.xml
+++ b/compose/material3/material3/src/androidMain/res/values/strings.xml
@@ -103,4 +103,8 @@
     <string name="time_picker_minute">Minute</string>
     <!-- Label for a textField that allows the user to the hour to set the time -->
     <string name="time_picker_hour">Hour</string>
+    <!-- A label for a textfield that allows the user to input minutes. It reads: Edit Box, for minutes -->
+    <string name="time_picker_minute_text_field">for minutes</string>
+    <!-- A label for a textfield that allows the user to input hours. It reads: Edit Box, for hour -->
+    <string name="time_picker_hour_text_field">for hour</string>
 </resources>
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt
index 5bfdc87..21cd441 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt
@@ -193,12 +193,11 @@
                     placeables[j].width +
                         if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0
                 }
-                val arrangement = Arrangement.Bottom
-                // TODO(soboleva): rtl support
-                // Handle vertical direction
+                val arrangement = Arrangement.End
                 val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 }
                 with(arrangement) {
-                    arrange(mainAxisLayoutSize, childrenMainAxisSizes, mainAxisPositions)
+                    arrange(mainAxisLayoutSize, childrenMainAxisSizes,
+                        layoutDirection, mainAxisPositions)
                 }
                 placeables.forEachIndexed { j, placeable ->
                     placeable.place(
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
index da9bf4d..a434b7e 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
@@ -74,6 +74,7 @@
  * children. Defaults to the matching content color for [sheetContainerColor], or if that is
  * not a color from the theme, this will keep the same content color set above the bottom sheet.
  * @param sheetTonalElevation the tonal elevation of the bottom sheet
+ * @param sheetShadowElevation the shadow elevation of the bottom sheet
  * @param sheetDragHandle optional visual marker to pull the scaffold's bottom sheet
  * @param sheetSwipeEnabled whether the sheet swiping is enabled and should react to the user's
  * input
@@ -101,6 +102,7 @@
     sheetContainerColor: Color = BottomSheetDefaults.ContainerColor,
     sheetContentColor: Color = contentColorFor(sheetContainerColor),
     sheetTonalElevation: Dp = BottomSheetDefaults.Elevation,
+    sheetShadowElevation: Dp = BottomSheetDefaults.Elevation,
     sheetDragHandle: @Composable (() -> Unit)? = { BottomSheetDefaults.DragHandle() },
     sheetSwipeEnabled: Boolean = true,
     topBar: @Composable (() -> Unit)? = null,
@@ -129,6 +131,7 @@
                     containerColor = sheetContainerColor,
                     contentColor = sheetContentColor,
                     tonalElevation = sheetTonalElevation,
+                    shadowElevation = sheetShadowElevation,
                     dragHandle = sheetDragHandle,
                     content = sheetContent
                 )
@@ -196,6 +199,7 @@
     containerColor: Color,
     contentColor: Color,
     tonalElevation: Dp,
+    shadowElevation: Dp,
     dragHandle: @Composable (() -> Unit)?,
     content: @Composable ColumnScope.() -> Unit
 ) {
@@ -257,7 +261,8 @@
         shape = shape,
         color = containerColor,
         contentColor = contentColor,
-        tonalElevation = tonalElevation
+        tonalElevation = tonalElevation,
+        shadowElevation = shadowElevation,
     ) {
         Column(Modifier.fillMaxWidth()) {
             if (dragHandle != null) {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
index 47e1162..f3e5f68 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
@@ -914,8 +914,9 @@
      * Sets a start and end selection dates.
      *
      * The function expects the dates to be within the state's year-range, and for the start date to
-     * appear before the end date. Also, if an end date is provided (e.g. not `null`), a start date
-     * is also expected to be provided. In any other case, an [IllegalArgumentException] is thrown.
+     * appear before, or be equal, the end date. Also, if an end date is provided (e.g. not `null`),
+     * a start date is also expected to be provided. In any other case, an
+     * [IllegalArgumentException] is thrown.
      *
      * @param startDateMillis timestamp in _UTC_ milliseconds from the epoch that represents the
      * start date selection. Provide a `null` to indicate no selection.
@@ -951,8 +952,8 @@
             requireNotNull(startDate) {
                 "An end date was provided without a start date."
             }
-            // Validate that the end date appears after the start date.
-            require(startDate.utcTimeMillis < endDate.utcTimeMillis) {
+            // Validate that the end date appears on or after the start date.
+            require(startDate.utcTimeMillis <= endDate.utcTimeMillis) {
                 "The provided end date appears before the start date."
             }
         }
@@ -1042,7 +1043,11 @@
                     verticalAlignment = Alignment.CenterVertically
                 ) {
                     if (headline != null) {
-                        ProvideTextStyle(value = headlineTextStyle, content = headline)
+                        ProvideTextStyle(value = headlineTextStyle) {
+                            Box(modifier = Modifier.weight(1f)) {
+                                headline()
+                            }
+                        }
                     }
                     modeToggleButton?.invoke()
                 }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
index 2962286..f2e199c 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
@@ -603,7 +603,7 @@
             // Reset the selection to "start" only.
             selectedStartDate.value = date
             selectedEndDate.value = null
-        } else if (currentStart != null && date > currentStart) {
+        } else if (currentStart != null && date >= currentStart) {
             selectedEndDate.value = date
         }
     }
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.kt
similarity index 76%
copy from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
copy to compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.kt
index 6f365ff..256aae5 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.kt
@@ -16,9 +16,9 @@
 
 package androidx.compose.material3
 
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual val is24HourFormat: Boolean
-    @Composable
-    @ReadOnlyComposable get() = false
\ No newline at end of file
+/**
+ * Returns Default [PlatformTextStyle].
+ */
+internal expect fun defaultPlatformTextStyle(): PlatformTextStyle?
\ No newline at end of file
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
index 939ade7..0f76f4d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
@@ -23,7 +23,9 @@
 import androidx.compose.foundation.layout.calculateEndPadding
 import androidx.compose.foundation.layout.calculateStartPadding
 import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.text.BasicTextField
 import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
@@ -61,6 +63,7 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.coerceAtLeast
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.lerp
 import androidx.compose.ui.unit.offset
 import androidx.compose.ui.util.lerp
 import kotlin.math.max
@@ -562,6 +565,8 @@
                 Box(
                     Modifier
                         .layoutId(PrefixId)
+                        .heightIn(min = MinTextLineHeight)
+                        .wrapContentHeight()
                         .padding(start = startPadding, end = PrefixSuffixTextPadding)
                 ) {
                     prefix()
@@ -571,36 +576,51 @@
                 Box(
                     Modifier
                         .layoutId(SuffixId)
+                        .heightIn(min = MinTextLineHeight)
+                        .wrapContentHeight()
                         .padding(start = PrefixSuffixTextPadding, end = endPadding)
                 ) {
                     suffix()
                 }
             }
 
-            val textPadding = Modifier.padding(
-                start = if (prefix == null) startPadding else 0.dp,
-                end = if (suffix == null) endPadding else 0.dp,
-            )
+            val textPadding = Modifier
+                .heightIn(min = MinTextLineHeight)
+                .wrapContentHeight()
+                .padding(
+                    start = if (prefix == null) startPadding else 0.dp,
+                    end = if (suffix == null) endPadding else 0.dp,
+                )
 
             if (placeholder != null) {
-                placeholder(Modifier.layoutId(PlaceholderId).then(textPadding))
+                placeholder(Modifier
+                    .layoutId(PlaceholderId)
+                    .then(textPadding))
             }
 
             Box(
-                modifier = Modifier.layoutId(TextFieldId).then(textPadding),
+                modifier = Modifier
+                    .layoutId(TextFieldId)
+                    .then(textPadding),
                 propagateMinConstraints = true
             ) {
                 textField()
             }
 
             if (label != null) {
-                Box(modifier = Modifier.layoutId(LabelId)) { label() }
+                Box(Modifier
+                    .heightIn(min = lerp(
+                        MinTextLineHeight, MinFocusedLabelLineHeight, animationProgress))
+                    .wrapContentHeight()
+                    .layoutId(LabelId)) { label() }
             }
 
             if (supporting != null) {
                 @OptIn(ExperimentalMaterial3Api::class)
                 Box(Modifier
                     .layoutId(SupportingId)
+                    .heightIn(min = MinSupportingTextLineHeight)
+                    .wrapContentHeight()
                     .padding(TextFieldDefaults.supportingTextPadding())
                 ) { supporting() }
             }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Shapes.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Shapes.kt
index e1bbb61..c0fcd04 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Shapes.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Shapes.kt
@@ -145,11 +145,18 @@
     return copy(bottomStart = CornerSize(0.0.dp), bottomEnd = CornerSize(0.0.dp))
 }
 
-/** Helper function for component shape tokens. Used to grab the top values of a shape parameter. */
+/**
+ * Helper function for component shape tokens. Used to grab the bottom values of a shape parameter.
+ */
 internal fun CornerBasedShape.bottom(): CornerBasedShape {
     return copy(topStart = CornerSize(0.0.dp), topEnd = CornerSize(0.0.dp))
 }
 
+/** Helper function for component shape tokens. Used to grab the start values of a shape parameter. */
+internal fun CornerBasedShape.start(): CornerBasedShape {
+    return copy(topEnd = CornerSize(0.0.dp), bottomEnd = CornerSize(0.0.dp))
+}
+
 /** Helper function for component shape tokens. Used to grab the end values of a shape parameter. */
 internal fun CornerBasedShape.end(): CornerBasedShape {
     return copy(topStart = CornerSize(0.0.dp), bottomStart = CornerSize(0.0.dp))
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
index 54a96ae..67281ba 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Strings.kt
@@ -88,6 +88,8 @@
         val TimePickerMinuteSuffix = Strings()
         val TimePickerHour = Strings()
         val TimePickerMinute = Strings()
+        val TimePickerHourTextField = Strings()
+        val TimePickerMinuteTextField = Strings()
         val TooltipPaneDescription = Strings()
     }
 }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
index bfdc8a6..c418cf7 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.foundation.text.InlineTextContent
+import androidx.compose.material3.tokens.DefaultTextStyle
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.compositionLocalOf
@@ -343,7 +344,7 @@
  *
  * @see ProvideTextStyle
  */
-val LocalTextStyle = compositionLocalOf(structuralEqualityPolicy()) { TextStyle.Default }
+val LocalTextStyle = compositionLocalOf(structuralEqualityPolicy()) { DefaultTextStyle }
 
 // TODO(b/156598010): remove this and replace with fold definition on the backing CompositionLocal
 /**
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 ddb51f2e..7010bcf 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
@@ -24,7 +24,9 @@
 import androidx.compose.foundation.layout.calculateEndPadding
 import androidx.compose.foundation.layout.calculateStartPadding
 import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.text.BasicTextField
 import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
@@ -59,6 +61,7 @@
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.coerceAtLeast
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.lerp
 import androidx.compose.ui.unit.offset
 import kotlin.math.max
 import kotlin.math.roundToInt
@@ -558,6 +561,8 @@
                 Box(
                     Modifier
                         .layoutId(PrefixId)
+                        .heightIn(min = MinTextLineHeight)
+                        .wrapContentHeight()
                         .padding(start = startPadding, end = PrefixSuffixTextPadding)
                 ) {
                     prefix()
@@ -567,6 +572,8 @@
                 Box(
                     Modifier
                         .layoutId(SuffixId)
+                        .heightIn(min = MinTextLineHeight)
+                        .wrapContentHeight()
                         .padding(start = PrefixSuffixTextPadding, end = endPadding)
                 ) {
                     suffix()
@@ -577,19 +584,29 @@
                 Box(
                     Modifier
                         .layoutId(LabelId)
+                        .heightIn(min = lerp(
+                            MinTextLineHeight, MinFocusedLabelLineHeight, animationProgress))
+                        .wrapContentHeight()
                         .padding(start = startPadding, end = endPadding)) { label() }
             }
 
-            val textPadding = Modifier.padding(
-                start = if (prefix == null) startPadding else 0.dp,
-                end = if (suffix == null) endPadding else 0.dp,
-            )
+            val textPadding = Modifier
+                .heightIn(min = MinTextLineHeight)
+                .wrapContentHeight()
+                .padding(
+                    start = if (prefix == null) startPadding else 0.dp,
+                    end = if (suffix == null) endPadding else 0.dp,
+                )
 
             if (placeholder != null) {
-                placeholder(Modifier.layoutId(PlaceholderId).then(textPadding))
+                placeholder(Modifier
+                    .layoutId(PlaceholderId)
+                    .then(textPadding))
             }
             Box(
-                modifier = Modifier.layoutId(TextFieldId).then(textPadding),
+                modifier = Modifier
+                    .layoutId(TextFieldId)
+                    .then(textPadding),
                 propagateMinConstraints = true,
             ) {
                 textField()
@@ -599,6 +616,8 @@
                 @OptIn(ExperimentalMaterial3Api::class)
                 Box(Modifier
                     .layoutId(SupportingId)
+                    .heightIn(min = MinSupportingTextLineHeight)
+                    .wrapContentHeight()
                     .padding(TextFieldDefaults.supportingTextPadding())
                 ) { supporting() }
             }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
index e90d4c1..6cfb01f 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
@@ -422,5 +422,8 @@
 internal val HorizontalIconPadding = 12.dp
 internal val SupportingTopPadding = 4.dp
 internal val PrefixSuffixTextPadding = 2.dp
+internal val MinTextLineHeight = 24.dp
+internal val MinFocusedLabelLineHeight = 16.dp
+internal val MinSupportingTextLineHeight = 16.dp
 
 internal val IconDefaultSizeModifier = Modifier.defaultMinSize(48.dp, 48.dp)
\ No newline at end of file
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimeFormat.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimeFormat.kt
index 01f635a..d1941c5 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimeFormat.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimeFormat.kt
@@ -21,4 +21,4 @@
 
 internal expect val is24HourFormat: Boolean
   @Composable
-  @ReadOnlyComposable get
+  @ReadOnlyComposable get
\ No newline at end of file
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 665d9fe..d2c7319 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
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:OptIn(ExperimentalMaterial3Api::class)
 
 package androidx.compose.material3
 
@@ -31,16 +32,16 @@
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
+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.layout.width
 import androidx.compose.foundation.selection.selectableGroup
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.CornerBasedShape
@@ -66,6 +67,8 @@
 import androidx.compose.material3.tokens.TimePickerTokens.ClockDialUnselectedLabelTextColor
 import androidx.compose.material3.tokens.TimePickerTokens.ContainerColor
 import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorContainerShape
+import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorHorizontalContainerHeight
+import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorHorizontalContainerWidth
 import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorOutlineColor
 import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorSelectedContainerColor
 import androidx.compose.material3.tokens.TimePickerTokens.PeriodSelectorSelectedLabelTextColor
@@ -114,16 +117,22 @@
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.LayoutModifier
 import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.MeasurePolicy
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.layout.boundsInParent
 import androidx.compose.ui.layout.layoutId
+import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.InspectorValueInfo
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.debugInspectorInfo
 import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.isContainer
+import androidx.compose.ui.semantics.onClick
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.selectableGroup
 import androidx.compose.ui.semantics.selected
@@ -140,6 +149,7 @@
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.center
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.zIndex
 import java.text.NumberFormat
 import kotlin.math.PI
 import kotlin.math.abs
@@ -171,6 +181,8 @@
  * @param modifier the [Modifier] to be applied to this time input
  * @param colors colors [TimePickerColors] that will be used to resolve the colors used for this
  * time picker in different states. See [TimePickerDefaults.colors].
+ * @param layoutType, the different [TimePickerLayoutType] supported by this time picker,
+ * it will change the position and sizing of different components of the timepicker.
  */
 @Composable
 @ExperimentalMaterial3Api
@@ -178,12 +190,20 @@
     state: TimePickerState,
     modifier: Modifier = Modifier,
     colors: TimePickerColors = TimePickerDefaults.colors(),
+    layoutType: TimePickerLayoutType = TimePickerDefaults.layoutType(),
 ) {
-    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
-        ClockDisplay(state, colors)
-        Spacer(modifier = Modifier.height(ClockDisplayBottomMargin))
-        ClockFace(state, colors)
-        Spacer(modifier = Modifier.height(ClockFaceBottomMargin))
+    if (layoutType == TimePickerLayoutType.Vertical) {
+        VerticalTimePicker(
+            state = state,
+            modifier = modifier,
+            colors = colors,
+        )
+    } else {
+        HorizontalTimePicker(
+            state = state,
+            modifier = modifier,
+            colors = colors
+        )
     }
 }
 
@@ -209,103 +229,7 @@
     modifier: Modifier = Modifier,
     colors: TimePickerColors = TimePickerDefaults.colors(),
 ) {
-    var hourValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
-        mutableStateOf(TextFieldValue(text = state.hourForDisplay.toLocalString(2)))
-    }
-    var minuteValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
-        mutableStateOf(TextFieldValue(text = state.minute.toLocalString(2)))
-    }
-
-    Row(
-        modifier = modifier.padding(bottom = TimeInputBottomPadding),
-        verticalAlignment = Alignment.Top
-    ) {
-        val textStyle = MaterialTheme.typography.fromToken(TimeInputTokens.TimeFieldLabelTextFont)
-            .copy(
-                textAlign = TextAlign.Center,
-                color = colors.timeSelectorContentColor(true)
-            )
-
-        CompositionLocalProvider(LocalTextStyle provides textStyle) {
-            TimePickerTextField(
-                modifier = Modifier
-                    .onKeyEvent { event ->
-                        // Zero == 48, Nine == 57
-                        val switchFocus = event.utf16CodePoint in 48..57 &&
-                            hourValue.selection.start == 2 && hourValue.text.length == 2
-
-                        if (switchFocus) {
-                            state.selection = Selection.Minute
-                        }
-
-                        false
-                    },
-                value = hourValue,
-                onValueChange = { newValue ->
-                    timeInputOnChange(
-                        selection = Selection.Hour,
-                        state = state,
-                        value = newValue,
-                        prevValue = hourValue,
-                        max = if (state.is24hour) 23 else 12,
-                    ) { hourValue = it }
-                },
-                state = state,
-                selection = Selection.Hour,
-                keyboardOptions = KeyboardOptions(
-                    imeAction = ImeAction.Next,
-                    keyboardType = KeyboardType.Number
-                ),
-                keyboardActions = KeyboardActions(onNext = { state.selection = Selection.Minute }),
-                colors = colors,
-            )
-            DisplaySeparator(Modifier.size(DisplaySeparatorWidth, PeriodSelectorContainerHeight))
-            TimePickerTextField(
-                modifier = Modifier
-                    .onPreviewKeyEvent { event ->
-                        // 0 == KEYCODE_DEL
-                        val switchFocus = event.utf16CodePoint == 0 &&
-                            minuteValue.selection.start == 0
-
-                        if (switchFocus) {
-                            state.selection = Selection.Hour
-                        }
-
-                        switchFocus
-                    },
-
-                value = minuteValue,
-                onValueChange = { newValue ->
-                    timeInputOnChange(
-                        selection = Selection.Minute,
-                        state = state,
-                        value = newValue,
-                        prevValue = minuteValue,
-                        max = 59,
-                    ) { minuteValue = it }
-                },
-                state = state,
-                selection = Selection.Minute,
-                keyboardOptions = KeyboardOptions(
-                    imeAction = ImeAction.Done,
-                    keyboardType = KeyboardType.Number
-                ),
-                keyboardActions = KeyboardActions(onNext = { state.selection = Selection.Minute }),
-                colors = colors,
-            )
-        }
-
-        if (!state.is24hour) {
-            PeriodToggle(
-                modifier = Modifier.size(
-                    PeriodSelectorContainerWidth,
-                    PeriodSelectorContainerHeight
-                ),
-                state = state,
-                colors = colors
-            )
-        }
-    }
+    TimeInputImpl(modifier, colors, state)
 }
 
 /**
@@ -382,6 +306,11 @@
         timeSelectorSelectedContentColor = timeSelectorSelectedContentColor,
         timeSelectorUnselectedContentColor = timeSelectorUnselectedContentColor
     )
+
+    /** Default layout type, uses the screen dimensions to choose an appropriate layout. */
+    @ReadOnlyComposable
+    @Composable
+    fun layoutType(): TimePickerLayoutType = defaultTimePickerLayoutType
 }
 
 /**
@@ -518,6 +447,29 @@
 }
 
 /**
+ * Represents the different configurations for the layout of the Time Picker
+ */
+@Immutable
+@JvmInline
+@ExperimentalMaterial3Api
+value class TimePickerLayoutType internal constructor(internal val value: Int) {
+
+    companion object {
+        /** Displays the Time picker with a horizontal layout. Should be used in landscape mode. */
+        val Horizontal = TimePickerLayoutType(0)
+
+        /** Displays the Time picker with a vertical layout. Should be used in portrait mode.*/
+        val Vertical = TimePickerLayoutType(1)
+    }
+
+    override fun toString() = when (this) {
+        Horizontal -> "Horizontal"
+        Vertical -> "Vertical"
+        else -> "Unknown"
+    }
+}
+
+/**
  * A class to handle state changes in a [TimePicker]
  *
  * @sample androidx.compose.material3.samples.TimePickerSample
@@ -563,9 +515,8 @@
         DpOffset(offsetX, offsetY)
     }
 
-    internal val values by derivedStateOf {
-        if (selection == Selection.Minute) Minutes else Hours
-    }
+    internal var center by mutableStateOf(IntOffset.Zero)
+    internal val values get() = if (selection == Selection.Minute) Minutes else Hours
 
     internal var selection by mutableStateOf(Selection.Hour)
     internal var isAfternoonToggle by mutableStateOf(initialHour > 12 && !is24Hour)
@@ -588,6 +539,12 @@
         hourAngle = RadiansPerHour * hour % 12 - FullCircle / 4
     }
 
+    internal fun moveSelector(x: Float, y: Float, maxDist: Float) {
+        if (selection == Selection.Hour && is24hour) {
+            isInnerCircle = dist(x, y, center.x, center.y) < maxDist
+        }
+    }
+
     internal fun isSelected(value: Int): Boolean =
         if (selection == Selection.Minute) {
             value == minute
@@ -655,6 +612,17 @@
         currentAngle.animateTo(targetValue.second, tween(200))
     }
 
+    internal suspend fun onTap(x: Float, y: Float, maxDist: Float) {
+        update(atan(y - center.y, x - center.x), true)
+        moveSelector(x, y, maxDist)
+
+        if (selection == Selection.Hour) {
+            selection = Selection.Minute
+        } else {
+            settle()
+        }
+    }
+
     companion object {
         /**
          * The default [Saver] implementation for [TimePickerState].
@@ -678,13 +646,191 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun ClockDisplay(state: TimePickerState, colors: TimePickerColors) {
+@ExperimentalMaterial3Api
+internal fun VerticalTimePicker(
+    state: TimePickerState,
+    modifier: Modifier = Modifier,
+    colors: TimePickerColors = TimePickerDefaults.colors(),
+) {
+    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+        VerticalClockDisplay(state, colors)
+        Spacer(modifier = Modifier.height(ClockDisplayBottomMargin))
+        ClockFace(state, colors)
+        Spacer(modifier = Modifier.height(ClockFaceBottomMargin))
+    }
+}
+
+@Composable
+internal fun HorizontalTimePicker(
+    state: TimePickerState,
+    modifier: Modifier = Modifier,
+    colors: TimePickerColors = TimePickerDefaults.colors(),
+) {
+    Row(
+        modifier = modifier.padding(bottom = ClockFaceBottomMargin),
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        HorizontalClockDisplay(state, colors)
+        Spacer(modifier = Modifier.width(ClockDisplayBottomMargin))
+        ClockFace(state, colors)
+    }
+}
+
+@Composable
+private fun TimeInputImpl(
+    modifier: Modifier,
+    colors: TimePickerColors,
+    state: TimePickerState,
+) {
+    var hourValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
+        mutableStateOf(TextFieldValue(text = state.hourForDisplay.toLocalString(2)))
+    }
+    var minuteValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
+        mutableStateOf(TextFieldValue(text = state.minute.toLocalString(2)))
+    }
+
+    Row(
+        modifier = modifier.padding(bottom = TimeInputBottomPadding),
+        verticalAlignment = Alignment.Top
+    ) {
+        val textStyle = MaterialTheme.typography.fromToken(TimeInputTokens.TimeFieldLabelTextFont)
+            .copy(
+                textAlign = TextAlign.Center,
+                color = colors.timeSelectorContentColor(true)
+            )
+
+        CompositionLocalProvider(LocalTextStyle provides textStyle) {
+            TimePickerTextField(
+                modifier = Modifier
+                    .onKeyEvent { event ->
+                        // Zero == 48, Nine == 57
+                        val switchFocus = event.utf16CodePoint in 48..57 &&
+                            hourValue.selection.start == 2 && hourValue.text.length == 2
+
+                        if (switchFocus) {
+                            state.selection = Selection.Minute
+                        }
+
+                        false
+                    },
+                value = hourValue,
+                onValueChange = { newValue ->
+                    timeInputOnChange(
+                        selection = Selection.Hour,
+                        state = state,
+                        value = newValue,
+                        prevValue = hourValue,
+                        max = if (state.is24hour) 23 else 12,
+                    ) { hourValue = it }
+                },
+                state = state,
+                selection = Selection.Hour,
+                keyboardOptions = KeyboardOptions(
+                    imeAction = ImeAction.Next,
+                    keyboardType = KeyboardType.Number
+                ),
+                keyboardActions = KeyboardActions(onNext = { state.selection = Selection.Minute }),
+                colors = colors,
+            )
+            DisplaySeparator(Modifier.size(DisplaySeparatorWidth, PeriodSelectorContainerHeight))
+            TimePickerTextField(
+                modifier = Modifier
+                    .onPreviewKeyEvent { event ->
+                        // 0 == KEYCODE_DEL
+                        val switchFocus = event.utf16CodePoint == 0 &&
+                            minuteValue.selection.start == 0
+
+                        if (switchFocus) {
+                            state.selection = Selection.Hour
+                        }
+
+                        switchFocus
+                    },
+
+                value = minuteValue,
+                onValueChange = { newValue ->
+                    timeInputOnChange(
+                        selection = Selection.Minute,
+                        state = state,
+                        value = newValue,
+                        prevValue = minuteValue,
+                        max = 59,
+                    ) { minuteValue = it }
+                },
+                state = state,
+                selection = Selection.Minute,
+                keyboardOptions = KeyboardOptions(
+                    imeAction = ImeAction.Done,
+                    keyboardType = KeyboardType.Number
+                ),
+                keyboardActions = KeyboardActions(onNext = { state.selection = Selection.Minute }),
+                colors = colors,
+            )
+        }
+
+        if (!state.is24hour) {
+            Box(modifier.padding(start = PeriodToggleMargin)) {
+                VerticalPeriodToggle(
+                    modifier = Modifier.size(
+                        PeriodSelectorContainerWidth,
+                        PeriodSelectorContainerHeight
+                    ),
+                    state = state,
+                    colors = colors,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun HorizontalClockDisplay(state: TimePickerState, colors: TimePickerColors) {
+    Column(verticalArrangement = Arrangement.Center) {
+        ClockDisplayNumbers(state, colors)
+        if (!state.is24hour) {
+            Box(modifier = Modifier.padding(top = PeriodToggleMargin)) {
+                HorizontalPeriodToggle(
+                    modifier = Modifier.size(
+                        PeriodSelectorHorizontalContainerWidth,
+                        PeriodSelectorHorizontalContainerHeight
+                    ),
+                    state = state,
+                    colors = colors,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun VerticalClockDisplay(state: TimePickerState, colors: TimePickerColors) {
     Row(horizontalArrangement = Arrangement.Center) {
-        CompositionLocalProvider(
-            LocalTextStyle provides MaterialTheme.typography.fromToken(TimeSelectorLabelTextFont)
-        ) {
+        ClockDisplayNumbers(state, colors)
+        if (!state.is24hour) {
+            Box(modifier = Modifier.padding(start = PeriodToggleMargin)) {
+                VerticalPeriodToggle(
+                    modifier = Modifier.size(
+                        PeriodSelectorVerticalContainerWidth,
+                        PeriodSelectorVerticalContainerHeight
+                    ),
+                    state = state,
+                    colors = colors,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+private fun ClockDisplayNumbers(
+    state: TimePickerState,
+    colors: TimePickerColors
+) {
+    CompositionLocalProvider(
+        LocalTextStyle provides MaterialTheme.typography.fromToken(TimeSelectorLabelTextFont)
+    ) {
+        Row {
             TimeSelector(
                 modifier = Modifier.size(
                     TimeSelectorContainerWidth,
@@ -711,26 +857,104 @@
                 selection = Selection.Minute,
                 colors = colors,
             )
-            if (!state.is24hour) {
-                PeriodToggle(
-                    Modifier.size(
-                        PeriodSelectorVerticalContainerWidth,
-                        PeriodSelectorVerticalContainerHeight
-                    ),
-                    state,
-                    colors
-                )
-            }
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun PeriodToggle(
+private fun HorizontalPeriodToggle(
     modifier: Modifier,
     state: TimePickerState,
-    colors: TimePickerColors
+    colors: TimePickerColors,
+) {
+    val measurePolicy = remember {
+        MeasurePolicy { measurables, constraints ->
+            val spacer = measurables.first { it.layoutId == "Spacer" }
+            val spacerPlaceable = spacer.measure(
+                constraints.copy(
+                    minWidth = 0,
+                    maxWidth = TimePickerTokens.PeriodSelectorOutlineWidth.toPx().roundToInt(),
+                )
+            )
+
+            val items = measurables.filter { it.layoutId != "Spacer" }.map { item ->
+                item.measure(constraints.copy(
+                    minWidth = 0,
+                    maxWidth = constraints.maxWidth / 2
+                ))
+            }
+
+            layout(constraints.maxWidth, constraints.maxHeight) {
+                items[0].place(0, 0)
+                items[1].place(items[0].width, 0)
+                spacerPlaceable.place(items[0].width - spacerPlaceable.width / 2, 0)
+            }
+        }
+    }
+
+    val shape = PeriodSelectorContainerShape.toShape() as CornerBasedShape
+
+    PeriodToggleImpl(
+        modifier = modifier,
+        state = state,
+        colors = colors,
+        measurePolicy = measurePolicy,
+        startShape = shape.start(),
+        endShape = shape.end()
+    )
+}
+
+@Composable
+private fun VerticalPeriodToggle(
+    modifier: Modifier,
+    state: TimePickerState,
+    colors: TimePickerColors,
+) {
+    val measurePolicy = remember {
+        MeasurePolicy { measurables, constraints ->
+            val spacer = measurables.first { it.layoutId == "Spacer" }
+            val spacerPlaceable = spacer.measure(
+                constraints.copy(
+                    minHeight = 0,
+                    maxHeight = TimePickerTokens.PeriodSelectorOutlineWidth.toPx().roundToInt()
+                )
+            )
+
+            val items = measurables.filter { it.layoutId != "Spacer" }.map { item ->
+                item.measure(constraints.copy(
+                    minHeight = 0,
+                    maxHeight = constraints.maxHeight / 2
+                ))
+            }
+
+            layout(constraints.maxWidth, constraints.maxHeight) {
+                items[0].place(0, 0)
+                items[1].place(0, items[0].height)
+                spacerPlaceable.place(0, items[0].height - spacerPlaceable.height / 2)
+            }
+        }
+    }
+
+    val shape = PeriodSelectorContainerShape.toShape() as CornerBasedShape
+
+    PeriodToggleImpl(
+        modifier = modifier,
+        state = state,
+        colors = colors,
+        measurePolicy = measurePolicy,
+        startShape = shape.top(),
+        endShape = shape.bottom()
+    )
+}
+
+@Composable
+private fun PeriodToggleImpl(
+    modifier: Modifier,
+    state: TimePickerState,
+    colors: TimePickerColors,
+    measurePolicy: MeasurePolicy,
+    startShape: Shape,
+    endShape: Shape,
 ) {
     val borderStroke = BorderStroke(
         TimePickerTokens.PeriodSelectorOutlineWidth,
@@ -739,42 +963,47 @@
 
     val shape = PeriodSelectorContainerShape.toShape() as CornerBasedShape
     val contentDescription = getString(Strings.TimePickerPeriodToggle)
-    Column(Modifier
-        .padding(start = PeriodToggleMargin)
-        .semantics { this.contentDescription = contentDescription }
-        .selectableGroup()
-        .then(modifier)
-        .border(border = borderStroke, shape = shape)
-    ) {
-        ToggleItem(
-            checked = !state.isAfternoonToggle,
-            shape = shape.top(),
-            onClick = {
-                state.isAfternoonToggle = false
-            },
-            colors = colors,
-        ) { Text(text = getString(string = Strings.TimePickerAM)) }
-        Spacer(
-            Modifier
-                .fillMaxWidth()
-                .height(TimePickerTokens.PeriodSelectorOutlineWidth)
-                .background(color = PeriodSelectorOutlineColor.toColor())
-        )
-        ToggleItem(
-            checked =
-            state.isAfternoonToggle,
-            shape = shape.bottom(),
-            onClick = {
-                state.isAfternoonToggle = true
-            },
-            colors = colors,
-        ) { Text(getString(string = Strings.TimePickerPM)) }
-    }
+    Layout(
+        modifier = modifier
+            .semantics {
+                isContainer = true
+                this.contentDescription = contentDescription
+            }
+            .selectableGroup()
+            .then(modifier)
+            .border(border = borderStroke, shape = shape),
+        measurePolicy = measurePolicy,
+        content = {
+            ToggleItem(
+                checked = !state.isAfternoonToggle,
+                shape = startShape,
+                onClick = {
+                    state.isAfternoonToggle = false
+                },
+                colors = colors,
+            ) { Text(text = getString(string = Strings.TimePickerAM)) }
+            Spacer(
+                Modifier
+                    .layoutId("Spacer")
+                    .zIndex(SeparatorZIndex)
+                    .fillMaxSize()
+                    .background(color = PeriodSelectorOutlineColor.toColor())
+            )
+            ToggleItem(
+                checked =
+                state.isAfternoonToggle,
+                shape = endShape,
+                onClick = {
+                    state.isAfternoonToggle = true
+                },
+                colors = colors,
+            ) { Text(getString(string = Strings.TimePickerPM)) }
+        }
+    )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun ColumnScope.ToggleItem(
+private fun ToggleItem(
     checked: Boolean,
     shape: Shape,
     onClick: () -> Unit,
@@ -786,7 +1015,8 @@
 
     TextButton(
         modifier = Modifier
-            .weight(1f)
+            .zIndex(if (checked) 0f else 1f)
+            .fillMaxSize()
             .semantics { selected = checked },
         contentPadding = PaddingValues(0.dp),
         shape = shape,
@@ -811,7 +1041,7 @@
     )
 
     Box(
-        modifier = modifier,
+        modifier = modifier.clearAndSetSemantics { },
         contentAlignment = Alignment.Center
     ) {
         Text(
@@ -861,13 +1091,13 @@
         shape = TimeSelectorContainerShape.toShape(),
         color = containerColor,
     ) {
-        val valueContentDescription = getString(
+        val valueContentDescription =
             numberContentDescription(
                 selection = selection,
-                is24Hour = state.is24hour
-            ),
-            value
-        )
+                is24Hour = state.is24hour,
+                number = value
+            )
+
         Box(contentAlignment = Alignment.Center) {
             Text(
                 modifier = Modifier.semantics { contentDescription = valueContentDescription },
@@ -878,7 +1108,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 internal fun ClockFace(state: TimePickerState, colors: TimePickerColors) {
     Crossfade(
@@ -886,6 +1115,7 @@
             .background(shape = CircleShape, color = colors.clockDialColor)
             .size(ClockDialContainerSize)
             .semantics {
+                isContainer = false
                 selectableGroup()
             },
         targetState = state.values,
@@ -902,13 +1132,12 @@
                 LocalContentColor provides colors.clockDialContentColor(false)
             ) {
                 repeat(screen.size) {
-                    val outerValue = if (!state.is24hour) screen[it] else screen[it] % 12
-                    ClockText(
-                        is24Hour = state.is24hour,
-                        selection = state.selection,
-                        value = outerValue,
-                        selected = state.isSelected(it)
-                    )
+                    val outerValue = if (!state.is24hour || state.selection == Selection.Minute) {
+                        screen[it]
+                    } else {
+                        screen[it] % 12
+                    }
+                    ClockText(state = state, value = outerValue)
                 }
 
                 if (state.selection == Selection.Hour && state.is24hour) {
@@ -921,12 +1150,7 @@
                     ) {
                         repeat(ExtraHours.size) {
                             val innerValue = ExtraHours[it]
-                            ClockText(
-                                is24Hour = true,
-                                selection = state.selection,
-                                value = innerValue,
-                                selected = state.isSelected(it % 11)
-                            )
+                            ClockText(state = state, value = innerValue)
                         }
                     }
                 }
@@ -935,7 +1159,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 private fun Modifier.drawSelector(
     state: TimePickerState,
     colors: TimePickerColors,
@@ -1003,37 +1226,24 @@
 }) {
     var offsetX by remember { mutableStateOf(0f) }
     var offsetY by remember { mutableStateOf(0f) }
-    var center by remember { mutableStateOf(IntOffset.Zero) }
+    val center by remember { mutableStateOf(IntOffset.Zero) }
     val scope = rememberCoroutineScope()
     val maxDist = with(LocalDensity.current) { MaxDistance.toPx() }
-    fun moveSelector(x: Float, y: Float) {
-        if (state.selection == Selection.Hour && state.is24hour) {
-            state.isInnerCircle = dist(x, y, center.x, center.y) < maxDist
-        }
-    }
+
     Modifier
-        .onSizeChanged { center = it.center }
-        .pointerInput(state, maxDist, center) {
+        .onSizeChanged { state.center = it.center }
+        .pointerInput(state, center, maxDist) {
             detectTapGestures(
                 onPress = {
                     offsetX = it.x
                     offsetY = it.y
                 },
                 onTap = {
-                    scope.launch {
-                        state.update(atan(it.y - center.y, it.x - center.x), true)
-                        moveSelector(it.x, it.y)
-
-                        if (state.selection == Selection.Hour) {
-                            state.selection = Selection.Minute
-                        } else {
-                            state.settle()
-                        }
-                    }
+                    scope.launch { state.onTap(it.x, it.y, maxDist) }
                 },
             )
         }
-        .pointerInput(state, maxDist, center) {
+        .pointerInput(state, center, maxDist) {
             detectDragGestures(onDragEnd = {
                 scope.launch {
                     if (state.selection == Selection.Hour) {
@@ -1047,47 +1257,56 @@
                 scope.launch {
                     offsetX += dragAmount.x
                     offsetY += dragAmount.y
-                    state.update(atan(offsetY - center.y, offsetX - center.x))
+                    state.update(atan(offsetY - state.center.y, offsetX - state.center.x))
                 }
-                moveSelector(offsetX, offsetY)
+                state.moveSelector(offsetX, offsetY, maxDist)
             }
         }
 }
 
 @Composable
-private fun ClockText(
-    is24Hour: Boolean,
-    selected: Boolean,
-    selection: Selection,
-    value: Int
-) {
+private fun ClockText(state: TimePickerState, value: Int) {
     val style = MaterialTheme.typography.fromToken(ClockDialLabelTextFont).let {
-        remember(it) {
-            copyAndSetFontPadding(style = it, false)
-        }
+        copyAndSetFontPadding(style = it, false)
     }
 
-    val contentDescription = getString(
+    val maxDist = with(LocalDensity.current) { MaxDistance.toPx() }
+    var center by remember { mutableStateOf(Offset.Zero) }
+    val scope = rememberCoroutineScope()
+    val contentDescription =
         numberContentDescription(
-            selection = selection,
-            is24Hour = is24Hour
-        ),
-        value
-    )
+            selection = state.selection,
+            is24Hour = state.is24hour,
+            number = value
+        )
+
+    val text = value.toLocalString(minDigits = 1)
+    val selected = if (state.selection == Selection.Minute) {
+        state.minute.toLocalString(minDigits = 1) == text
+    } else {
+        state.hour.toLocalString(minDigits = 1) == text
+    }
 
     Box(
         contentAlignment = Alignment.Center,
         modifier = Modifier
             .minimumInteractiveComponentSize()
             .size(MinimumInteractiveSize)
+            .onGloballyPositioned { center = it.boundsInParent().center }
             .focusable()
-            .semantics {
+            .semantics(mergeDescendants = true) {
+                onClick {
+                    scope.launch { state.onTap(center.x, center.y, maxDist) }
+                    true
+                }
                 this.selected = selected
-                this.contentDescription = contentDescription
             }
     ) {
         Text(
-            text = value.toLocalString(minDigits = 1),
+            modifier = Modifier.clearAndSetSemantics {
+                this.contentDescription = contentDescription
+            },
+            text = text,
             style = style,
         )
     }
@@ -1174,13 +1393,24 @@
             )
         }
 
+        val contentDescription = getString(
+            if (selection == Selection.Minute) {
+                Strings.TimePickerMinuteTextField
+            } else {
+                Strings.TimePickerHourTextField
+            }
+        )
+
         Box(Modifier.visible(selected)) {
             BasicTextField(
                 value = value,
                 onValueChange = onValueChange,
                 modifier = Modifier
                     .focusRequester(focusRequester)
-                    .size(TimeFieldContainerWidth, TimeFieldContainerHeight),
+                    .size(TimeFieldContainerWidth, TimeFieldContainerHeight)
+                    .semantics {
+                        this.contentDescription = contentDescription
+                    },
                 interactionSource = interactionSource,
                 keyboardOptions = keyboardOptions,
                 keyboardActions = keyboardActions,
@@ -1219,7 +1449,9 @@
         }
 
         Text(
-            modifier = Modifier.offset(y = SupportLabelTop),
+            modifier = Modifier
+                .offset(y = SupportLabelTop)
+                .clearAndSetSemantics {},
             text = getString(
                 if (selection == Selection.Hour) {
                     Strings.TimePickerHour
@@ -1288,16 +1520,20 @@
 
 @Composable
 @ReadOnlyComposable
-private fun numberContentDescription(selection: Selection, is24Hour: Boolean): Strings {
-    if (selection == Selection.Minute) {
-        return Strings.TimePickerMinuteSuffix
+internal fun numberContentDescription(
+    selection: Selection,
+    is24Hour: Boolean,
+    number: Int
+): String {
+    val id = if (selection == Selection.Minute) {
+        Strings.TimePickerMinuteSuffix
+    } else if (is24Hour) {
+        Strings.TimePicker24HourSuffix
+    } else {
+        Strings.TimePickerHourSuffix
     }
 
-    if (is24Hour) {
-        return Strings.TimePicker24HourSuffix
-    }
-
-    return Strings.TimePickerHourSuffix
+    return getString(id, number)
 }
 
 private fun valuesForAnimation(current: Float, new: Float): Pair<Float, Float> {
@@ -1331,6 +1567,11 @@
     Selector, InnerCircle,
 }
 
+@OptIn(ExperimentalMaterial3Api::class)
+internal expect val defaultTimePickerLayoutType: TimePickerLayoutType
+    @Composable
+    @ReadOnlyComposable get
+
 @JvmInline
 internal value class Selection private constructor(val value: Int) {
     companion object {
@@ -1343,6 +1584,7 @@
 private const val QuarterCircle = PI / 2
 private const val RadiansPerMinute: Float = FullCircle / 60
 private const val RadiansPerHour: Float = FullCircle / 12f
+private const val SeparatorZIndex = 2f
 
 private val OuterCircleSizeRadius = 101.dp
 private val InnerCircleRadius = 69.dp
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TypographyTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TypographyTokens.kt
index 403ced0..089c598 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TypographyTokens.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TypographyTokens.kt
@@ -18,11 +18,12 @@
 
 package androidx.compose.material3.tokens
 
+import androidx.compose.material3.defaultPlatformTextStyle
 import androidx.compose.ui.text.TextStyle
 
 internal object TypographyTokens {
     val BodyLarge =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.BodyLargeFont,
             fontWeight = TypeScaleTokens.BodyLargeWeight,
             fontSize = TypeScaleTokens.BodyLargeSize,
@@ -30,7 +31,7 @@
             letterSpacing = TypeScaleTokens.BodyLargeTracking,
         )
     val BodyMedium =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.BodyMediumFont,
             fontWeight = TypeScaleTokens.BodyMediumWeight,
             fontSize = TypeScaleTokens.BodyMediumSize,
@@ -38,7 +39,7 @@
             letterSpacing = TypeScaleTokens.BodyMediumTracking,
         )
     val BodySmall =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.BodySmallFont,
             fontWeight = TypeScaleTokens.BodySmallWeight,
             fontSize = TypeScaleTokens.BodySmallSize,
@@ -46,7 +47,7 @@
             letterSpacing = TypeScaleTokens.BodySmallTracking,
         )
     val DisplayLarge =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.DisplayLargeFont,
             fontWeight = TypeScaleTokens.DisplayLargeWeight,
             fontSize = TypeScaleTokens.DisplayLargeSize,
@@ -54,7 +55,7 @@
             letterSpacing = TypeScaleTokens.DisplayLargeTracking,
         )
     val DisplayMedium =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.DisplayMediumFont,
             fontWeight = TypeScaleTokens.DisplayMediumWeight,
             fontSize = TypeScaleTokens.DisplayMediumSize,
@@ -62,7 +63,7 @@
             letterSpacing = TypeScaleTokens.DisplayMediumTracking,
         )
     val DisplaySmall =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.DisplaySmallFont,
             fontWeight = TypeScaleTokens.DisplaySmallWeight,
             fontSize = TypeScaleTokens.DisplaySmallSize,
@@ -70,7 +71,7 @@
             letterSpacing = TypeScaleTokens.DisplaySmallTracking,
         )
     val HeadlineLarge =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.HeadlineLargeFont,
             fontWeight = TypeScaleTokens.HeadlineLargeWeight,
             fontSize = TypeScaleTokens.HeadlineLargeSize,
@@ -78,7 +79,7 @@
             letterSpacing = TypeScaleTokens.HeadlineLargeTracking,
         )
     val HeadlineMedium =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.HeadlineMediumFont,
             fontWeight = TypeScaleTokens.HeadlineMediumWeight,
             fontSize = TypeScaleTokens.HeadlineMediumSize,
@@ -86,7 +87,7 @@
             letterSpacing = TypeScaleTokens.HeadlineMediumTracking,
         )
     val HeadlineSmall =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.HeadlineSmallFont,
             fontWeight = TypeScaleTokens.HeadlineSmallWeight,
             fontSize = TypeScaleTokens.HeadlineSmallSize,
@@ -94,7 +95,7 @@
             letterSpacing = TypeScaleTokens.HeadlineSmallTracking,
         )
     val LabelLarge =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.LabelLargeFont,
             fontWeight = TypeScaleTokens.LabelLargeWeight,
             fontSize = TypeScaleTokens.LabelLargeSize,
@@ -102,7 +103,7 @@
             letterSpacing = TypeScaleTokens.LabelLargeTracking,
         )
     val LabelMedium =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.LabelMediumFont,
             fontWeight = TypeScaleTokens.LabelMediumWeight,
             fontSize = TypeScaleTokens.LabelMediumSize,
@@ -110,7 +111,7 @@
             letterSpacing = TypeScaleTokens.LabelMediumTracking,
         )
     val LabelSmall =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.LabelSmallFont,
             fontWeight = TypeScaleTokens.LabelSmallWeight,
             fontSize = TypeScaleTokens.LabelSmallSize,
@@ -118,7 +119,7 @@
             letterSpacing = TypeScaleTokens.LabelSmallTracking,
         )
     val TitleLarge =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.TitleLargeFont,
             fontWeight = TypeScaleTokens.TitleLargeWeight,
             fontSize = TypeScaleTokens.TitleLargeSize,
@@ -126,7 +127,7 @@
             letterSpacing = TypeScaleTokens.TitleLargeTracking,
         )
     val TitleMedium =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.TitleMediumFont,
             fontWeight = TypeScaleTokens.TitleMediumWeight,
             fontSize = TypeScaleTokens.TitleMediumSize,
@@ -134,11 +135,13 @@
             letterSpacing = TypeScaleTokens.TitleMediumTracking,
         )
     val TitleSmall =
-        TextStyle(
+        DefaultTextStyle.copy(
             fontFamily = TypeScaleTokens.TitleSmallFont,
             fontWeight = TypeScaleTokens.TitleSmallWeight,
             fontSize = TypeScaleTokens.TitleSmallSize,
             lineHeight = TypeScaleTokens.TitleSmallLineHeight,
             letterSpacing = TypeScaleTokens.TitleSmallTracking,
         )
-}
\ No newline at end of file
+}
+
+internal val DefaultTextStyle = TextStyle.Default.copy(platformStyle = defaultPlatformTextStyle())
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/CalendarModel.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt
similarity index 100%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/CalendarModel.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.desktop.kt
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.desktop.kt
index 8f2bd49..3e06cac 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/DefaultPlatformTextStyle.desktop.kt
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+package androidx.compose.material3
 
-package androidx.compose.foundation.newtext.text.copypasta
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = null
\ No newline at end of file
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/IncludeFontPaddingHelper.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/IncludeFontPaddingHelper.desktop.kt
similarity index 100%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/IncludeFontPaddingHelper.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/IncludeFontPaddingHelper.desktop.kt
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/ModalBottomSheetPopup.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/ModalBottomSheetPopup.desktop.kt
similarity index 100%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/ModalBottomSheetPopup.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/ModalBottomSheetPopup.desktop.kt
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Strings.desktop.kt
similarity index 97%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Strings.desktop.kt
index f58f0d5..e36431b 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/Strings.desktop.kt
@@ -84,6 +84,8 @@
         Strings.TimePicker24HourSuffix -> "%1$ hours"
         Strings.TimePickerMinute -> "Minute"
         Strings.TimePickerHour -> "Hour"
+        Strings.TimePickerMinuteTextField -> "for minutes"
+        Strings.TimePickerHourTextField -> "for hour"
         Strings.TooltipPaneDescription -> "Tooltip"
         else -> ""
     }
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/SystemBarsDefaultInsets.desktop.kt
similarity index 100%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/SystemBarsDefaultInsets.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/SystemBarsDefaultInsets.desktop.kt
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt
similarity index 99%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt
index 6f365ff..f1c70f9 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimeFormat.desktop.kt
@@ -21,4 +21,4 @@
 
 internal actual val is24HourFormat: Boolean
     @Composable
-    @ReadOnlyComposable get() = false
\ No newline at end of file
+    @ReadOnlyComposable get() = false
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt
similarity index 76%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt
index 8f2bd49..530eca7 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TimePicker.desktop.kt
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+package androidx.compose.material3
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+@OptIn(ExperimentalMaterial3Api::class)
+internal actual val defaultTimePickerLayoutType: TimePickerLayoutType =
+    TimePickerLayoutType.Vertical
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TooltipPopup.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TooltipPopup.desktop.kt
similarity index 100%
rename from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TooltipPopup.desktop.kt
rename to compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TooltipPopup.desktop.kt
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 c79fda6..3c0412e 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
@@ -1479,6 +1479,7 @@
     }
 
     internal fun changesApplied() {
+        createFreshInsertTable()
         providerUpdates.clear()
     }
 
@@ -3517,7 +3518,11 @@
             val insertTable = insertTable
             recordSlotEditingOperation { _, slots, _ ->
                 slots.beginInsert()
-                slots.moveFrom(insertTable, anchor.toIndexFor(insertTable))
+                slots.moveFrom(
+                    table = insertTable,
+                    index = anchor.toIndexFor(insertTable),
+                    removeSourceGroup = false
+                )
                 slots.endInsert()
             }
         } else {
@@ -3533,7 +3538,11 @@
                     }
                 }
                 slots.beginInsert()
-                slots.moveFrom(insertTable, anchor.toIndexFor(insertTable))
+                slots.moveFrom(
+                    table = insertTable,
+                    index = anchor.toIndexFor(insertTable),
+                    removeSourceGroup = false
+                )
                 slots.endInsert()
             }
         }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
index 3ed0e5a2..1a46dc9 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
@@ -1949,7 +1949,8 @@
             fromIndex: Int,
             toWriter: SlotWriter,
             updateFromCursor: Boolean,
-            updateToCursor: Boolean
+            updateToCursor: Boolean,
+            removeSourceGroup: Boolean = true
         ): List<Anchor> {
             val groupsToMove = fromWriter.groupSize(fromIndex)
             val sourceGroupsEnd = fromIndex + groupsToMove
@@ -2057,7 +2058,11 @@
             } else emptyList()
 
             val parentGroup = fromWriter.parent(fromIndex)
-            val anchorsRemoved = if (updateFromCursor) {
+            val anchorsRemoved = if (!removeSourceGroup) {
+                // e.g.: we can skip groups removal for insertTable of Composer because
+                // it's going to be disposed anyway after changes applied
+                false
+            } else if (updateFromCursor) {
                 // Remove the group using the sequence the writer expects when removing a group, that
                 // is the root group and the group's parent group must be correctly started and ended
                 // when it is not a root group.
@@ -2164,7 +2169,7 @@
      *
      * @return a list of the anchors that were moved
      */
-    fun moveFrom(table: SlotTable, index: Int): List<Anchor> {
+    fun moveFrom(table: SlotTable, index: Int, removeSourceGroup: Boolean = true): List<Anchor> {
         runtimeCheck(insertCount > 0)
 
         if (index == 0 && currentGroup == 0 && this.table.groupsSize == 0) {
@@ -2196,7 +2201,8 @@
                 index,
                 this,
                 updateFromCursor = true,
-                updateToCursor = true
+                updateToCursor = true,
+                removeSourceGroup = removeSourceGroup
             )
         }
     }
diff --git a/compose/ui/ui-inspection/OWNERS b/compose/ui/ui-inspection/OWNERS
index 78dae4b..5548ceb 100644
--- a/compose/ui/ui-inspection/OWNERS
+++ b/compose/ui/ui-inspection/OWNERS
@@ -1,4 +1,4 @@
-davidherman@google.com
+# Bug component: 1333602
 jbakermalone@google.com
 jlauridsen@google.com
 sergeyv@google.com
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index e218a96..9c9235b 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -1295,6 +1295,7 @@
   }
 
   @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Alignment {
+    ctor public LineHeightStyle.Alignment(float topRatio);
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Alignment.Companion Companion;
   }
 
diff --git a/compose/ui/ui-text/api/public_plus_experimental_current.txt b/compose/ui/ui-text/api/public_plus_experimental_current.txt
index da4f33e..746202e 100644
--- a/compose/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-text/api/public_plus_experimental_current.txt
@@ -1385,7 +1385,7 @@
   }
 
   @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Alignment {
-    ctor @androidx.compose.ui.text.ExperimentalTextApi public LineHeightStyle.Alignment(float topRatio);
+    ctor public LineHeightStyle.Alignment(float topRatio);
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Alignment.Companion Companion;
   }
 
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index e218a96..9c9235b 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -1295,6 +1295,7 @@
   }
 
   @kotlin.jvm.JvmInline public static final value class LineHeightStyle.Alignment {
+    ctor public LineHeightStyle.Alignment(float topRatio);
     field public static final androidx.compose.ui.text.style.LineHeightStyle.Alignment.Companion Companion;
   }
 
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationIndentationFixTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationIndentationFixTest.kt
index 54aa03d..20fe4e3 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationIndentationFixTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationIndentationFixTest.kt
@@ -65,7 +65,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 22) // b/269193223
+    @SdkSuppress(minSdkVersion = 23) // b/266743243
     @Test
     fun getLineLeftAndGetLineRight_Ltr_TextIndent() {
         val paragraph = paragraph(
@@ -149,7 +149,7 @@
         }
     }
 
-    @SdkSuppress(minSdkVersion = 22) // b/269193223
+    @SdkSuppress(minSdkVersion = 23) // b/266743243
     @Test
     fun getLineLeftAndGetLineRight_Ltr_TextIndent_sp_letterspacing() {
         val paragraph = paragraph(
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
index d657f6a..d86dfa9 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
@@ -215,7 +215,7 @@
         assertThat(brokenLines).isEqualTo(expectedBrokenLines)
     }
 
-    @SdkSuppress(minSdkVersion = 22) // b/269193836
+    @SdkSuppress(minSdkVersion = 23) // b/269193836
     @Test
     fun correct_lineBreak_paragraph_result() {
         val expectedBrokenLines = listOf(
@@ -233,7 +233,7 @@
         assertThat(brokenLines).isEqualTo(expectedBrokenLines)
     }
 
-    @SdkSuppress(minSdkVersion = 22) // b/269193836
+    @SdkSuppress(minSdkVersion = 23) // b/269193836
     @Test
     fun correct_lineBreak_heading_result() {
         val expectedBrokenLines = listOf(
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt
index 6f3ff165..a0f3c2a 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt
@@ -16,66 +16,40 @@
 
 package androidx.compose.ui.text.style
 
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.MultiParagraph
-import androidx.compose.ui.text.TextLayoutInput
-import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.AndroidParagraph
+import androidx.compose.ui.text.Paragraph
 import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.ceilToInt
 import androidx.compose.ui.text.font.createFontFamilyResolver
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.constrain
 import androidx.test.platform.app.InstrumentationRegistry
-import kotlin.math.ceil
 
-@OptIn(ExperimentalTextApi::class)
 open class TextLineBreaker {
-    private val defaultDensity = Density(1f)
     private val context = InstrumentationRegistry.getInstrumentation().context
     private val fontFamilyResolver = createFontFamilyResolver(context)
     private val defaultHyphens = Hyphens.None
     private val defaultLineBreak = LineBreak.Simple
+    private val density = Density(density = 1f)
 
-    private fun constructTextLayoutResult(
+    private fun paragraph(
         text: String,
         textStyle: TextStyle,
         maxWidth: Int = Constraints.Infinity
-    ): TextLayoutResult {
-        val constraints = Constraints(maxWidth = maxWidth)
-
-        val input = TextLayoutInput(
-            text = AnnotatedString(text),
-            style = textStyle,
+    ): Paragraph {
+        return AndroidParagraph(
+            text = text,
+            spanStyles = listOf(),
             placeholders = listOf(),
+            style = textStyle,
             maxLines = Int.MAX_VALUE,
-            softWrap = true,
-            overflow = TextOverflow.Visible,
-            density = defaultDensity,
-            layoutDirection = LayoutDirection.Ltr,
-            fontFamilyResolver = fontFamilyResolver,
-            constraints = constraints
-        )
-
-        val paragraph = MultiParagraph(
-            annotatedString = input.text,
-            style = input.style,
-            constraints = input.constraints,
-            density = input.density,
-            fontFamilyResolver = input.fontFamilyResolver
-        )
-
-        return TextLayoutResult(
-            layoutInput = input,
-            multiParagraph = paragraph,
-            size = constraints.constrain(
-                IntSize(
-                    ceil(paragraph.width).toInt(),
-                    ceil(paragraph.height).toInt()
-                )
-            )
+            ellipsis = false,
+            constraints = Constraints(
+                maxWidth = maxWidth,
+                maxHeight = Float.POSITIVE_INFINITY.ceilToInt()
+            ),
+            density = density,
+            fontFamilyResolver = fontFamilyResolver
         )
     }
 
@@ -85,7 +59,7 @@
         lineBreak: LineBreak = defaultLineBreak,
         maxWidth: Int
     ): List<String> {
-        val layoutResult = constructTextLayoutResult(
+        val layoutResult = paragraph(
             text = text,
             textStyle = TextStyle(hyphens = hyphens, lineBreak = lineBreak),
             maxWidth = maxWidth
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
index 3bcd60e..22913d8 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/platform/AndroidParagraphHelper.android.kt
@@ -85,24 +85,13 @@
         spannableString.setSpan(NoopSpan, 0, text.length)
     }
 
-    if (contextTextStyle.isIncludeFontPaddingEnabled() &&
-        contextTextStyle.lineHeightStyle == null
-    ) {
-        // keep the existing line height behavior for includeFontPadding=true
-        spannableString.setLineHeight(
-            lineHeight = contextTextStyle.lineHeight,
-            contextFontSize = contextFontSize,
-            density = density
-        )
-    } else {
-        val lineHeightStyle = contextTextStyle.lineHeightStyle ?: LineHeightStyle.Default
-        spannableString.setLineHeight(
-            lineHeight = contextTextStyle.lineHeight,
-            lineHeightStyle = lineHeightStyle,
-            contextFontSize = contextFontSize,
-            density = density,
-        )
-    }
+    val lineHeightStyle = contextTextStyle.lineHeightStyle ?: LineHeightStyle.Default
+    spannableString.setLineHeight(
+        lineHeight = contextTextStyle.lineHeight,
+        lineHeightStyle = lineHeightStyle,
+        contextFontSize = contextFontSize,
+        density = density,
+    )
 
     spannableString.setTextIndent(contextTextStyle.textIndent, contextFontSize, density)
 
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 3b316c8..444b076 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
@@ -45,7 +45,6 @@
 import androidx.compose.ui.text.android.style.FontFeatureSpan
 import androidx.compose.ui.text.android.style.LetterSpacingSpanEm
 import androidx.compose.ui.text.android.style.LetterSpacingSpanPx
-import androidx.compose.ui.text.android.style.LineHeightSpan
 import androidx.compose.ui.text.android.style.LineHeightStyleSpan
 import androidx.compose.ui.text.android.style.ShadowSpan
 import androidx.compose.ui.text.android.style.SkewXSpan
@@ -140,22 +139,6 @@
     }
 }
 
-@OptIn(InternalPlatformTextApi::class)
-internal fun Spannable.setLineHeight(
-    lineHeight: TextUnit,
-    contextFontSize: Float,
-    density: Density
-) {
-    val resolvedLineHeight = resolveLineHeightInPx(lineHeight, contextFontSize, density)
-    if (!resolvedLineHeight.isNaN()) {
-        setSpan(
-            span = LineHeightSpan(lineHeight = resolvedLineHeight),
-            start = 0,
-            end = length
-        )
-    }
-}
-
 private fun resolveLineHeightInPx(
     lineHeight: TextUnit,
     contextFontSize: Float,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/EditCommand.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/EditCommand.kt
index eeb8ba6..1b03ee1 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/EditCommand.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/EditCommand.kt
@@ -263,15 +263,15 @@
     }
 
     override fun applyTo(buffer: EditingBuffer) {
-        buffer.delete(
-            buffer.selectionEnd,
-            minOf(buffer.selectionEnd + lengthAfterCursor, buffer.length)
-        )
+        // calculate the end with safe addition since lengthAfterCursor can be set to e.g. Int.MAX
+        // by the input
+        val end = buffer.selectionEnd.addExactOrElse(lengthAfterCursor) { buffer.length }
+        buffer.delete(buffer.selectionEnd, minOf(end, buffer.length))
 
-        buffer.delete(
-            maxOf(0, buffer.selectionStart - lengthBeforeCursor),
-            buffer.selectionStart
-        )
+        // calculate the start with safe subtraction since lengthBeforeCursor can be set to e.g.
+        // Int.MAX by the input
+        val start = buffer.selectionStart.subtractExactOrElse(lengthBeforeCursor) { 0 }
+        buffer.delete(maxOf(0, start), buffer.selectionStart)
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/MathUtils.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/MathUtils.kt
new file mode 100644
index 0000000..68dbd15
--- /dev/null
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/MathUtils.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.ui.text.input
+
+/**
+ * Adds [this] and [right], and if an overflow occurs returns result of [defaultValue].
+ */
+internal inline fun Int.addExactOrElse(right: Int, defaultValue: () -> Int): Int {
+    val result = this + right
+    // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+    return if (this xor result and (right xor result) < 0) defaultValue() else result
+}
+
+/**
+ * Subtracts [right] from [this], and if an overflow occurs returns result of [defaultValue].
+ */
+internal fun Int.subtractExactOrElse(right: Int, defaultValue: () -> Int): Int {
+    val result = this - right
+    // HD 2-12 Overflow iff the arguments have different signs and
+    // the sign of the result is different from the sign of x
+    return if (this xor right and (this xor result) < 0) defaultValue() else result
+}
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 afa4713..e6d44f7 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
@@ -16,7 +16,6 @@
 
 package androidx.compose.ui.text.style
 
-import androidx.compose.ui.text.ExperimentalTextApi
 import androidx.compose.ui.text.PlatformParagraphStyle
 
 /**
@@ -195,7 +194,7 @@
      * between 0f (inclusive) and 1f (inclusive).
      */
     @kotlin.jvm.JvmInline
-    value class Alignment @ExperimentalTextApi constructor(internal val topRatio: Float) {
+    value class Alignment constructor(internal val topRatio: Float) {
 
         init {
             check(topRatio in 0f..1f || topRatio == -1f) {
@@ -235,7 +234,6 @@
              * +--------+
              * </pre>
              */
-            @OptIn(ExperimentalTextApi::class)
             val Top = Alignment(topRatio = 0f)
 
             /**
@@ -256,7 +254,6 @@
              * +--------+
              * </pre>
              */
-            @OptIn(ExperimentalTextApi::class)
             val Center = Alignment(topRatio = 0.5f)
 
             /**
@@ -265,7 +262,6 @@
              * will be distributed as 8 units to top, and 2 units to the bottom of the line. This is
              * the default behavior.
              */
-            @OptIn(ExperimentalTextApi::class)
             val Proportional = Alignment(topRatio = -1f)
 
             /**
@@ -289,7 +285,6 @@
              * +--------+
              * </pre>
              */
-            @OptIn(ExperimentalTextApi::class)
             val Bottom = Alignment(topRatio = 1f)
         }
     }
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextCommandTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextCommandTest.kt
index 713c016..fe3eea8 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextCommandTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextCommandTest.kt
@@ -235,4 +235,66 @@
         }
         assertThat(error).hasMessageThat().contains("-42")
     }
+
+    @Test
+    fun deletes_whenLengthAfterCursorOverflows_withMaxValue() {
+        val text = "abcde"
+        val textAfterDelete = "abcd"
+        val selection = TextRange(textAfterDelete.length)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextCommand(
+            lengthBeforeCursor = 0,
+            lengthAfterCursor = Int.MAX_VALUE
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo(textAfterDelete)
+        assertThat(eb.cursor).isEqualTo(textAfterDelete.length)
+    }
+
+    @Test
+    fun deletes_whenLengthBeforeCursorOverflows_withMaxValue() {
+        val text = "abcde"
+        val selection = TextRange(1)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextCommand(
+            lengthBeforeCursor = Int.MAX_VALUE,
+            lengthAfterCursor = 0
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo("bcde")
+        assertThat(eb.cursor).isEqualTo(0)
+    }
+
+    @Test
+    fun deletes_whenLengthAfterCursorOverflows() {
+        val text = "abcde"
+        val textAfterDelete = "abcd"
+        val selection = TextRange(textAfterDelete.length)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextCommand(
+            lengthBeforeCursor = 0,
+            lengthAfterCursor = Int.MAX_VALUE - 1
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo(textAfterDelete)
+        assertThat(eb.cursor).isEqualTo(textAfterDelete.length)
+    }
+
+    @Test
+    fun deletes_whenLengthBeforeCursorOverflows() {
+        val text = "abcde"
+        val selection = TextRange(1)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextCommand(
+            lengthBeforeCursor = Int.MAX_VALUE - 1,
+            lengthAfterCursor = 0
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo("bcde")
+        assertThat(eb.cursor).isEqualTo(0)
+    }
 }
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextInCodePointsCommandTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextInCodePointsCommandTest.kt
index 0f4d16a..72d1ccf4 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextInCodePointsCommandTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/input/DeleteSurroundingTextInCodePointsCommandTest.kt
@@ -246,4 +246,66 @@
         }
         assertThat(error).hasMessageThat().contains("-42")
     }
+
+    @Test
+    fun deletes_whenLengthAfterCursorOverflows_withMaxValue() {
+        val text = "abcde"
+        val textAfterDelete = "abcd"
+        val selection = TextRange(textAfterDelete.length)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextInCodePointsCommand(
+            lengthBeforeCursor = 0,
+            lengthAfterCursor = Int.MAX_VALUE
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo(textAfterDelete)
+        assertThat(eb.cursor).isEqualTo(textAfterDelete.length)
+    }
+
+    @Test
+    fun deletes_whenLengthBeforeCursorOverflows_withMaxValue() {
+        val text = "abcde"
+        val selection = TextRange(1)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextInCodePointsCommand(
+            lengthBeforeCursor = Int.MAX_VALUE,
+            lengthAfterCursor = 0
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo("bcde")
+        assertThat(eb.cursor).isEqualTo(0)
+    }
+
+    @Test
+    fun deletes_whenLengthAfterCursorOverflows() {
+        val text = "abcde"
+        val textAfterDelete = "abcd"
+        val selection = TextRange(textAfterDelete.length)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextInCodePointsCommand(
+            lengthBeforeCursor = 0,
+            lengthAfterCursor = Int.MAX_VALUE - 1
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo(textAfterDelete)
+        assertThat(eb.cursor).isEqualTo(textAfterDelete.length)
+    }
+
+    @Test
+    fun deletes_whenLengthBeforeCursorOverflows() {
+        val text = "abcde"
+        val selection = TextRange(1)
+        val eb = EditingBuffer(text, selection)
+
+        DeleteSurroundingTextInCodePointsCommand(
+            lengthBeforeCursor = Int.MAX_VALUE - 1,
+            lengthAfterCursor = 0
+        ).applyTo(eb)
+
+        assertThat(eb.toString()).isEqualTo("bcde")
+        assertThat(eb.cursor).isEqualTo(0)
+    }
 }
\ No newline at end of file
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 74cc50f..fb9d0ea 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -2082,6 +2082,7 @@
 
   public abstract static class Placeable.PlacementScope {
     ctor public Placeable.PlacementScope();
+    method public androidx.compose.ui.layout.LayoutCoordinates? getCoordinates();
     method protected abstract androidx.compose.ui.unit.LayoutDirection getParentLayoutDirection();
     method protected abstract int getParentWidth();
     method public final void place(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex);
@@ -2092,6 +2093,7 @@
     method public final void placeRelativeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, long position, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
+    property public androidx.compose.ui.layout.LayoutCoordinates? coordinates;
     property protected abstract androidx.compose.ui.unit.LayoutDirection parentLayoutDirection;
     property protected abstract int parentWidth;
   }
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index f9090fb..d21ed84 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -2259,7 +2259,7 @@
 
   public abstract static class Placeable.PlacementScope {
     ctor public Placeable.PlacementScope();
-    method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.layout.LayoutCoordinates? getCoordinates();
+    method public androidx.compose.ui.layout.LayoutCoordinates? getCoordinates();
     method protected abstract androidx.compose.ui.unit.LayoutDirection getParentLayoutDirection();
     method protected abstract int getParentWidth();
     method public final void place(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex);
@@ -2270,7 +2270,7 @@
     method public final void placeRelativeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, long position, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
-    property @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.layout.LayoutCoordinates? coordinates;
+    property public androidx.compose.ui.layout.LayoutCoordinates? coordinates;
     property protected abstract androidx.compose.ui.unit.LayoutDirection parentLayoutDirection;
     property protected abstract int parentWidth;
   }
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index d34024c..b46c1e6 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -2088,6 +2088,7 @@
 
   public abstract static class Placeable.PlacementScope {
     ctor public Placeable.PlacementScope();
+    method public androidx.compose.ui.layout.LayoutCoordinates? getCoordinates();
     method protected abstract androidx.compose.ui.unit.LayoutDirection getParentLayoutDirection();
     method protected abstract int getParentWidth();
     method public final void place(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex);
@@ -2098,6 +2099,7 @@
     method public final void placeRelativeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, int x, int y, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
     method public final void placeWithLayer(androidx.compose.ui.layout.Placeable, long position, optional float zIndex, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit> layerBlock);
+    property public androidx.compose.ui.layout.LayoutCoordinates? coordinates;
     property protected abstract androidx.compose.ui.unit.LayoutDirection parentLayoutDirection;
     property protected abstract int parentWidth;
   }
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index b76ffed..2b2f069 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -83,7 +83,7 @@
         implementation("androidx.savedstate:savedstate-ktx:1.2.1")
         implementation("androidx.lifecycle:lifecycle-runtime:2.6.1")
         implementation("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
-        implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+        implementation("androidx.profileinstaller:profileinstaller:1.3.0")
         implementation("androidx.emoji2:emoji2:1.2.0")
 
         testImplementation(libs.testRules)
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PlacementScopeCoordinatesSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PlacementScopeCoordinatesSample.kt
index a6f0137..fc5a7d4 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PlacementScopeCoordinatesSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/PlacementScopeCoordinatesSample.kt
@@ -17,7 +17,6 @@
 
 import androidx.annotation.Sampled
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.layout.Layout
@@ -27,7 +26,6 @@
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.round
 
-@OptIn(ExperimentalComposeUiApi::class)
 @Sampled
 @Composable
 fun PlacementScopeCoordinatesSample() {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/GraphicsLayerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/GraphicsLayerTest.kt
index e7627aa..ba80c91 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/GraphicsLayerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/draw/GraphicsLayerTest.kt
@@ -31,6 +31,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.movableContentOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertPixelColor
@@ -90,6 +91,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
 import kotlin.math.ceil
 import kotlin.math.roundToInt
 import org.junit.Assert.assertEquals
@@ -1412,4 +1414,162 @@
             assertEquals(Rect(0f, 0f, 10f, 10f), coordinates.boundsInRoot())
         }
     }
+
+    @Test
+    fun invalidationAfterMovingMovableContentWithLayer() {
+        var moveContent by mutableStateOf(false)
+        var counter by mutableStateOf(0)
+        var counterReadInDrawing = -1
+        val content = movableContentOf {
+            Box(
+                Modifier
+                    .size(5.dp)
+                    .graphicsLayer()
+                    .drawBehind {
+                        counterReadInDrawing = counter
+                    })
+        }
+
+        rule.setContent {
+            if (moveContent) {
+                Box(Modifier.size(5.dp)) {
+                    content()
+                }
+            } else {
+                Box(Modifier.size(10.dp)) {
+                    content()
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            moveContent = true
+        }
+
+        rule.runOnIdle {
+            assertThat(counterReadInDrawing).isEqualTo(counter)
+            counter++
+        }
+
+        rule.runOnIdle {
+            assertThat(counterReadInDrawing).isEqualTo(counter)
+        }
+    }
+
+    @Test
+    fun updatingLayerPropertiesAfterMovingMovableContent() {
+        var moveContent by mutableStateOf(false)
+        var counter by mutableStateOf(0)
+        var counterReadInLayerBlock = -1
+        val content = movableContentOf {
+            Box(
+                Modifier
+                    .size(5.dp)
+                    .graphicsLayer {
+                        counterReadInLayerBlock = counter
+                    }
+            )
+        }
+
+        rule.setContent {
+            if (moveContent) {
+                Box(Modifier.size(5.dp)) {
+                    content()
+                }
+            } else {
+                Box(Modifier.size(10.dp)) {
+                    content()
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            moveContent = true
+        }
+
+        rule.runOnIdle {
+            assertThat(counterReadInLayerBlock).isEqualTo(counter)
+            counter++
+        }
+
+        rule.runOnIdle {
+            assertThat(counterReadInLayerBlock).isEqualTo(counter)
+        }
+    }
+
+    @Test
+    fun updatingValueIsNotCausingRemeasureOrRelayout() {
+        var translationX by mutableStateOf(0f)
+        lateinit var coordinates: LayoutCoordinates
+        var remeasureCount = 0
+        var relayoutCount = 0
+        val layoutModifier = Modifier.layout { measurable, constraints ->
+            val placeable = measurable.measure(constraints)
+            remeasureCount++
+            layout(placeable.width, placeable.height) {
+                relayoutCount++
+                placeable.place(0, 0)
+            }
+        }
+        rule.setContent {
+            Box(Modifier.graphicsLayer(translationX = translationX).then(layoutModifier)) {
+                Layout(Modifier.onGloballyPositioned { coordinates = it }) { _, _ ->
+                    layout(10, 10) {}
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(0f, coordinates.boundsInRoot().left)
+            // reset counters
+            remeasureCount = 0
+            relayoutCount = 0
+            // update translation
+            translationX = 10f
+        }
+
+        rule.runOnIdle {
+            assertEquals(10f, coordinates.boundsInRoot().left)
+            assertEquals(0, remeasureCount)
+            assertEquals(0, relayoutCount)
+        }
+    }
+
+    @Test
+    fun updatingLambdaIsNotCausingRemeasureOrRelayout() {
+        var lambda by mutableStateOf<GraphicsLayerScope.() -> Unit>({})
+        lateinit var coordinates: LayoutCoordinates
+        var remeasureCount = 0
+        var relayoutCount = 0
+        val layoutModifier = Modifier.layout { measurable, constraints ->
+            val placeable = measurable.measure(constraints)
+            remeasureCount++
+            layout(placeable.width, placeable.height) {
+                relayoutCount++
+                placeable.place(0, 0)
+            }
+        }
+        rule.setContent {
+            Box(Modifier.graphicsLayer(lambda).then(layoutModifier)) {
+                Layout(Modifier.onGloballyPositioned { coordinates = it }) { _, _ ->
+                    layout(10, 10) {}
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(0f, coordinates.boundsInRoot().left)
+            // reset counters
+            remeasureCount = 0
+            relayoutCount = 0
+            // update lambda
+            lambda = { translationX = 10f }
+        }
+
+        rule.runOnIdle {
+            assertEquals(10f, coordinates.boundsInRoot().left)
+            assertEquals(0, remeasureCount)
+            assertEquals(0, relayoutCount)
+        }
+    }
 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacementLayoutCoordinatesTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacementLayoutCoordinatesTest.kt
index b048f0e..f655381 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacementLayoutCoordinatesTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacementLayoutCoordinatesTest.kt
@@ -58,7 +58,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 
-@OptIn(ExperimentalComposeUiApi::class)
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class PlacementLayoutCoordinatesTest {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalModifierNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalModifierNodeTest.kt
index c11ac21..897ab66 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalModifierNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/CompositionLocalModifierNodeTest.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.node
 
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.ReusableContent
 import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -186,6 +187,80 @@
         }
     }
 
+    // Regression test for b/271875799
+    @Test
+    fun compositionLocalsUpdateWhenContentMoves() {
+        var readValue = -1
+        var providedValue by mutableStateOf(42)
+
+        var contentKey by mutableStateOf(1)
+        val modifier = modifierNodeElementOf {
+            object : Modifier.Node(), DrawModifierNode,
+                CompositionLocalConsumerModifierNode {
+                override fun ContentDrawScope.draw() {
+                    readValue = currentValueOf(localInt)
+                    drawContent()
+                }
+            }
+        }
+
+        rule.setContent {
+            CompositionLocalProvider(localInt provides providedValue) {
+                ReusableContent(contentKey) {
+                    Layout(modifier, EmptyBoxMeasurePolicy)
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(readValue).isEqualTo(42)
+        }
+
+        contentKey++
+        providedValue = 86
+
+        rule.runOnIdle {
+            assertThat(readValue).isEqualTo(86)
+        }
+    }
+
+    // Regression test for b/271875799
+    @Test
+    fun staticCompositionLocalsUpdateWhenContentMoves() {
+        var readValue = -1
+        var providedValue by mutableStateOf(32)
+
+        var contentKey by mutableStateOf(1)
+        val modifier = modifierNodeElementOf {
+            object : Modifier.Node(), DrawModifierNode,
+                CompositionLocalConsumerModifierNode {
+                override fun ContentDrawScope.draw() {
+                    readValue = currentValueOf(staticLocalInt)
+                    drawContent()
+                }
+            }
+        }
+
+        rule.setContent {
+            CompositionLocalProvider(staticLocalInt provides providedValue) {
+                ReusableContent(contentKey) {
+                    Layout(modifier, EmptyBoxMeasurePolicy)
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(readValue).isEqualTo(32)
+        }
+
+        contentKey++
+        providedValue = 64
+
+        rule.runOnIdle {
+            assertThat(readValue).isEqualTo(64)
+        }
+    }
+
     private inline fun <reified T : Modifier.Node> modifierNodeElementOf(
         crossinline create: () -> T
     ): ModifierNodeElement<T> = object : ModifierNodeElement<T>() {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
index 4bcf007..773cc2e 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
@@ -556,17 +556,17 @@
     ): Comparator<SemanticsNode> {
         // First compare the coordinates LTR
         var comparator = compareBy<SemanticsNode>(
-            { it.layoutNode.coordinates.boundsInWindow().left },
-            { it.layoutNode.coordinates.boundsInWindow().top },
-            { it.layoutNode.coordinates.boundsInWindow().bottom },
-            { it.layoutNode.coordinates.boundsInWindow().right })
+            { it.boundsInWindow.left },
+            { it.boundsInWindow.top },
+            { it.boundsInWindow.bottom },
+            { it.boundsInWindow.right })
         // Modify comparison if we're not using LTR comparison strategy to use RTL instead
         if (layoutIsRtl) {
             comparator = compareBy(
-                { it.layoutNode.coordinates.boundsInWindow().right },
-                { it.layoutNode.coordinates.boundsInWindow().top },
-                { it.layoutNode.coordinates.boundsInWindow().bottom },
-                { it.layoutNode.coordinates.boundsInWindow().left })
+                { it.boundsInWindow.right },
+                { it.boundsInWindow.top },
+                { it.boundsInWindow.bottom },
+                { it.boundsInWindow.left })
         }
         return comparator
             // then compare by layoutNode's zIndex and placement order
@@ -600,8 +600,8 @@
             node: SemanticsNode
         ): Boolean {
             // Conversion to long is needed in order to utilize `until`, which has no float ver
-            val entryTopCoord = node.layoutNode.coordinates.boundsInWindow().top
-            val entryBottomCoord = node.layoutNode.coordinates.boundsInWindow().bottom
+            val entryTopCoord = node.boundsInWindow.top
+            val entryBottomCoord = node.boundsInWindow.bottom
             val entryRange = entryTopCoord.rangeUntil(entryBottomCoord)
 
             for (currIndex in 0..rowGroupings.lastIndex) {
@@ -635,7 +635,7 @@
             val currEntry = parentListToSort[entryIndex]
             // If this is the first entry, or vertical groups don't overlap
             if (entryIndex == 0 || !placedEntryRowOverlaps(currEntry)) {
-                val newRect = currEntry.layoutNode.coordinates.boundsInWindow()
+                val newRect = currEntry.boundsInWindow
                 rowGroupings.add(Pair(newRect, mutableListOf(currEntry)))
             } // otherwise, we've already iterated through, found and placed it in a matching group
         }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
index cc534a5..ba495f2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/GraphicsLayerModifier.kt
@@ -399,6 +399,12 @@
     val spotShadowColor: Color,
     val compositingStrategy: CompositingStrategy
 ) : ModifierNodeElement<SimpleGraphicsLayerModifier>() {
+
+    /**
+     * [SimpleGraphicsLayerModifier.invalidateLayerBlock] is doing the manual invalidation.
+     */
+    override val autoInvalidate = false
+
     override fun create(): SimpleGraphicsLayerModifier {
         return SimpleGraphicsLayerModifier(
             scaleX = scaleX,
@@ -543,10 +549,18 @@
 private data class BlockGraphicsLayerElement(
     val block: GraphicsLayerScope.() -> Unit
 ) : ModifierNodeElement<BlockGraphicsLayerModifier>() {
+
+    /**
+     * We can skip remeasuring as we only need to rerun the placement block. we request it
+     * manually in the [update] block.
+     */
+    override val autoInvalidate = false
+
     override fun create() = BlockGraphicsLayerModifier(block)
 
     override fun update(node: BlockGraphicsLayerModifier) = node.apply {
         layerBlock = block
+        invalidateLayerBlock()
     }
 
     override fun InspectorInfo.inspectableProperties() {
@@ -559,6 +573,13 @@
     var layerBlock: GraphicsLayerScope.() -> Unit,
 ) : LayoutModifierNode, Modifier.Node() {
 
+    fun invalidateLayerBlock() {
+        requireCoordinator(Nodes.Layout).wrapped?.updateLayerBlock(
+            layerBlock,
+            forceUpdateLayerParameters = true
+        )
+    }
+
     override fun MeasureScope.measure(
         measurable: Measurable,
         constraints: Constraints
@@ -617,7 +638,7 @@
     fun invalidateLayerBlock() {
         requireCoordinator(Nodes.Layout).wrapped?.updateLayerBlock(
             this.layerBlock,
-            forceLayerInvalidated = true
+            forceUpdateLayerParameters = true
         )
     }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/Placeable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/Placeable.kt
index f2f70d3..99301bd 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/Placeable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/Placeable.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.ui.layout
 
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.graphics.GraphicsLayerScope
 import androidx.compose.ui.node.LayoutNodeLayoutDelegate
 import androidx.compose.ui.node.NodeCoordinator
@@ -161,9 +160,6 @@
          *
          * @sample androidx.compose.ui.samples.PlacementScopeCoordinatesSample
          */
-        @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-        @ExperimentalComposeUiApi
-        @get:ExperimentalComposeUiApi
         open val coordinates: LayoutCoordinates?
             get() = null
 
@@ -342,7 +338,6 @@
                 private set
             private var _coordinates: LayoutCoordinates? = null
 
-            @ExperimentalComposeUiApi
             override val coordinates: LayoutCoordinates?
                 get() {
                     layoutDelegate?.coordinatesAccessedDuringPlacement = true
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 6ca357e..a7a67f3 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
@@ -463,7 +463,7 @@
         // Update lookahead root when attached. For nested cases, we'll always use the
         // closest lookahead root
         updateLookaheadRoot()
-        nodes.attach(performInvalidations = false)
+        nodes.attach()
         _foldedChildren.forEach { child ->
             child.attach(owner)
         }
@@ -684,7 +684,12 @@
             viewConfiguration = value[LocalViewConfiguration]
             @OptIn(ExperimentalComposeUiApi::class)
             nodes.headToTail(Nodes.CompositionLocalConsumer) { modifierNode ->
-                autoInvalidateUpdatedNode(modifierNode as Modifier.Node)
+                val delegatedNode = modifierNode.node
+                if (delegatedNode.isAttached) {
+                    autoInvalidateUpdatedNode(delegatedNode)
+                } else {
+                    delegatedNode.updatedNodeAwaitingAttachForInvalidation = true
+                }
             }
         }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeLayoutDelegate.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeLayoutDelegate.kt
index 64a3e9b..368a34c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeLayoutDelegate.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeLayoutDelegate.kt
@@ -364,10 +364,7 @@
                 check(
                     measuredByParent == LayoutNode.UsageByParent.NotUsed ||
                         @Suppress("DEPRECATION") canMultiMeasure
-                ) {
-                    "measure() may not be called multiple times on the same Measurable. Current " +
-                        "state $measuredByParent. Parent state ${parent.layoutState}."
-                }
+                ) { MeasuredTwiceErrorMessage }
                 measuredByParent = when (parent.layoutState) {
                     LayoutState.Measuring ->
                         LayoutNode.UsageByParent.InMeasureBlock
@@ -829,10 +826,7 @@
                 check(
                     measuredByParentInLookahead == LayoutNode.UsageByParent.NotUsed ||
                         @Suppress("DEPRECATION") canMultiMeasure
-                ) {
-                    "measure() may not be called multiple times on the same Measurable. Current " +
-                        "state $measuredByParentInLookahead. Parent state ${parent.layoutState}."
-                }
+                ) { MeasuredTwiceErrorMessage }
                 measuredByParentInLookahead = when (parent.layoutState) {
                     LayoutState.LookaheadMeasuring, LayoutState.Measuring ->
                         LayoutNode.UsageByParent.InMeasureBlock
@@ -1174,6 +1168,12 @@
     )
 }
 
+private val MeasuredTwiceErrorMessage: String =
+    "measure() may not be called multiple times on the same Measurable. If you want to " +
+        "get the content size of the Measurable before calculating the final constraints, " +
+        "please use methods like minIntrinsicWidth()/maxIntrinsicWidth() and " +
+        "minIntrinsicHeight()/maxIntrinsicHeight()"
+
 /**
  * AlignmentLinesOwner defines APIs that are needed to respond to alignment line changes, and to
  * query alignment line related info.
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
index e6eeda9..5684882 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
@@ -213,7 +213,7 @@
             syncCoordinators()
         }
         if (attachNeeded && layoutNode.isAttached) {
-            attach(performInvalidations = true)
+            attach()
         }
     }
 
@@ -264,17 +264,15 @@
         outerCoordinator = coordinator
     }
 
-    fun attach(performInvalidations: Boolean) {
+    fun attach() {
         headToTail {
             if (!it.isAttached) {
                 it.attach()
-                if (performInvalidations) {
-                    if (it.insertedNodeAwaitingAttachForInvalidation) {
-                        autoInvalidateInsertedNode(it)
-                    }
-                    if (it.updatedNodeAwaitingAttachForInvalidation) {
-                        autoInvalidateUpdatedNode(it)
-                    }
+                if (it.insertedNodeAwaitingAttachForInvalidation) {
+                    autoInvalidateInsertedNode(it)
+                }
+                if (it.updatedNodeAwaitingAttachForInvalidation) {
+                    autoInvalidateUpdatedNode(it)
                 }
                 // when we attach with performInvalidations == false no separate
                 // invalidations needed as the whole LayoutNode is attached to the tree.
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 9bdb4f2..cceff4d 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
@@ -221,12 +221,12 @@
         } else {
             wrappedBy?.invalidateLayer()
         }
-        layoutNode.owner?.onLayoutChange(layoutNode)
         measuredSize = IntSize(width, height)
-        graphicsLayerScope.size = measuredSize.toSize()
+        updateLayerParameters(invokeOnLayoutChange = false)
         visitNodes(Nodes.Draw) {
             it.onMeasureResultChanged()
         }
+        layoutNode.owner?.onLayoutChange(layoutNode)
     }
 
     override var position: IntOffset = IntOffset.Zero
@@ -308,7 +308,7 @@
         zIndex: Float,
         layerBlock: (GraphicsLayerScope.() -> Unit)?
     ) {
-        onLayerBlockUpdated(layerBlock)
+        updateLayerBlock(layerBlock)
         if (this.position != position) {
             this.position = position
             layoutNode.layoutDelegate.measurePassDelegate
@@ -380,20 +380,11 @@
 
     fun updateLayerBlock(
         layerBlock: (GraphicsLayerScope.() -> Unit)?,
-        forceLayerInvalidated: Boolean = false
+        forceUpdateLayerParameters: Boolean = false
     ) {
-        val layerInvalidated = this.layerBlock !== layerBlock || forceLayerInvalidated
-        this.layerBlock = layerBlock
-        onLayerBlockUpdated(layerBlock, forceLayerInvalidated = layerInvalidated)
-    }
-
-    private fun onLayerBlockUpdated(
-        layerBlock: (GraphicsLayerScope.() -> Unit)?,
-        forceLayerInvalidated: Boolean = false
-    ) {
-        val layerInvalidated = this.layerBlock !== layerBlock || layerDensity != layoutNode
+        val updateParameters = this.layerBlock !== layerBlock || layerDensity != layoutNode
             .density || layerLayoutDirection != layoutNode.layoutDirection ||
-            forceLayerInvalidated
+            forceUpdateLayerParameters
         this.layerBlock = layerBlock
         this.layerDensity = layoutNode.density
         this.layerLayoutDirection = layoutNode.layoutDirection
@@ -410,7 +401,7 @@
                 updateLayerParameters()
                 layoutNode.innerLayerCoordinatorIsDirty = true
                 invalidateParentLayer()
-            } else if (layerInvalidated) {
+            } else if (updateParameters) {
                 updateLayerParameters()
             }
         } else {
@@ -427,7 +418,7 @@
         }
     }
 
-    private fun updateLayerParameters() {
+    private fun updateLayerParameters(invokeOnLayoutChange: Boolean = true) {
         val layer = layer
         if (layer != null) {
             val layerBlock = requireNotNull(layerBlock)
@@ -462,11 +453,13 @@
                 density = layoutNode.density
             )
             isClipping = graphicsLayerScope.clip
+            lastLayerAlpha = graphicsLayerScope.alpha
+            if (invokeOnLayoutChange) {
+                layoutNode.owner?.onLayoutChange(layoutNode)
+            }
         } else {
             require(layerBlock == null)
         }
-        lastLayerAlpha = graphicsLayerScope.alpha
-        layoutNode.owner?.onLayoutChange(layoutNode)
     }
 
     private val invalidateParentLayer: () -> Unit = {
@@ -906,7 +899,10 @@
      * attached to the [Owner].
      */
     fun onLayoutNodeAttach() {
-        onLayerBlockUpdated(layerBlock)
+        // this call will update the parameters of the layer (alpha, scale, etc)
+        updateLayerBlock(layerBlock, forceUpdateLayerParameters = true)
+        // this call will invalidate the content of the layer
+        layer?.invalidate()
     }
 
     /**
@@ -916,7 +912,7 @@
     fun onRelease() {
         released = true
         if (layer != null) {
-            onLayerBlockUpdated(null)
+            updateLayerBlock(null)
         }
     }
 
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
index 935adbe..f03ec69 100644
--- a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
+++ b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/AllDemos.kt
@@ -53,7 +53,8 @@
 val AllComposeConstraintLayoutDemos: List<ComposeDemo> =
     listOf(
         ComposeDemo("CustomColorInKeyAttributes") { CustomColorInKeyAttributesDemo() },
-        ComposeDemo("SimpleOnSwipe") { SimpleOnSwipe() },
+        ComposeDemo("Simple OnSwipe") { SimpleOnSwipe() },
+        ComposeDemo("Multiple OnSwipe") { MultiSwipeDsl() },
         ComposeDemo("AnimatedChainOrientation") { ChainsAnimatedOrientationDemo() },
         ComposeDemo("CollapsibleToolbar w/ Column") { ToolBarDslDemo() },
         ComposeDemo("CollapsibleToolbar w/ LazyColumn") { ToolBarLazyDslDemo() },
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/OnSwipeDemos.kt b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/OnSwipeDemos.kt
index 8fdbe10..d3f65d8 100644
--- a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/OnSwipeDemos.kt
+++ b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/OnSwipeDemos.kt
@@ -25,20 +25,33 @@
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.Button
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+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.graphics.Color
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
+import androidx.constraintlayout.compose.Dimension
 import androidx.constraintlayout.compose.ExperimentalMotionApi
 import androidx.constraintlayout.compose.MotionLayout
 import androidx.constraintlayout.compose.MotionLayoutDebugFlags
 import androidx.constraintlayout.compose.MotionScene
+import androidx.constraintlayout.compose.OnSwipe
+import androidx.constraintlayout.compose.SwipeDirection
+import androidx.constraintlayout.compose.SwipeMode
+import androidx.constraintlayout.compose.SwipeSide
+import androidx.constraintlayout.compose.SwipeTouchUp
 import androidx.constraintlayout.compose.layoutId
 import androidx.constraintlayout.compose.rememberMotionLayoutState
 
@@ -155,4 +168,137 @@
         }
         Text(text = "Current progress: ${motionLayoutState.currentProgress}")
     }
+}
+
+@Preview
+@Composable
+fun MultiSwipeDsl() {
+    val modes = remember { arrayOf(SwipeMode.Velocity, SwipeMode.Spring) }
+    val touchUps = remember {
+        arrayOf(
+            SwipeTouchUp.AutoComplete,
+            SwipeTouchUp.ToStart,
+            SwipeTouchUp.ToEnd,
+            SwipeTouchUp.Stop,
+            SwipeTouchUp.Decelerate,
+            SwipeTouchUp.NeverCompleteStart,
+            SwipeTouchUp.NeverCompleteEnd,
+        )
+    }
+    val endWidth = arrayOf(50, 200)
+    val simpleSwipeConfigs = remember {
+        val configCombinations = mutableListOf<SimpleSwipeConfig>()
+        touchUps.forEach { touchUp ->
+            endWidth.forEach { width ->
+                modes.forEach { mode ->
+                    configCombinations.add(
+                        SimpleSwipeConfig(
+                            mode,
+                            width,
+                            touchUp
+                        )
+                    )
+                }
+            }
+        }
+        return@remember configCombinations
+    }
+    Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
+        simpleSwipeConfigs.forEach { config ->
+            Box(
+                modifier = Modifier
+                    .height(20.dp)
+                    .fillMaxWidth()
+                    .background(Color.LightGray)
+            )
+            SimpleSwipeDsl(config)
+        }
+    }
+}
+
+@Stable
+@Immutable
+private data class SimpleSwipeConfig(
+    val mode: SwipeMode,
+    val endWidth: Int,
+    val touchUp: SwipeTouchUp
+)
+
+@Composable
+private fun SimpleSwipeDsl(config: SimpleSwipeConfig) {
+    val mode = config.mode
+    val endWidth = config.endWidth
+    val touchUp = config.touchUp
+    val titleText = "(${mode.name} $endWidth ${touchUp.name})"
+
+    MotionLayout(
+        modifier = Modifier
+            .height(70.dp)
+            .fillMaxWidth()
+            .background(Color.White),
+        motionScene = MotionScene {
+            val title = createRefFor("title")
+            val box = createRefFor("box")
+
+            val from = constraintSet {
+                constrain(title) {
+                    width = Dimension.wrapContent
+                    height = Dimension.value(50.dp)
+                    centerTo(parent)
+                    customFloat("mValue", 0.0f)
+                    customColor("back", Color(0xffffffff))
+                }
+                constrain(box) {
+                    width = Dimension.value(50.dp)
+                    height = Dimension.value(50.dp)
+                    bottom.linkTo(parent.bottom)
+                    top.linkTo(parent.top)
+                    start.linkTo(parent.start, 70.dp)
+                    rotationZ = 0f
+                    customColor("boxColor", Color(0xff00ffff))
+                }
+            }
+            val to = constraintSet(extendConstraintSet = from) {
+                constrain(title) {
+                    customFloat("mValue", 100.0f)
+                    customColor("back", Color(0xffFF88FF))
+                }
+                constrain(box) {
+                    width = Dimension.value(endWidth.dp)
+                    clearHorizontal()
+                    end.linkTo(parent.end, 70.dp)
+                    rotationZ = 360f
+                    customColor("boxColor", Color(0xFF00FF00))
+                }
+            }
+            defaultTransition(
+                from = from,
+                to = to
+            ) {
+                onSwipe = OnSwipe(
+                    anchor = box,
+                    direction = SwipeDirection.Right,
+                    side = SwipeSide.Left,
+                    mode = mode,
+                    onTouchUp = touchUp
+                )
+            }
+        }
+    ) {
+        val progress = customFloat("title", "mValue")
+        val textBackColor = customColor("title", "back")
+
+        Text(
+            text = "$titleText  $progress",
+            modifier = Modifier
+                .layoutId("title")
+                .background(textBackColor),
+            textAlign = TextAlign.Center
+        )
+        Box(
+            modifier = Modifier
+                .background(customProperties("box").color("boxColor"))
+                .layoutId("box")
+        )
+    }
 }
\ No newline at end of file
diff --git a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/PuzzleDemo.kt b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/PuzzleDemo.kt
index 42be16c..f5d5cc4 100644
--- a/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/PuzzleDemo.kt
+++ b/constraintlayout/constraintlayout-compose/integration-tests/demos/src/main/java/androidx/constraintlayout/compose/demos/PuzzleDemo.kt
@@ -34,7 +34,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.drawscope.clipRect
-import androidx.compose.ui.graphics.drawscope.withTransform
+import androidx.compose.ui.graphics.drawscope.translate
 import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.rememberVectorPainter
 import androidx.compose.ui.layout.layoutId
@@ -173,15 +173,12 @@
 ) {
     Canvas(modifier.fillMaxSize()) {
         clipRect {
-            withTransform({
-                scale(scaleY = gridSize.toFloat(), scaleX = gridSize.toFloat())
-                translate(
-                    left = -(x - gridSize / 2) * size.width / gridSize,
-                    top = -(y - gridSize / 2) * size.height / gridSize
-                )
-            }) {
+            translate(
+                left = -x * size.width,
+                top = -y * size.height
+            ) {
                 with(painter) {
-                    draw(size)
+                    draw(size.times(gridSize.toFloat()))
                 }
             }
         }
diff --git a/constraintlayout/constraintlayout-compose/src/androidAndroidTest/kotlin/androidx/constraintlayout/compose/MotionLayoutTest.kt b/constraintlayout/constraintlayout-compose/src/androidAndroidTest/kotlin/androidx/constraintlayout/compose/MotionLayoutTest.kt
index 9ccf8d8..4ae97ba 100644
--- a/constraintlayout/constraintlayout-compose/src/androidAndroidTest/kotlin/androidx/constraintlayout/compose/MotionLayoutTest.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidAndroidTest/kotlin/androidx/constraintlayout/compose/MotionLayoutTest.kt
@@ -54,6 +54,7 @@
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.text.PlatformTextStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontWeight
@@ -502,11 +503,13 @@
 @Composable
 private fun CustomTextSize(modifier: Modifier, progress: Float) {
     val context = LocalContext.current
+    @Suppress("DEPRECATION")
     CompositionLocalProvider(
         LocalDensity provides Density(1f, 1f),
         LocalTextStyle provides TextStyle(
             fontFamily = FontFamily.Monospace,
-            fontWeight = FontWeight.Normal
+            fontWeight = FontWeight.Normal,
+            platformStyle = PlatformTextStyle(includeFontPadding = true)
         )
     ) {
         MotionLayout(
diff --git a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/motion/utils/StopLogicEngine.java b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/motion/utils/StopLogicEngine.java
index 621fce0..0982b43 100644
--- a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/motion/utils/StopLogicEngine.java
+++ b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/motion/utils/StopLogicEngine.java
@@ -179,10 +179,10 @@
     private void setup(float velocity, float distance, float maxAcceleration, float maxVelocity,
             float maxTime) {
         mDone = false;
+        mStage3EndPosition = distance;
         if (velocity == 0) {
             velocity = 0.0001f;
         }
-        this.mStage1Velocity = velocity;
         float min_time_to_stop = velocity / maxAcceleration;
         float stopDistance = min_time_to_stop * velocity / 2;
 
diff --git a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/Transition.java b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/Transition.java
index 877cafd..3bbe216 100644
--- a/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/Transition.java
+++ b/constraintlayout/constraintlayout-core/src/main/java/androidx/constraintlayout/core/state/Transition.java
@@ -280,9 +280,17 @@
             float rest = currentPosition + 0.5f * Math.abs(velocity) * velocity / mMaxAcceleration;
             switch (mOnTouchUp) {
                 case ON_UP_AUTOCOMPLETE_TO_START:
+                    if (currentPosition >= 1f) {
+                        return 1;
+                    }
+                    return 0;
                 case ON_UP_NEVER_COMPLETE_TO_END:
                     return 0;
                 case ON_UP_AUTOCOMPLETE_TO_END:
+                    if (currentPosition <= 0f) {
+                        return 0;
+                    }
+                    return 1;
                 case ON_UP_NEVER_COMPLETE_TO_START:
                     return 1;
                 case ON_UP_STOP:
@@ -309,7 +317,14 @@
 
         void config(float position, float velocity, long start, float duration) {
             mStart = start;
+            if (Math.abs(velocity) > mMaxVelocity) {
+                velocity = mMaxVelocity * Math.signum(velocity);
+            }
             mDestination = getDestinationPosition(position, velocity, duration);
+            if (mDestination == position) {
+                mEngine = null;
+                return;
+            }
             if ((mOnTouchUp == ON_UP_DECELERATE)
                     && (mAutoCompleteMode == MODE_CONTINUOUS_VELOCITY)) {
                 StopLogicEngine.Decelerate sld;
@@ -381,7 +396,7 @@
             if (mOnTouchUp == ON_UP_STOP) {
                 return false;
             }
-            return !mEngine.isStopped();
+            return mEngine != null && !mEngine.isStopped();
         }
     }
 
diff --git a/constraintlayout/constraintlayout/build.gradle b/constraintlayout/constraintlayout/build.gradle
index 894dfc7..060d756 100644
--- a/constraintlayout/constraintlayout/build.gradle
+++ b/constraintlayout/constraintlayout/build.gradle
@@ -26,7 +26,7 @@
     implementation("androidx.appcompat:appcompat:1.2.0")
     implementation("androidx.core:core:1.3.2")
     implementation(project(":constraintlayout:constraintlayout-core"))
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     testImplementation(libs.junit)
 
diff --git a/coordinatorlayout/OWNERS b/coordinatorlayout/OWNERS
new file mode 100644
index 0000000..347e71c
--- /dev/null
+++ b/coordinatorlayout/OWNERS
@@ -0,0 +1,2 @@
+aelias@google.com
+ryanmentley@google.com
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 124fa91..355b4f0 100644
--- a/core/core/src/main/java/androidx/core/app/NotificationCompat.java
+++ b/core/core/src/main/java/androidx/core/app/NotificationCompat.java
@@ -4280,12 +4280,14 @@
              * where the platform doesn't support the MIME type, the original text provided in the
              * constructor will be used.
              *
-             * @param dataMimeType The MIME type of the content
+             * @param dataMimeType The MIME type of the content. See
+             * {@link android.graphics.ImageDecoder#isMimeTypeSupported(String)}
+             * for a list of supported image MIME types.
              * @param dataUri The uri containing the content whose type is given by the MIME type.
              * <p class="note">
+             * Notification Listeners including the System UI need permission to access the
+             * data the Uri points to. The recommended ways to do this are:
              * <ol>
-             *   <li>Notification Listeners including the System UI need permission to access the
-             *       data the Uri points to. The recommended ways to do this are:</li>
              *   <li>Store the data in your own ContentProvider, making sure that other apps have
              *       the correct permission to access your provider. The preferred mechanism for
              *       providing access is to use per-URI permissions which are temporary and only
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoJavaTest.java b/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoJavaTest.java
index 4d0a31a..40acdb0 100644
--- a/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoJavaTest.java
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoJavaTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertThrows;
 
 import android.content.Context;
+import android.graphics.drawable.Icon;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
@@ -77,6 +78,25 @@
         assertThat(displayInfo.getUserId()).isEqualTo(expectedUserId);
         assertThat(displayInfo.getUserDisplayName()).isEqualTo(expectedDisplayName);
         assertThat(displayInfo.getCredentialTypeIcon()).isNull();
+        assertThat(displayInfo.getDefaultProvider()).isNull();
+    }
+
+    @SdkSuppress(minSdkVersion = 28)
+    @Test
+    public void constructWithOptionalParameters_success() {
+        CharSequence expectedUserId = "userId";
+        CharSequence expectedDisplayName = "displayName";
+        Icon expectedIcon = Icon.createWithResource(mContext, R.drawable.ic_passkey);
+        String expectedDefaultProvider = "defaultProvider";
+
+        CreateCredentialRequest.DisplayInfo displayInfo =
+                new CreateCredentialRequest.DisplayInfo(expectedUserId,
+                        expectedDisplayName, expectedIcon, expectedDefaultProvider);
+
+        assertThat(displayInfo.getUserId()).isEqualTo(expectedUserId);
+        assertThat(displayInfo.getUserDisplayName()).isEqualTo(expectedDisplayName);
+        assertThat(displayInfo.getCredentialTypeIcon()).isEqualTo(expectedIcon);
+        assertThat(displayInfo.getDefaultProvider()).isEqualTo(expectedDefaultProvider);
     }
 
     @SdkSuppress(minSdkVersion = 28)
@@ -95,5 +115,6 @@
         assertThat(displayInfo.getUserDisplayName()).isNull();
         assertThat(displayInfo.getCredentialTypeIcon().getResId()).isEqualTo(
                 R.drawable.ic_password);
+        assertThat(displayInfo.getDefaultProvider()).isNull();
     }
 }
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoTest.kt b/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoTest.kt
index 2fb3e1d..bfde3e9 100644
--- a/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoTest.kt
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/CreateCredentialRequestDisplayInfoTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.credentials
 
+import android.graphics.drawable.Icon
 import androidx.credentials.CreateCredentialRequest.DisplayInfo
 import androidx.credentials.CreateCredentialRequest.DisplayInfo.Companion.parseFromCredentialDataBundle
 import androidx.credentials.internal.FrameworkImplHelper.Companion.getFinalCreateCredentialData
@@ -54,8 +55,8 @@
 
     @Test
     fun constructWithUserIdAndDisplayName_success() {
-        val expectedUserId = "userId"
-        val expectedDisplayName = "displayName"
+        val expectedUserId: CharSequence = "userId"
+        val expectedDisplayName: CharSequence = "displayName"
 
         val displayInfo = DisplayInfo(
             expectedUserId,
@@ -65,6 +66,26 @@
         assertThat(displayInfo.userId).isEqualTo(expectedUserId)
         assertThat(displayInfo.userDisplayName).isEqualTo(expectedDisplayName)
         assertThat(displayInfo.credentialTypeIcon).isNull()
+        assertThat(displayInfo.defaultProvider).isNull()
+    }
+
+    @SdkSuppress(minSdkVersion = 28)
+    @Test
+    fun constructWithOptionalParameters_success() {
+        val expectedUserId: CharSequence = "userId"
+        val expectedDisplayName: CharSequence = "displayName"
+        val expectedIcon = Icon.createWithResource(mContext, R.drawable.ic_passkey)
+        val expectedDefaultProvider = "defaultProvider"
+
+        val displayInfo = DisplayInfo(
+            expectedUserId,
+            expectedDisplayName, expectedIcon, expectedDefaultProvider
+        )
+
+        assertThat(displayInfo.userId).isEqualTo(expectedUserId)
+        assertThat(displayInfo.userDisplayName).isEqualTo(expectedDisplayName)
+        assertThat(displayInfo.credentialTypeIcon).isEqualTo(expectedIcon)
+        assertThat(displayInfo.defaultProvider).isEqualTo(expectedDefaultProvider)
     }
 
     @SdkSuppress(minSdkVersion = 28)
@@ -84,5 +105,6 @@
         assertThat(displayInfo.credentialTypeIcon?.resId).isEqualTo(
             R.drawable.ic_password
         )
+        assertThat(displayInfo.defaultProvider).isNull()
     }
 }
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt
index 4334cc0..10c6a67 100644
--- a/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt
+++ b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt
@@ -67,13 +67,15 @@
      * @property userId the user identifier of the created credential
      * @property userDisplayName an optional display name in addition to the [userId] that may be
      * displayed next to the `userId` during the user consent to help your user better understand
-     * the credential being created.
+     * the credential being created
      */
     class DisplayInfo internal /** @hide */ constructor(
         val userId: CharSequence,
         val userDisplayName: CharSequence?,
         /** @hide */
-        val credentialTypeIcon: Icon?
+        val credentialTypeIcon: Icon?,
+        /** @hide */
+        val defaultProvider: String?,
     ) {
 
         /**
@@ -82,7 +84,7 @@
          * @param userId the user id of the created credential
          * @param userDisplayName an optional display name in addition to the [userId] that may be
          * displayed next to the `userId` during the user consent to help your user better
-         * understand the credential being created.
+         * understand the credential being created
          * @throws IllegalArgumentException If [userId] is empty
          */
         @JvmOverloads constructor(
@@ -91,7 +93,8 @@
         ) : this(
             userId,
             userDisplayName,
-            null
+            null,
+            null,
         )
 
         init {
@@ -106,6 +109,9 @@
             if (!TextUtils.isEmpty(userDisplayName)) {
                 bundle.putCharSequence(BUNDLE_KEY_USER_DISPLAY_NAME, userDisplayName)
             }
+            if (!TextUtils.isEmpty(defaultProvider)) {
+                bundle.putString(BUNDLE_KEY_DEFAULT_PROVIDER, defaultProvider)
+            }
             // Today the type icon is determined solely within this library right before the
             // request is passed into the framework. Later if needed a new API can be added for
             // custom SDKs to supply their own credential type icons.
@@ -132,6 +138,10 @@
             const val BUNDLE_KEY_CREDENTIAL_TYPE_ICON =
                 "androidx.credentials.BUNDLE_KEY_CREDENTIAL_TYPE_ICON"
 
+            /** @hide */
+            const val BUNDLE_KEY_DEFAULT_PROVIDER =
+                "androidx.credentials.BUNDLE_KEY_DEFAULT_PROVIDER"
+
             /**
              * Returns a RequestDisplayInfo from a `credentialData` Bundle, or otherwise `null` if
              * parsing fails.
@@ -149,7 +159,9 @@
                         displayInfoBundle.getCharSequence(BUNDLE_KEY_USER_DISPLAY_NAME)
                     val icon: Icon? =
                         displayInfoBundle.getParcelable(BUNDLE_KEY_CREDENTIAL_TYPE_ICON)
-                    DisplayInfo(userId!!, displayName, icon)
+                    val defaultProvider: String? =
+                        displayInfoBundle.getString(BUNDLE_KEY_DEFAULT_PROVIDER)
+                    DisplayInfo(userId!!, displayName, icon, defaultProvider)
                 } catch (e: Exception) {
                     null
                 }
diff --git a/cursoradapter/OWNERS b/cursoradapter/OWNERS
new file mode 100644
index 0000000..347e71c
--- /dev/null
+++ b/cursoradapter/OWNERS
@@ -0,0 +1,2 @@
+aelias@google.com
+ryanmentley@google.com
diff --git a/customview/OWNERS b/customview/OWNERS
index 31cd563..9dc5349 100644
--- a/customview/OWNERS
+++ b/customview/OWNERS
@@ -1,2 +1,4 @@
 # Bug component: 461406
 alanv@google.com
+aelias@google.com
+ryanmentley@google.com
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index bf6a5c6..e099b3b 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -799,6 +799,124 @@
 public abstract java\.util\.List<androidx\.room\.integration\.kotlintestapp\.test\.JvmNameInDaoTest\.JvmNameEntity> jvmQuery\(\);
 public abstract androidx\.room\.integration\.kotlintestapp\.test\.JvmNameInDaoTest\.JvmNameDao jvmDao\(\);
 \^
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout\.java:[0-9]+: warning: \[deprecation\] CompactChip in androidx\.wear\.tiles\.material has been deprecated
+Note: \$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Button\.java has additional uses or overrides of a deprecated API\.
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] ButtonDefaults in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] Chip in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Chip;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] ChipColors in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.ChipColors;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] CircularProgressIndicator in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] Colors in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Colors;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] CompactChip in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] ProgressIndicatorColors in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.ProgressIndicatorColors;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] ProgressIndicatorDefaults in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] Text in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] TitleChip in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.TitleChip;
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] Typography in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Typography;
+import static androidx\.wear\.tiles\.material\.Typography\.TYPOGRAPHY_CAPTION[0-9]+;
+import static androidx\.wear\.tiles\.material\.Typography\.TYPOGRAPHY_TITLE[0-9]+;
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest\.java:[0-9]+: warning: \[deprecation\] Button in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest\.java:[0-9]+: warning: \[deprecation\] ButtonDefaults in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest\.java:[0-9]+: warning: \[deprecation\] LayoutDefaults in androidx\.wear\.tiles\.material\.layouts has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest\.java:[0-9]+: warning: \[deprecation\] CompactChip in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.CompactChip;
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest\.java:[0-9]+: warning: \[deprecation\] Text in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Text;
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest\.java:[0-9]+: warning: \[deprecation\] CircularProgressIndicator in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest\.java:[0-9]+: warning: \[deprecation\] Text in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/ButtonTest\.java:[0-9]+: warning: \[deprecation\] ButtonDefaults in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/CircularProgressIndicatorTest\.java:[0-9]+: warning: \[deprecation\] ProgressIndicatorDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Helper\.checkTag;
+import static androidx\.wear\.tiles\.material\.Helper\.getMetadataTagName;
+import static androidx\.wear\.tiles\.material\.Helper\.getTagBytes;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator\.java:[0-9]+: warning: \[deprecation\] ProgressIndicatorDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults\.DEFAULT_COLORS;
+import static androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults\.DEFAULT_END_ANGLE;
+import static androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults\.DEFAULT_PADDING;
+import static androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults\.DEFAULT_START_ANGLE;
+import static androidx\.wear\.tiles\.material\.ProgressIndicatorDefaults\.DEFAULT_STROKE_WIDTH;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/CompactChip\.java:[0-9]+: warning: \[deprecation\] ChipDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.COMPACT_HEIGHT;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.COMPACT_HEIGHT_TAPPABLE;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.COMPACT_HORIZONTAL_PADDING;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.COMPACT_PRIMARY_COLORS;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/CompactChip\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Chip\.java:[0-9]+: warning: \[deprecation\] ChipDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.DEFAULT_HEIGHT;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.DEFAULT_MARGIN_PERCENT;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.HORIZONTAL_PADDING;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.ICON_SIZE;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.ICON_SPACER_WIDTH;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.PRIMARY_COLORS;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Chip\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Helper\.radiusOf;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Typography\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Chip\.java:[0-9]+: warning: \[deprecation\] Typography in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Typography\.TypographyName;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Text\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Text\.java:[0-9]+: warning: \[deprecation\] Typography in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Typography\.TYPOGRAPHY_DISPLAY[0-9]+;
+import static androidx\.wear\.tiles\.material\.Typography\.getFontStyleBuilder;
+import static androidx\.wear\.tiles\.material\.Typography\.getLineHeightForTypography;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Button\.java:[0-9]+: warning: \[deprecation\] ButtonDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.ButtonDefaults\.DEFAULT_SIZE;
+import static androidx\.wear\.tiles\.material\.ButtonDefaults\.EXTRA_LARGE_SIZE;
+import static androidx\.wear\.tiles\.material\.ButtonDefaults\.LARGE_SIZE;
+import static androidx\.wear\.tiles\.material\.ButtonDefaults\.PRIMARY_COLORS;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Button\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/Button\.java:[0-9]+: warning: \[deprecation\] Typography in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/TitleChip\.java:[0-9]+: warning: \[deprecation\] ChipDefaults in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.TITLE_HEIGHT;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.TITLE_HORIZONTAL_PADDING;
+import static androidx\.wear\.tiles\.material\.ChipDefaults\.TITLE_PRIMARY_COLORS;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/TitleChip\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/LayoutDefaults\.java:[0-9]+: warning: \[deprecation\] ButtonDefaults in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.ButtonDefaults;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout\.java:[0-9]+: warning: \[deprecation\] LayoutDefaults in androidx\.wear\.tiles\.material\.layouts has been deprecated
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Helper\.getMetadataTagBytes;
+import static androidx\.wear\.tiles\.material\.Helper\.isRoundDevice;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout\.java:[0-9]+: warning: \[deprecation\] ProgressIndicatorDefaults in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout\.java:[0-9]+: warning: \[deprecation\] LayoutDefaults in androidx\.wear\.tiles\.material\.layouts has been deprecated
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout\.java:[0-9]+: warning: \[deprecation\] CircularProgressIndicator in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.CircularProgressIndicator;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout\.java:[0-9]+: warning: \[deprecation\] LayoutDefaults in androidx\.wear\.tiles\.material\.layouts has been deprecated
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_BUTTON_[0-9]+_SIZE;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_BUTTON_[0-9]+_PLUS_SIZE;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_BUTTON_MAX_NUMBER;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_BUTTON_SPACER_HEIGHT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.MULTI_BUTTON_SPACER_WIDTH;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout\.java:[0-9]+: warning: \[deprecation\] Button in androidx\.wear\.tiles\.material has been deprecated
+import androidx\.wear\.tiles\.material\.Button;
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout\.java:[0-9]+: warning: \[deprecation\] ChipDefaults in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout\.java:[0-9]+: warning: \[deprecation\] LayoutDefaults in androidx\.wear\.tiles\.material\.layouts has been deprecated
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.DEFAULT_VERTICAL_SPACER_HEIGHT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP;
+import static androidx\.wear\.tiles\.material\.layouts\.LayoutDefaults\.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP;
+Note: \$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout\.java has additional uses or overrides of a deprecated API\.
+[0-9]+ warnings
 # Gradle will log if you are not authenticated to upload scans
 A build scan was not published as you have not authenticated with server 'ge\.androidx\.dev'\.
 For more information, please see https://gradle\.com/help/gradle\-authenticating\-with\-gradle\-enterprise\.
@@ -845,7 +963,7 @@
 void androidx.tv.foundation.lazy.list.LazyListKt.LazyList(androidx.compose.ui.Modifier, androidx.tv.foundation.lazy.list.TvLazyListState, androidx.compose.foundation.layout.PaddingValues, boolean, boolean, boolean, androidx.tv.foundation.PivotOffsets, androidx.compose.ui.Alignment$Horizontal, androidx.compose.foundation.layout.Arrangement$Vertical, androidx.compose.ui.Alignment$Vertical, androidx.compose.foundation.layout.Arrangement$Horizontal, kotlin.jvm.functions.Function1, androidx.compose.runtime.Composer, int, int, int)
 void androidx.tv.foundation.lazy.grid.LazyGridKt.LazyGrid(androidx.compose.ui.Modifier, androidx.tv.foundation.lazy.grid.TvLazyGridState, kotlin.jvm.functions.Function2, androidx.compose.foundation.layout.PaddingValues, boolean, boolean, boolean, androidx.compose.foundation.layout.Arrangement$Vertical, androidx.compose.foundation.layout.Arrangement$Horizontal, androidx.tv.foundation.PivotOffsets, kotlin.jvm.functions.Function1, androidx.compose.runtime.Composer, int, int, int)
 # > Task :room:integration-tests:room-testapp:mergeDexWithExpandProjectionDebugAndroidTest
-WARNING: D8: Application does not contain `androidx\.tracing\.Trace` as referenced in main\-dex\-list\.
+WARNING:D[0-9]+: Application does not contain `androidx\.tracing\.Trace` as referenced in main\-dex\-list\.
 # > Task :hilt:hilt-compiler:kaptTestKotlin
 Annotation processors discovery from compile classpath is deprecated\.
 Set 'kapt\.include\.compile\.classpath=false' to disable discovery\.
@@ -876,4 +994,12 @@
 # > Configure project :internal-testutils-ktx
 WARNING:.*The option setting 'android\.r8\.maxWorkers=[0-9]+' is experimental\.
 # Building XCFrameworks (b/260140834) and iOS benchmark invocation
-.*xcodebuild.*
\ No newline at end of file
+.*xcodebuild.*
+# > Task :wear:tiles:tiles-material:compileDebugJavaWithJavac
+\$SUPPORT/wear/tiles/tiles\-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator\.java:[0-9]+: warning: \[deprecation\] Helper in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Helper\.checkNotNull;
+# > Task :wear:tiles:tiles-material:compileDebugUnitTestJavaWithJavac
+\$SUPPORT/wear/tiles/tiles\-material/src/test/java/androidx/wear/tiles/material/TextTest\.java:[0-9]+: warning: \[deprecation\] Typography in androidx\.wear\.tiles\.material has been deprecated
+import static androidx\.wear\.tiles\.material\.Typography\.TYPOGRAPHY_BODY[0-9]+;
+# > Task :wear:tiles:tiles-material:compileDebugAndroidTestJavaWithJavac
+\$SUPPORT/wear/tiles/tiles\-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator\.java:[0-9]+: warning: \[deprecation\] Button in androidx\.wear\.tiles\.material has been deprecated
\ No newline at end of file
diff --git a/development/update_studio.sh b/development/update_studio.sh
index 02c7a6a..2024fe4 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -7,8 +7,8 @@
 
 # Get versions
 echo Getting Studio version and link
-AGP_VERSION=${1:-8.0.0-beta05}
-STUDIO_VERSION_STRING=${2:-"Android Studio Flamingo | 2022.2.1 Beta 5"}
+AGP_VERSION=${1:-8.0.0-beta03}
+STUDIO_VERSION_STRING=${2:-"Android Studio Flamingo | 2022.2.1 Beta 3"}
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
 echo iframe link $STUDIO_IFRAME_LINK
 STUDIO_IFRAME_REDIRECT=`curl -s $STUDIO_IFRAME_LINK | grep href | sed 's/.*href="\([^"]*\)".*/\1/g'`
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index 4b406d6..67b8d16 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -212,29 +212,29 @@
     docs("androidx.media2:media2-session:1.2.1")
     docs("androidx.media2:media2-widget:1.2.1")
     docs("androidx.media:media:1.6.0")
-    docs("androidx.media3:media3-cast:1.0.0-rc02")
-    docs("androidx.media3:media3-common:1.0.0-rc02")
-    docs("androidx.media3:media3-database:1.0.0-rc02")
-    docs("androidx.media3:media3-datasource:1.0.0-rc02")
-    docs("androidx.media3:media3-datasource-cronet:1.0.0-rc02")
-    docs("androidx.media3:media3-datasource-okhttp:1.0.0-rc02")
-    docs("androidx.media3:media3-datasource-rtmp:1.0.0-rc02")
-    docs("androidx.media3:media3-decoder:1.0.0-rc02")
-    docs("androidx.media3:media3-effect:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-dash:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-hls:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-ima:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-rtsp:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-smoothstreaming:1.0.0-rc02")
-    docs("androidx.media3:media3-exoplayer-workmanager:1.0.0-rc02")
-    docs("androidx.media3:media3-extractor:1.0.0-rc02")
-    docs("androidx.media3:media3-session:1.0.0-rc02")
-    docs("androidx.media3:media3-test-utils:1.0.0-rc02")
-    docs("androidx.media3:media3-test-utils-robolectric:1.0.0-rc02")
-    docs("androidx.media3:media3-transformer:1.0.0-rc02")
-    docs("androidx.media3:media3-ui:1.0.0-rc02")
-    docs("androidx.media3:media3-ui-leanback:1.0.0-rc02")
+    docs("androidx.media3:media3-cast:1.0.0")
+    docs("androidx.media3:media3-common:1.0.0")
+    docs("androidx.media3:media3-database:1.0.0")
+    docs("androidx.media3:media3-datasource:1.0.0")
+    docs("androidx.media3:media3-datasource-cronet:1.0.0")
+    docs("androidx.media3:media3-datasource-okhttp:1.0.0")
+    docs("androidx.media3:media3-datasource-rtmp:1.0.0")
+    docs("androidx.media3:media3-decoder:1.0.0")
+    docs("androidx.media3:media3-effect:1.0.0")
+    docs("androidx.media3:media3-exoplayer:1.0.0")
+    docs("androidx.media3:media3-exoplayer-dash:1.0.0")
+    docs("androidx.media3:media3-exoplayer-hls:1.0.0")
+    docs("androidx.media3:media3-exoplayer-ima:1.0.0")
+    docs("androidx.media3:media3-exoplayer-rtsp:1.0.0")
+    docs("androidx.media3:media3-exoplayer-smoothstreaming:1.0.0")
+    docs("androidx.media3:media3-exoplayer-workmanager:1.0.0")
+    docs("androidx.media3:media3-extractor:1.0.0")
+    docs("androidx.media3:media3-session:1.0.0")
+    docs("androidx.media3:media3-test-utils:1.0.0")
+    docs("androidx.media3:media3-test-utils-robolectric:1.0.0")
+    docs("androidx.media3:media3-transformer:1.0.0")
+    docs("androidx.media3:media3-ui:1.0.0")
+    docs("androidx.media3:media3-ui-leanback:1.0.0")
     docs("androidx.mediarouter:mediarouter:1.6.0-alpha02")
     docs("androidx.mediarouter:mediarouter-testing:1.6.0-alpha02")
     docs("androidx.metrics:metrics-performance:1.0.0-alpha03")
@@ -278,7 +278,7 @@
     docs("androidx.privacysandbox.ui:ui-client:1.0.0-alpha01")
     docs("androidx.privacysandbox.ui:ui-core:1.0.0-alpha01")
     docs("androidx.privacysandbox.ui:ui-provider:1.0.0-alpha01")
-    docs("androidx.profileinstaller:profileinstaller:1.3.0-rc01")
+    docs("androidx.profileinstaller:profileinstaller:1.3.0")
     docs("androidx.recommendation:recommendation:1.0.0")
     docs("androidx.recyclerview:recyclerview:1.3.0")
     docs("androidx.recyclerview:recyclerview-selection:2.0.0-alpha01")
@@ -396,16 +396,16 @@
     samples("androidx.wear:wear-input-samples:1.2.0-alpha01")
     docs("androidx.wear:wear-input-testing:1.2.0-alpha02")
     docs("androidx.webkit:webkit:1.7.0-alpha03")
-    docs("androidx.window.extensions.core:core:1.0.0-alpha01")
-    docs("androidx.window:window:1.1.0-alpha06")
+    docs("androidx.window.extensions.core:core:1.0.0-beta01")
+    docs("androidx.window:window:1.1.0-beta01")
     stubs(fileTree(dir: "../window/stubs/", include: ["window-sidecar-release-0.1.0-alpha01.aar"]))
-    docs("androidx.window:window-core:1.1.0-alpha06")
+    docs("androidx.window:window-core:1.1.0-beta01")
     stubs("androidx.window:window-extensions:1.0.0-alpha01")
-    docs("androidx.window:window-java:1.1.0-alpha06")
-    docs("androidx.window:window-rxjava2:1.1.0-alpha06")
-    docs("androidx.window:window-rxjava3:1.1.0-alpha06")
-    samples("androidx.window:window-samples:1.1.0-alpha06")
-    docs("androidx.window:window-testing:1.1.0-alpha06")
+    docs("androidx.window:window-java:1.1.0-beta01")
+    docs("androidx.window:window-rxjava2:1.1.0-beta01")
+    docs("androidx.window:window-rxjava3:1.1.0-beta01")
+    samples("androidx.window:window-samples:1.1.0-beta01")
+    docs("androidx.window:window-testing:1.1.0-beta01")
     docs("androidx.work:work-gcm:2.8.0")
     docs("androidx.work:work-multiprocess:2.8.0")
     docs("androidx.work:work-runtime:2.8.0")
diff --git a/drawerlayout/OWNERS b/drawerlayout/OWNERS
new file mode 100644
index 0000000..347e71c
--- /dev/null
+++ b/drawerlayout/OWNERS
@@ -0,0 +1,2 @@
+aelias@google.com
+ryanmentley@google.com
diff --git a/emoji2/emoji2-emojipicker/src/androidTest/java/androidx/emoji2/emojipicker/EmojiPickerViewTest.kt b/emoji2/emoji2-emojipicker/src/androidTest/java/androidx/emoji2/emojipicker/EmojiPickerViewTest.kt
index 57c0bc3..f6bbac1 100644
--- a/emoji2/emoji2-emojipicker/src/androidTest/java/androidx/emoji2/emojipicker/EmojiPickerViewTest.kt
+++ b/emoji2/emoji2-emojipicker/src/androidTest/java/androidx/emoji2/emojipicker/EmojiPickerViewTest.kt
@@ -39,6 +39,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
 import org.hamcrest.Description
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
@@ -120,6 +121,8 @@
         activityTestRule.scenario.onActivity {
             view = it.findViewById(R.id.emojiPickerTest)
         }
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+
         // Scroll to the nose emoji, long click then select nose in dark skin tone
         findViewByEmoji(view, NOSE_EMOJI)
             ?: onView(withId(EmojiPickerViewR.id.emoji_picker_body))
@@ -143,7 +146,6 @@
     @Test
     fun testHeader_highlightCurrentCategory() {
         disableRecent()
-
         assertSelectedHeaderIndex(0)
         scrollToEmoji(NOSE_EMOJI)
         assertSelectedHeaderIndex(1)
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 614d3fb..248f510 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -34,7 +34,7 @@
     api("androidx.lifecycle:lifecycle-livedata-core:2.6.1")
     api("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
     api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
     api("androidx.savedstate:savedstate:1.2.1")
     api("androidx.annotation:annotation-experimental:1.0.0")
     api(libs.kotlinStdlib)
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
index a7112a1..4535f2c 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentResultTest.kt
@@ -22,6 +22,8 @@
 import androidx.activity.result.ActivityResult
 import androidx.fragment.app.test.FragmentTestActivity
 import androidx.fragment.test.R
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
 import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -200,6 +202,36 @@
     }
 
     @Test
+    fun testClearResultListenerInCallbackWhenStarted() {
+        withUse(ActivityScenario.launch(FragmentTestActivity::class.java)) {
+            val fm = withActivity {
+                setContentView(R.layout.simple_container)
+                supportFragmentManager
+            }
+
+            val fragment1 = ClearResultFragment(Lifecycle.State.RESUMED)
+
+            // set a result while no listener is available so it is stored in the fragment manager
+            fm.setFragmentResult("requestKey", Bundle())
+
+            // adding the fragment is going to execute and clear its listener.
+            withActivity {
+                fm.beginTransaction()
+                    .add(R.id.fragmentContainer, fragment1)
+                    .commitNow()
+            }
+
+            withActivity {
+                // Send a second result, which should not be received by fragment1
+                fm.setFragmentResult("requestKey", Bundle())
+            }
+
+            assertWithMessage("the listener should only be executed once")
+                .that(fragment1.callbackCount).isEqualTo(1)
+        }
+    }
+
+    @Test
     fun testResetResultListener() {
        withUse(ActivityScenario.launch(FragmentTestActivity::class.java)) {
             val fm = withActivity {
@@ -453,19 +485,24 @@
     }
 }
 
-class ClearResultFragment : StrictFragment() {
+class ClearResultFragment(
+    private val setLifecycleInState: Lifecycle.State = Lifecycle.State.CREATED
+) : StrictFragment() {
     var callbackCount = 0
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-
-        parentFragmentManager.setFragmentResultListener(
-            "requestKey", this,
-            FragmentResultListener { _, _ ->
-                callbackCount++
-                parentFragmentManager.clearFragmentResultListener("requestKey")
+        lifecycle.addObserver(LifecycleEventObserver { _, event ->
+            if (Lifecycle.Event.upTo(setLifecycleInState) == event) {
+                parentFragmentManager.setFragmentResultListener(
+                    "requestKey", this,
+                    FragmentResultListener { _, _ ->
+                        callbackCount++
+                        parentFragmentManager.clearFragmentResultListener("requestKey")
+                    }
+                )
             }
-        )
+        })
     }
 }
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
index 97f5ae8..af1ead3 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/LoaderTest.kt
@@ -29,10 +29,8 @@
 import androidx.testutils.waitForExecution
 import com.google.common.truth.Truth.assertThat
 import java.lang.ref.WeakReference
-import leakcanary.DetectLeaksAfterTestSuccess
 import org.junit.Rule
 import org.junit.Test
-import org.junit.rules.RuleChain
 import org.junit.runner.RunWith
 
 @RunWith(AndroidJUnit4::class)
@@ -40,12 +38,16 @@
 class LoaderTest {
 
     @Suppress("DEPRECATION")
+    @get:Rule
     var activityRule = androidx.test.rule.ActivityTestRule(LoaderActivity::class.java)
 
+    // TODO(b/272519998): Add back in leak detection rule chain once leak addressed by platform
     // Detect leaks BEFORE and AFTER activity is destroyed
+    /*
     @get:Rule
     val ruleChain: RuleChain = RuleChain.outerRule(DetectLeaksAfterTestSuccess())
         .around(activityRule)
+    */
 
     /**
      * Test to ensure that there is no Activity leak due to Loader
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
index 8dacb98..a2fbe3e 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/OnBackStackChangedListenerTest.kt
@@ -332,7 +332,7 @@
             executePendingTransactions()
 
             assertThat(startedCount).isEqualTo(1)
-            assertThat(committedCount).isEqualTo(0)
+            assertThat(committedCount).isEqualTo(1)
         }
     }
 }
\ No newline at end of file
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index 5393b86..fdda8bc 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -988,7 +988,6 @@
                 }
             }
         };
-        lifecycle.addObserver(observer);
         LifecycleAwareResultListener storedListener = mResultListeners.put(requestKey,
                 new LifecycleAwareResultListener(lifecycle, listener, observer));
         if (storedListener != null) {
@@ -998,6 +997,9 @@
             Log.v(FragmentManager.TAG, "Setting FragmentResultListener with key " + requestKey
                     + " lifecycleOwner " + lifecycle + " and listener " + listener);
         }
+        // Only add the observer after we've added the listener to the map
+        // to ensure that re-entrant removals actually have a registered listener to remove
+        lifecycle.addObserver(observer);
     }
 
     @Override
@@ -1892,14 +1894,23 @@
         // such as push, push, pop, push are correctly considered a push
         boolean isPop = isRecordPop.get(endIndex - 1);
 
-        if (mBackStackChangeListeners != null) {
-            // we dispatch callbacks based on each record
+        if (mBackStackChangeListeners != null && !mBackStackChangeListeners.isEmpty()) {
+            ArrayList<Fragment> fragments = new ArrayList<>();
+            // Build a list of fragments based on the records
             for (BackStackRecord record : records) {
-                for (Fragment fragment : fragmentsFromRecord(record)) {
-                    // We give all fragment the back stack changed started signal first
-                    for (OnBackStackChangedListener listener : mBackStackChangeListeners) {
-                        listener.onBackStackChangeStarted(fragment, isPop);
-                    }
+                fragments.addAll(fragmentsFromRecord(record));
+            }
+            // Dispatch to all of the fragments in the list
+            for (OnBackStackChangedListener listener : mBackStackChangeListeners) {
+                // We give all fragment the back stack changed started signal first
+                for (Fragment fragment: fragments) {
+                    listener.onBackStackChangeStarted(fragment, isPop);
+                }
+            }
+            for (OnBackStackChangedListener listener : mBackStackChangeListeners) {
+                // Then we give them all the committed signal
+                for (Fragment fragment: fragments) {
+                    listener.onBackStackChangeCommitted(fragment, isPop);
                 }
             }
         }
@@ -1950,17 +1961,6 @@
         }
         if (addToBackStack) {
             reportBackStackChanged();
-            if (mBackStackChangeListeners != null) {
-                // we dispatch callbacks based on each record
-                for (BackStackRecord record : records) {
-                    for (Fragment fragment : fragmentsFromRecord(record)) {
-                        // Then we give them all the committed signal
-                        for (OnBackStackChangedListener listener : mBackStackChangeListeners) {
-                            listener.onBackStackChangeCommitted(fragment, isPop);
-                        }
-                    }
-                }
-            }
         }
     }
 
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
index 5798d51..4d75f81 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
@@ -281,6 +281,7 @@
         }
     }
 
+    @Ignore("b/273482357")
     @Test
     fun itemContent_multipleViews() {
         TestGlanceAppWidget.uiDefinition = {
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt b/glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt
index 578fd4e..42bdefa 100644
--- a/glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt
+++ b/glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt
@@ -51,4 +51,21 @@
             }
         }
     }
-}
\ No newline at end of file
+}
+
+/**
+ * Monitors global snapshot state writes and sends apply notifications.
+ */
+internal suspend fun globalSnapshotMonitor() {
+    val channel = Channel<Unit>(Channel.CONFLATED)
+    val observerHandle = Snapshot.registerGlobalWriteObserver {
+        channel.trySend(Unit)
+    }
+    try {
+        channel.consumeEach {
+            Snapshot.sendApplyNotifications()
+        }
+    } finally {
+        observerHandle.dispose()
+    }
+}
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt b/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt
index c2369aa..f580890 100644
--- a/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt
+++ b/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt
@@ -26,6 +26,7 @@
 import androidx.work.CoroutineWorker
 import androidx.work.WorkerParameters
 import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
@@ -54,17 +55,18 @@
         internal val defaultTimeout = 45.seconds
     }
 
-    override suspend fun doWork(): Result = withTimeoutOrNull(defaultTimeout) {
-        val frameClock = InteractiveFrameClock(this)
-        val key =
-            inputData.getString(sessionManager.keyParam)
-                ?: return@withTimeoutOrNull Result.failure()
-        val session = requireNotNull(sessionManager.getSession(key)) {
-            "No session available to key $key"
-        }
+    private val key = inputData.getString(sessionManager.keyParam)
+            ?: error("SessionWorker must be started with a key")
 
+    @Deprecated("Deprecated by super class, replacement in progress, see b/245353737")
+    @OptIn(ExperimentalStdlibApi::class)
+    override val coroutineContext = Dispatchers.Main
+
+    override suspend fun doWork(): Result = withTimeoutOrNull(defaultTimeout) {
+        val session = sessionManager.getSession(key) ?: error("No session available for key $key")
         if (DEBUG) Log.d(TAG, "Setting up composition for ${session.key}")
-        GlobalSnapshotManager.ensureStarted()
+        val frameClock = InteractiveFrameClock(this)
+        val snapshotMonitor = launch { globalSnapshotMonitor() }
         val root = session.createRootEmittable()
         val recomposer = Recomposer(coroutineContext)
         val composition = Composition(Applier(root), recomposer).apply {
@@ -109,6 +111,7 @@
 
         composition.dispose()
         frameClock.stopInteractive()
+        snapshotMonitor.cancel()
         recomposer.close()
         recomposer.join()
         return@withTimeoutOrNull Result.success()
diff --git a/gradle.properties b/gradle.properties
index 35cce07..a26afbf 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -32,7 +32,7 @@
 androidx.allowCustomCompileSdk=false
 
 # Don't warn about needing to update AGP
-android.suppressUnsupportedCompileSdk=Tiramisu,33,UpsideDownCake
+android.suppressUnsupportedCompileSdk=Tiramisu,33
 
 # Disable features we do not use
 android.defaults.buildfeatures.aidl=false
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f77cc84..2383b5d9 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
 # -----------------------------------------------------------------------------
 # All of the following should be updated in sync.
 # -----------------------------------------------------------------------------
-androidGradlePlugin = "8.0.0-beta05"
+androidGradlePlugin = "8.0.0-beta03"
 # 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.0.0-beta05"
+androidLint = "31.0.0-beta03"
 # 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 = "2022.2.1.16"
+androidStudio = "2022.2.1.14"
 # -----------------------------------------------------------------------------
 
 androidGradlePluginMin = "7.0.4"
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/MultiBufferedCanvasRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/MultiBufferedCanvasRendererTest.kt
new file mode 100644
index 0000000..85138d1
--- /dev/null
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/MultiBufferedCanvasRendererTest.kt
@@ -0,0 +1,141 @@
+/*
+ * 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.graphics
+
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.ColorSpace
+import android.graphics.RenderNode
+import android.os.Build
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class MultiBufferedCanvasRendererTest {
+
+    companion object {
+        const val TEST_WIDTH = 20
+        const val TEST_HEIGHT = 20
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderFrameInvokesCallback() {
+        val renderNode = RenderNode("node").apply {
+            setPosition(0, 0, TEST_WIDTH, TEST_HEIGHT)
+            val canvas = beginRecording()
+            canvas.drawColor(Color.RED)
+            endRecording()
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        val renderer = MultiBufferedCanvasRenderer(renderNode, TEST_WIDTH, TEST_HEIGHT)
+        try {
+            val renderLatch = CountDownLatch(1)
+            renderer.renderFrame(executor) {
+                renderLatch.countDown()
+            }
+            assertTrue(renderLatch.await(1000, TimeUnit.MILLISECONDS))
+        } finally {
+            renderer.release()
+            executor.shutdownNow()
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderAfterReleaseDoesNotRender() {
+        val renderNode = RenderNode("node").apply {
+            setPosition(0, 0, TEST_WIDTH, TEST_HEIGHT)
+            val canvas = beginRecording()
+            canvas.drawColor(Color.RED)
+            endRecording()
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        val renderer = MultiBufferedCanvasRenderer(renderNode, TEST_WIDTH, TEST_HEIGHT)
+        try {
+            val renderLatch = CountDownLatch(1)
+            renderer.release()
+            renderer.renderFrame(executor) {
+                renderLatch.countDown()
+            }
+            assertFalse(renderLatch.await(1000, TimeUnit.MILLISECONDS))
+        } finally {
+            executor.shutdownNow()
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testMultiReleasesDoesNotCrash() {
+        val renderNode = RenderNode("node").apply {
+            setPosition(0, 0, TEST_WIDTH, TEST_HEIGHT)
+            val canvas = beginRecording()
+            canvas.drawColor(Color.RED)
+            endRecording()
+        }
+        val renderer = MultiBufferedCanvasRenderer(renderNode, TEST_WIDTH, TEST_HEIGHT)
+        renderer.release()
+        renderer.release()
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderOutput() {
+        val renderNode = RenderNode("node").apply {
+            setPosition(0, 0, TEST_WIDTH, TEST_HEIGHT)
+            val canvas = beginRecording()
+            drawSquares(
+                canvas,
+                TEST_WIDTH,
+                TEST_HEIGHT,
+                Color.RED,
+                Color.YELLOW,
+                Color.GREEN,
+                Color.BLUE
+            )
+            endRecording()
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        val renderer = MultiBufferedCanvasRenderer(renderNode, TEST_WIDTH, TEST_HEIGHT)
+        try {
+            val renderLatch = CountDownLatch(1)
+            var bitmap: Bitmap? = null
+            renderer.renderFrame(executor) { buffer ->
+                val colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB)
+                bitmap = Bitmap.wrapHardwareBuffer(buffer, colorSpace)
+                    ?.copy(Bitmap.Config.ARGB_8888, false)
+                renderLatch.countDown()
+            }
+            assertTrue(renderLatch.await(1000, TimeUnit.MILLISECONDS))
+            assertNotNull(bitmap)
+            bitmap!!.verifyQuadrants(Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE)
+        } finally {
+            renderer.release()
+            executor.shutdownNow()
+        }
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/TestUtils.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/TestUtils.kt
new file mode 100644
index 0000000..7958b18
--- /dev/null
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/TestUtils.kt
@@ -0,0 +1,122 @@
+/*
+ * 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.graphics
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.opengl.EGL14
+import androidx.graphics.opengl.egl.EGLConfigAttributes
+import androidx.graphics.opengl.egl.EGLManager
+import androidx.graphics.opengl.egl.EGLSpec
+import androidx.graphics.opengl.egl.EGLVersion
+import org.junit.Assert
+
+fun drawSquares(
+    canvas: Canvas,
+    width: Int,
+    height: Int,
+    topLeft: Int,
+    topRight: Int,
+    bottomLeft: Int,
+    bottomRight: Int
+) {
+    val paint = Paint()
+    val widthF = width.toFloat()
+    val heightF = height.toFloat()
+    val halfWidth = widthF / 2f
+    val halfHeight = heightF / 2f
+    canvas.drawRect(0f, 0f, halfWidth, halfHeight,
+        paint.apply { color = topLeft })
+    canvas.drawRect(halfWidth, 0f, widthF, halfHeight,
+        paint.apply { color = topRight })
+    canvas.drawRect(0f, halfHeight, halfWidth, heightF,
+        paint.apply { color = bottomLeft })
+    canvas.drawRect(halfWidth, halfHeight, widthF, heightF,
+        paint.apply { color = bottomRight })
+}
+
+fun Bitmap.verifyQuadrants(
+    topLeft: Int,
+    topRight: Int,
+    bottomLeft: Int,
+    bottomRight: Int
+) {
+    Assert.assertEquals(topLeft, getPixel(1, 1))
+    Assert.assertEquals(topLeft, getPixel(width / 2 - 2, 1))
+    Assert.assertEquals(topLeft, getPixel(width / 2 - 2, height / 2 - 2))
+    Assert.assertEquals(topLeft, getPixel(1, height / 2 - 2))
+
+    Assert.assertEquals(topRight, getPixel(width / 2 + 2, 1))
+    Assert.assertEquals(topRight, getPixel(width - 2, 1))
+    Assert.assertEquals(topRight, getPixel(width - 2, height / 2 - 2))
+    Assert.assertEquals(topRight, getPixel(width / 2 + 2, height / 2 - 2))
+
+    Assert.assertEquals(bottomLeft, getPixel(1, height / 2 + 2))
+    Assert.assertEquals(bottomLeft, getPixel(width / 2 - 2, height / 2 + 2))
+    Assert.assertEquals(bottomLeft, getPixel(width / 2 - 2, height - 2))
+    Assert.assertEquals(bottomLeft, getPixel(1, height - 2))
+
+    Assert.assertEquals(bottomRight, getPixel(width / 2 + 2, height / 2 + 2))
+    Assert.assertEquals(bottomRight, getPixel(width - 2, height / 2 + 2))
+    Assert.assertEquals(bottomRight, getPixel(width - 2, height - 2))
+    Assert.assertEquals(bottomRight, getPixel(width / 2 + 2, height - 2))
+}
+
+fun Bitmap.isAllColor(targetColor: Int): Boolean {
+    for (i in 0 until width) {
+        for (j in 0 until height) {
+            if (getPixel(i, j) != targetColor) {
+                return false
+            }
+        }
+    }
+    return true
+}
+
+fun withEgl(block: (egl: EGLManager) -> Unit) {
+    val egl = createAndSetupEGLManager(EGLSpec.V14)
+    try {
+        block(egl)
+    } finally {
+        releaseEGLManager(egl)
+    }
+}
+
+// Helper method to create and initialize an EGLManager
+private fun createAndSetupEGLManager(eglSpec: EGLSpec = EGLSpec.V14): EGLManager {
+    val egl = EGLManager(eglSpec)
+    Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
+    Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
+
+    egl.initialize()
+
+    val config = egl.loadConfig(EGLConfigAttributes.RGBA_8888)
+    if (config == null) {
+        Assert.fail("Config 888 should be supported")
+    }
+
+    egl.createContext(config!!)
+    return egl
+}
+
+// Helper method to release EGLManager
+private fun releaseEGLManager(egl: EGLManager) {
+    egl.release()
+    Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
+    Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29Test.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29Test.kt
new file mode 100644
index 0000000..736b93e
--- /dev/null
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29Test.kt
@@ -0,0 +1,456 @@
+/*
+ * 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.graphics.lowlatency
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.ColorSpace
+import android.hardware.HardwareBuffer
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.graphics.drawSquares
+import androidx.graphics.isAllColor
+import androidx.graphics.opengl.egl.supportsNativeAndroidFence
+import androidx.graphics.surface.SurfaceControlCompat
+import androidx.graphics.surface.SurfaceControlCompat.Companion.BUFFER_TRANSFORM_IDENTITY
+import androidx.graphics.verifyQuadrants
+import androidx.graphics.withEgl
+import androidx.hardware.SyncFenceCompat
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicInteger
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class SingleBufferedCanvasRendererV29Test {
+
+    companion object {
+        const val TEST_WIDTH = 20
+        const val TEST_HEIGHT = 20
+    }
+
+    data class RectColors(
+        val topLeft: Int,
+        val topRight: Int,
+        val bottomLeft: Int,
+        val bottomRight: Int
+    )
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderFrameRotate0() {
+        testRenderWithTransform(
+            BUFFER_TRANSFORM_IDENTITY,
+            RectColors(
+                topLeft = Color.RED,
+                topRight = Color.YELLOW,
+                bottomRight = Color.BLUE,
+                bottomLeft = Color.GREEN
+            ),
+            RectColors(
+                topLeft = Color.RED,
+                topRight = Color.YELLOW,
+                bottomRight = Color.BLUE,
+                bottomLeft = Color.GREEN
+            )
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderFrameRotate90() {
+        testRenderWithTransform(
+            SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90,
+            RectColors(
+                topLeft = Color.RED,
+                topRight = Color.YELLOW,
+                bottomRight = Color.BLUE,
+                bottomLeft = Color.GREEN
+            ),
+            RectColors(
+                topLeft = Color.YELLOW,
+                topRight = Color.BLUE,
+                bottomRight = Color.GREEN,
+                bottomLeft = Color.RED
+            )
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderFrameRotate180() {
+        testRenderWithTransform(
+            SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180,
+            RectColors(
+                topLeft = Color.RED,
+                topRight = Color.YELLOW,
+                bottomRight = Color.BLUE,
+                bottomLeft = Color.GREEN
+            ),
+            RectColors(
+                topLeft = Color.BLUE,
+                topRight = Color.GREEN,
+                bottomRight = Color.RED,
+                bottomLeft = Color.YELLOW
+            )
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRenderFrameRotate270() {
+        testRenderWithTransform(
+            SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270,
+            RectColors(
+                topLeft = Color.RED,
+                topRight = Color.YELLOW,
+                bottomRight = Color.BLUE,
+                bottomLeft = Color.GREEN
+            ),
+            RectColors(
+                topLeft = Color.GREEN,
+                topRight = Color.RED,
+                bottomRight = Color.YELLOW,
+                bottomLeft = Color.BLUE
+            )
+        )
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testClearRenderer() {
+        val transformer = BufferTransformer().apply {
+            computeTransform(TEST_WIDTH, TEST_HEIGHT, BUFFER_TRANSFORM_IDENTITY)
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        val firstRenderLatch = CountDownLatch(1)
+        val clearLatch = CountDownLatch(2)
+        var buffer: HardwareBuffer? = null
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Unit> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Unit) {
+                    canvas.drawColor(Color.RED)
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    syncFenceCompat?.awaitForever()
+                    buffer = hardwareBuffer
+                    firstRenderLatch.countDown()
+                    clearLatch.countDown()
+                }
+            }).apply {
+                // See: b/236394768 Workaround for ANGLE issue where FBOs with HardwareBuffer
+                // attachments are not executed until a glReadPixels call is made
+                forceFlush.set(true)
+            }
+        try {
+            renderer.render(Unit)
+            firstRenderLatch.await(3000, TimeUnit.MILLISECONDS)
+            renderer.clear()
+            assertTrue(clearLatch.await(3000, TimeUnit.MILLISECONDS))
+            assertNotNull(buffer)
+            val colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB)
+            val bitmap = Bitmap.wrapHardwareBuffer(buffer!!, colorSpace)
+                ?.copy(Bitmap.Config.ARGB_8888, false)
+            assertNotNull(bitmap)
+            assertTrue(bitmap!!.isAllColor(Color.TRANSPARENT))
+        } finally {
+            val latch = CountDownLatch(1)
+            renderer.release(true) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testCancelPending() {
+        val transformer = BufferTransformer().apply {
+            computeTransform(TEST_WIDTH, TEST_HEIGHT, BUFFER_TRANSFORM_IDENTITY)
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        var buffer: HardwareBuffer? = null
+        val initialDrawLatch = CountDownLatch(1)
+        val bufferReadyLatch = CountDownLatch(1)
+        val waitForRequestLatch = CountDownLatch(1)
+
+        var drawCancelledRequestLatch: CountDownLatch? = null
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Int> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Int) {
+                    canvas.drawColor(param)
+                    initialDrawLatch.countDown()
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    syncFenceCompat?.awaitForever()
+                    buffer = hardwareBuffer
+                    bufferReadyLatch.countDown()
+                    drawCancelledRequestLatch?.countDown()
+                }
+            })
+        try {
+            renderer.render(Color.RED)
+            assertTrue(initialDrawLatch.await(3000, TimeUnit.MILLISECONDS))
+
+            drawCancelledRequestLatch = CountDownLatch(2)
+            renderer.render(Color.GREEN)
+            renderer.render(Color.YELLOW)
+            renderer.cancelPending()
+            waitForRequestLatch.countDown()
+
+            assertTrue(bufferReadyLatch.await(3000, TimeUnit.MILLISECONDS))
+            // Because the requests were cancelled this latch should not be signalled
+            assertFalse(drawCancelledRequestLatch.await(1000, TimeUnit.MILLISECONDS))
+            assertNotNull(buffer)
+            val colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB)
+            val bitmap = Bitmap.wrapHardwareBuffer(buffer!!, colorSpace)
+                ?.copy(Bitmap.Config.ARGB_8888, false)
+            assertNotNull(bitmap)
+            assertTrue(bitmap!!.isAllColor(Color.RED))
+        } finally {
+            val latch = CountDownLatch(1)
+            renderer.release(true) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testMultiReleasesDoesNotCrash() {
+        val transformer = BufferTransformer()
+        val executor = Executors.newSingleThreadExecutor()
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Void> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Void) {
+                    // NO-OP
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    // NO-OP
+                }
+            })
+        try {
+            val latch = CountDownLatch(1)
+            renderer.release(true) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+            renderer.release(true)
+        } finally {
+            if (!executor.isShutdown) {
+                executor.shutdownNow()
+            }
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testRendererVisibleFlag() {
+        var supportsNativeAndroidFence = false
+        withEgl { eglManager ->
+            supportsNativeAndroidFence = eglManager.supportsNativeAndroidFence()
+        }
+        if (!supportsNativeAndroidFence) {
+            return
+        }
+        val transformer = BufferTransformer().apply {
+            computeTransform(TEST_WIDTH, TEST_HEIGHT, BUFFER_TRANSFORM_IDENTITY)
+        }
+        val executor = Executors.newSingleThreadExecutor()
+        var syncFenceNull = false
+        var drawLatch: CountDownLatch? = null
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Int> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Int) {
+                    canvas.drawColor(param)
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    syncFenceNull = syncFenceCompat == null
+                    syncFenceCompat?.awaitForever()
+                    drawLatch?.countDown()
+                }
+            })
+        try {
+            renderer.isVisible = false
+            drawLatch = CountDownLatch(1)
+            renderer.render(Color.RED)
+            assertTrue(drawLatch.await(3000, TimeUnit.MILLISECONDS))
+            assertFalse(syncFenceNull)
+
+            renderer.isVisible = true
+            drawLatch = CountDownLatch(1)
+            renderer.render(Color.BLUE)
+            assertTrue(drawLatch.await(3000, TimeUnit.MILLISECONDS))
+            assertTrue(syncFenceNull)
+        } finally {
+            val latch = CountDownLatch(1)
+            renderer.release(true) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testBatchedRenders() {
+        val transformer = BufferTransformer()
+        transformer.computeTransform(TEST_WIDTH, TEST_HEIGHT, BUFFER_TRANSFORM_IDENTITY)
+        val executor = Executors.newSingleThreadExecutor()
+        val renderCount = AtomicInteger(0)
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Int> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Int) {
+                    canvas.drawColor(param)
+                    renderCount.incrementAndGet()
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    // NO-OP
+                }
+            })
+        try {
+            renderer.render(Color.RED)
+            renderer.render(Color.BLUE)
+            renderer.render(Color.YELLOW)
+        } finally {
+            val latch = CountDownLatch(1)
+            renderer.release(false) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+            assertEquals(3, renderCount.get())
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    private fun testRenderWithTransform(
+        transform: Int,
+        actualColors: RectColors,
+        expectedColors: RectColors
+    ) {
+        val transformer = BufferTransformer()
+        transformer.computeTransform(TEST_WIDTH, TEST_HEIGHT, transform)
+        val executor = Executors.newSingleThreadExecutor()
+        var buffer: HardwareBuffer? = null
+        val renderLatch = CountDownLatch(1)
+        val renderer = SingleBufferedCanvasRendererV29(
+            TEST_WIDTH,
+            TEST_HEIGHT,
+            transformer,
+            executor,
+            object : SingleBufferedCanvasRenderer.RenderCallbacks<Int> {
+                override fun render(canvas: Canvas, width: Int, height: Int, param: Int) {
+                    drawSquares(
+                        canvas,
+                        width,
+                        height,
+                        actualColors.topLeft,
+                        actualColors.topRight,
+                        actualColors.bottomLeft,
+                        actualColors.bottomRight
+                    )
+                }
+
+                override fun onBufferReady(
+                    hardwareBuffer: HardwareBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    syncFenceCompat?.awaitForever()
+                    buffer = hardwareBuffer
+                    renderLatch.countDown()
+                }
+            })
+        try {
+            renderer.render(0)
+            assertTrue(renderLatch.await(3000, TimeUnit.MILLISECONDS))
+            assertNotNull(buffer)
+            val colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB)
+            val bitmap = Bitmap.wrapHardwareBuffer(buffer!!, colorSpace)
+                ?.copy(Bitmap.Config.ARGB_8888, false)
+            assertNotNull(bitmap)
+            bitmap!!.verifyQuadrants(
+                expectedColors.topLeft,
+                expectedColors.topRight,
+                expectedColors.bottomLeft,
+                expectedColors.bottomRight
+            )
+        } finally {
+            val latch = CountDownLatch(1)
+            renderer.release(true) {
+                executor.shutdownNow()
+                latch.countDown()
+            }
+            assertTrue(latch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
index bd9b975..a03d42d 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
@@ -40,12 +40,14 @@
 import androidx.annotation.RequiresApi
 import androidx.annotation.WorkerThread
 import androidx.graphics.SurfaceTextureRenderer
+import androidx.graphics.isAllColor
 import androidx.graphics.lowlatency.LineRenderer
 import androidx.graphics.lowlatency.Rectangle
 import androidx.hardware.SyncFenceCompat
 import androidx.graphics.opengl.egl.EGLManager
 import androidx.graphics.opengl.egl.EGLSpec
 import androidx.graphics.opengl.egl.supportsNativeAndroidFence
+import androidx.graphics.verifyQuadrants
 import androidx.lifecycle.Lifecycle.State
 import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -948,8 +950,6 @@
                 val surface = Surface(surfaceTexture)
                 val canvas = surface.lockCanvas(null)
                 canvas.save()
-                // GL is flipped vertically from Android's canvas so flip the canvas here
-                canvas.scale(1f, -1f, width / 2f, height / 2f)
                 val paint = Paint()
                 // top left
                 canvas.drawRect(0f, 0f, width / 2f, height / 2f,
@@ -1055,9 +1055,6 @@
         val frameHandler = Handler(frameHandlerThread.looper)
         val renderNode = RenderNode("node").apply {
             setPosition(0, 0, width, height)
-            scaleY = -1f
-            pivotX = width / 2f
-            pivotY = height / 2f
             val canvas = beginRecording()
             val paint = Paint()
             // top left
@@ -1342,44 +1339,6 @@
         assertTrue(copyLatch.await(3000, TimeUnit.MILLISECONDS))
     }
 
-    private fun Bitmap.isAllColor(targetColor: Int): Boolean {
-        for (i in 0 until width) {
-            for (j in 0 until height) {
-                if (getPixel(i, j) != targetColor) {
-                    return false
-                }
-            }
-        }
-        return true
-    }
-
-    private fun Bitmap.verifyQuadrants(
-        topLeft: Int,
-        topRight: Int,
-        bottomLeft: Int,
-        bottomRight: Int
-    ) {
-        assertEquals(topLeft, getPixel(0, 0))
-        assertEquals(topLeft, getPixel(width / 2 - 1, 0))
-        assertEquals(topLeft, getPixel(width / 2 - 1, height / 2 - 1))
-        assertEquals(topLeft, getPixel(0, height / 2 - 1))
-
-        assertEquals(topRight, getPixel(width / 2 + 1, 0))
-        assertEquals(topRight, getPixel(width - 1, 0))
-        assertEquals(topRight, getPixel(width - 1, height / 2 - 1))
-        assertEquals(topRight, getPixel(width / 2 + 1, height / 2 - 1))
-
-        assertEquals(bottomLeft, getPixel(0, height / 2 + 1))
-        assertEquals(bottomLeft, getPixel(width / 2 - 1, height / 2 + 1))
-        assertEquals(bottomLeft, getPixel(width / 2 - 1, height - 1))
-        assertEquals(bottomLeft, getPixel(0, height - 1))
-
-        assertEquals(bottomRight, getPixel(width / 2 + 1, height / 2 + 1))
-        assertEquals(bottomRight, getPixel(width - 1, height / 2 + 1))
-        assertEquals(bottomRight, getPixel(width - 1, height - 1))
-        assertEquals(bottomRight, getPixel(width / 2 + 1, height - 1))
-    }
-
     private fun genTexture(): Int {
         val buffer = IntArray(1)
         GLES20.glGenTextures(1, buffer, 0)
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
index 09d8470..482afc6 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncStrategyTest.kt
@@ -16,19 +16,15 @@
 
 package androidx.graphics.opengl
 
-import android.opengl.EGL14
 import android.os.Build
 import androidx.annotation.RequiresApi
 import androidx.graphics.lowlatency.FrontBufferSyncStrategy
 import androidx.graphics.lowlatency.FrontBufferUtils
-import androidx.graphics.opengl.egl.EGLConfigAttributes
-import androidx.graphics.opengl.egl.EGLManager
 import androidx.graphics.opengl.egl.EGLSpec
-import androidx.graphics.opengl.egl.EGLVersion
 import androidx.graphics.opengl.egl.supportsNativeAndroidFence
+import androidx.graphics.withEgl
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import org.junit.Assert
 import org.junit.Assert.assertTrue
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -101,37 +97,4 @@
             }
         }
     }
-
-    private fun withEgl(block: (egl: EGLManager) -> Unit) {
-        val egl = createAndSetupEGLManager(EGLSpec.V14)
-        try {
-            block(egl)
-        } finally {
-            releaseEGLManager(egl)
-        }
-    }
-
-    // Helper method to create and initialize an EGLManager
-    fun createAndSetupEGLManager(eglSpec: EGLSpec = EGLSpec.V14): EGLManager {
-        val egl = EGLManager(eglSpec)
-        Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
-        Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
-
-        egl.initialize()
-
-        val config = egl.loadConfig(EGLConfigAttributes.RGBA_8888)
-        if (config == null) {
-            Assert.fail("Config 888 should be supported")
-        }
-
-        egl.createContext(config!!)
-        return egl
-    }
-
-    // Helper method to release EGLManager
-    fun releaseEGLManager(egl: EGLManager) {
-        egl.release()
-        Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
-        Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
-    }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt
new file mode 100644
index 0000000..a9feab6
--- /dev/null
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.graphics
+
+import android.annotation.SuppressLint
+import android.graphics.HardwareRenderer
+import android.graphics.PixelFormat
+import android.graphics.RenderNode
+import android.hardware.HardwareBuffer
+import android.media.ImageReader
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import java.util.concurrent.Executor
+
+/**
+ * Helper class used to draw RenderNode content into a HardwareBuffer instance. The contents of the
+ * HardwareBuffer are not persisted across renders.
+ */
+@RequiresApi(Build.VERSION_CODES.Q)
+internal class MultiBufferedCanvasRenderer(
+    private val renderNode: RenderNode,
+    width: Int,
+    height: Int,
+    format: Int = PixelFormat.RGBA_8888,
+    usage: Long = HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT,
+    maxImages: Int = 2
+) {
+    // PixelFormat.RGBA_8888 should be accepted here but Android Studio flags as a warning
+    @SuppressLint("WrongConstant")
+    private val mImageReader = ImageReader.newInstance(width, height, format, maxImages, usage)
+    private var mHardwareRenderer: HardwareRenderer? = HardwareRenderer().apply {
+        setContentRoot(renderNode)
+        setSurface(mImageReader.surface)
+        start()
+    }
+
+    private var mIsReleased = false
+
+    fun renderFrame(executor: Executor, bufferAvailable: (HardwareBuffer) -> Unit) {
+        val renderer = mHardwareRenderer
+        if (renderer != null && !mIsReleased) {
+            with(renderer) {
+                createRenderRequest()
+                    .setFrameCommitCallback(executor) {
+                        val nextImage = mImageReader.acquireNextImage()
+                        nextImage?.let { image ->
+                            val buffer = image.hardwareBuffer
+                            if (buffer != null) {
+                                executor.execute {
+                                    bufferAvailable(buffer)
+                                }
+                            }
+                            image.close()
+                        }
+                    }
+                    .syncAndDraw()
+            }
+        } else {
+            Log.v(TAG, "mHardwareRenderer is null")
+        }
+    }
+
+    fun release() {
+        if (!mIsReleased) {
+            mImageReader.close()
+            mHardwareRenderer?.let { renderer ->
+                renderer.stop()
+                renderer.destroy()
+            }
+            mHardwareRenderer = null
+            mIsReleased = true
+        }
+    }
+
+    internal companion object {
+        const val TAG = "MultiBufferRenderer"
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/ParamQueue.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/ParamQueue.kt
index a0b1765..167bd13 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/ParamQueue.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/ParamQueue.kt
@@ -80,4 +80,8 @@
             mParams.add(param)
         }
     }
+
+    fun count(): Int = mLock.withLock { mParams.size }
+
+    fun isEmpty() = count() == 0
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRenderer.kt
new file mode 100644
index 0000000..8a66107
--- /dev/null
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRenderer.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.graphics.lowlatency
+
+import android.graphics.Canvas
+import android.hardware.HardwareBuffer
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.annotation.WorkerThread
+import androidx.hardware.SyncFenceCompat
+import java.util.concurrent.Executor
+
+/**
+ * Interface to provide an abstraction around implementations for a low latency hardware
+ * accelerated [Canvas] that provides a [HardwareBuffer] with the [Canvas] rendered scene
+ */
+internal interface SingleBufferedCanvasRenderer<T> {
+
+    interface RenderCallbacks<T> {
+        @WorkerThread
+        fun render(canvas: Canvas, width: Int, height: Int, param: T)
+
+        @WorkerThread
+        fun onBufferReady(hardwareBuffer: HardwareBuffer, syncFenceCompat: SyncFenceCompat?)
+    }
+
+    /**
+     * Render into the [HardwareBuffer] with the given parameter and bounds
+     */
+    fun render(param: T)
+
+    /**
+     * Flag to indicate whether or not the contents of the [SingleBufferedCanvasRenderer] are visible.
+     * This is used to help internal state to determine appropriate synchronization
+     */
+    var isVisible: Boolean
+
+    /**
+     * Releases resources associated with [SingleBufferedCanvasRenderer] instance. Attempts to
+     * use this object after it is closed will be ignored
+     */
+    fun release(cancelPending: Boolean, onReleaseComplete: (() -> Unit)? = null)
+
+    /**
+     * Clear the contents of the [HardwareBuffer]
+     */
+    fun clear()
+
+    /**
+     * Cancel all pending render requests
+     */
+    fun cancelPending()
+
+    companion object {
+
+        @RequiresApi(Build.VERSION_CODES.Q)
+        fun <T> create(
+            width: Int,
+            height: Int,
+            bufferTransformer: BufferTransformer,
+            executor: Executor,
+            bufferReadyListener: RenderCallbacks<T>
+        ): SingleBufferedCanvasRenderer<T> {
+            // TODO return different instance for corresponding platform version
+            return SingleBufferedCanvasRendererV29(
+                width,
+                height,
+                bufferTransformer,
+                executor,
+                bufferReadyListener
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt
new file mode 100644
index 0000000..2227aa8
--- /dev/null
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt
@@ -0,0 +1,270 @@
+/*
+ * 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.graphics.lowlatency
+
+import android.graphics.Canvas
+import android.graphics.SurfaceTexture
+import android.hardware.HardwareBuffer
+import android.opengl.GLES20
+import android.opengl.Matrix
+import android.os.Build
+import android.util.Log
+import androidx.annotation.RequiresApi
+import androidx.graphics.lowlatency.FrontBufferUtils.Companion.obtainHardwareBufferUsageFlags
+import androidx.graphics.opengl.FrameBuffer
+import androidx.graphics.opengl.FrameBufferRenderer
+import androidx.graphics.opengl.GLRenderer
+import androidx.graphics.opengl.QuadTextureRenderer
+import androidx.graphics.opengl.egl.EGLManager
+import androidx.graphics.opengl.egl.EGLSpec
+import androidx.hardware.SyncFenceCompat
+import java.nio.IntBuffer
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicBoolean
+
+@RequiresApi(Build.VERSION_CODES.Q)
+internal class SingleBufferedCanvasRendererV29<T>(
+    private val width: Int,
+    private val height: Int,
+    private val bufferTransformer: BufferTransformer,
+    private val executor: Executor,
+    private val callbacks: SingleBufferedCanvasRenderer.RenderCallbacks<T>,
+) : SingleBufferedCanvasRenderer<T> {
+
+    private val mProducer = TextureProducer<T>(
+        width,
+        height,
+        object : TextureProducer.Callbacks<T> {
+            override fun onTextureAvailable(texture: SurfaceTexture) {
+                mSurfaceTexture = texture
+                mFrameBufferTarget.requestRender()
+            }
+
+            override fun render(canvas: Canvas, width: Int, height: Int, param: T) {
+                callbacks.render(canvas, width, height, param)
+            }
+        })
+
+    /**
+     * Source SurfaceTexture that the destination of content to be rendered from the provided
+     * RenderNode
+     */
+    private var mSurfaceTexture: SurfaceTexture? = null
+
+    /**
+     * HardwareBuffer flags for front buffered rendering
+     */
+    private val mHardwareBufferUsageFlags = obtainHardwareBufferUsageFlags()
+
+    // ---------- GLThread ------
+
+    /**
+     * [FrontBufferSyncStrategy] used for [FrameBufferRenderer] to conditionally decide
+     * when to create a [SyncFenceCompat] for transaction calls.
+     */
+    private val mFrontBufferSyncStrategy = FrontBufferSyncStrategy(mHardwareBufferUsageFlags)
+
+    /**
+     * Shader that handles rendering a texture as a quad into the destination
+     */
+    private var mQuadRenderer: QuadTextureRenderer? = null
+
+    /**
+     * Texture id of the SurfaceTexture that is to be rendered
+     */
+    private var mTextureId: Int = -1
+
+    /**
+     * Scratch buffer used for gen/delete texture operations
+     */
+    private val buffer = IntArray(1)
+
+    // ---------- GLThread ------
+
+    private val mFrameBufferRenderer = FrameBufferRenderer(
+        object : FrameBufferRenderer.RenderCallback {
+
+            private val mMVPMatrix = FloatArray(16)
+            private val mProjection = FloatArray(16)
+
+            private fun obtainQuadRenderer(): QuadTextureRenderer =
+                mQuadRenderer ?: QuadTextureRenderer().apply {
+                    GLES20.glGenTextures(1, buffer, 0)
+                    mTextureId = buffer[0]
+                    mSurfaceTexture?.let { texture ->
+                        texture.attachToGLContext(mTextureId)
+                        setSurfaceTexture(texture)
+                    }
+                    mQuadRenderer = this
+                }
+
+            override fun obtainFrameBuffer(egl: EGLSpec): FrameBuffer {
+                return mFrontBufferLayer ?: FrameBuffer(
+                    egl,
+                    HardwareBuffer.create(
+                        bufferTransformer.glWidth,
+                        bufferTransformer.glHeight,
+                        HardwareBuffer.RGBA_8888,
+                        1,
+                        mHardwareBufferUsageFlags
+                    )
+                ).also { mFrontBufferLayer = it }
+            }
+
+            @RequiresApi(Build.VERSION_CODES.S)
+            override fun onDraw(eglManager: EGLManager) {
+                mSurfaceTexture?.let { texture ->
+                    val bufferWidth = bufferTransformer.glWidth
+                    val bufferHeight = bufferTransformer.glHeight
+                    GLES20.glViewport(0, 0, bufferWidth, bufferHeight)
+                    Matrix.orthoM(
+                        mMVPMatrix,
+                        0,
+                        0f,
+                        bufferWidth.toFloat(),
+                        0f,
+                        bufferHeight.toFloat(),
+                        -1f,
+                        1f
+                    )
+
+                    Matrix.multiplyMM(mProjection, 0, mMVPMatrix, 0, bufferTransformer.transform, 0)
+                    // texture.updateTexImage is called within QuadTextureRenderer#draw
+                    obtainQuadRenderer().draw(mProjection, width.toFloat(), height.toFloat())
+                    texture.releaseTexImage()
+                    mProducer.markTextureConsumed()
+                }
+            }
+
+            override fun onDrawComplete(
+                frameBuffer: FrameBuffer,
+                syncFenceCompat: SyncFenceCompat?
+            ) {
+                if (forceFlush.get()) {
+                    // See b/236394768. On some ANGLE versions, attempting to do a glClear + flush
+                    // does not actually flush pixels to FBOs with HardwareBuffer attachments
+                    // For testing purposes when verifying clear use cases, do a GPU readback
+                    // to actually executed any pending clear operations to verify output
+                    GLES20.glReadPixels(0, 0, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
+                        IntBuffer.wrap(IntArray(1)))
+                }
+
+                mProducer.execute {
+                    callbacks.onBufferReady(frameBuffer.hardwareBuffer, syncFenceCompat)
+                }
+            }
+        },
+        mFrontBufferSyncStrategy
+    )
+
+    /**
+     * [GLRenderer] used to render contents of the SurfaceTexture into a HardwareBuffer
+     */
+    private val mGLRenderer = GLRenderer().apply { start() }
+
+    private var mFrameBufferTarget: GLRenderer.RenderTarget =
+        mGLRenderer.createRenderTarget(width, height, mFrameBufferRenderer)
+
+    /**
+     * Flag to maintain visibility state on the main thread
+     */
+    private var mIsVisible = false
+
+    /**
+     * Flag to determine if the SingleBufferedCanvasRenderer instance has been released
+     */
+    private var mIsReleased = false
+
+    override var isVisible: Boolean
+        set(value) {
+            mGLRenderer.execute {
+                mFrontBufferSyncStrategy.isVisible = value
+            }
+            mIsVisible = value
+        }
+        get() = mFrontBufferSyncStrategy.isVisible
+
+    private var mFrontBufferLayer: FrameBuffer? = null
+
+    override fun render(param: T) {
+        if (!mIsReleased) {
+            mProducer.requestRender(param)
+        } else {
+            Log.w(TAG, "Attempt to render with CanvasRenderer that has already been released")
+        }
+    }
+
+    override fun release(cancelPending: Boolean, onReleaseComplete: (() -> Unit)?) {
+        if (!mIsReleased) {
+            if (cancelPending) {
+                mProducer.cancelPending()
+            }
+            mProducer.release(cancelPending) {
+                // If the producer is torn down after all pending requests are completed
+                // then there is nothing left for the render target to consume so
+                // detach immediately
+                mFrameBufferTarget.detach(true) {
+                    // GL Thread
+                    mQuadRenderer?.release()
+                    if (mTextureId != -1) {
+                        buffer[0] = mTextureId
+                        GLES20.glDeleteTextures(1, buffer, 0)
+                        mTextureId = -1
+                    }
+                }
+                mGLRenderer.stop(true)
+                onReleaseComplete?.invoke()
+           }
+
+            mIsReleased = true
+        } else {
+            Log.w(TAG, "Attempt to release CanvasRenderer that has already been released")
+        }
+    }
+
+    private val mClearRunnable = Runnable {
+        mFrameBufferRenderer.clear()
+        mFrameBufferTarget.requestRender()
+    }
+
+    override fun cancelPending() {
+        if (!mIsReleased) {
+            mProducer.cancelPending()
+        } else {
+            Log.w(TAG, "Attempt to cancel pending requests when the CanvasRender has " +
+                "already been released")
+        }
+    }
+
+    override fun clear() {
+        if (!mIsReleased) {
+            mProducer.execute(mClearRunnable)
+        } else {
+            Log.w(TAG, "Attempt to clear contents when the CanvasRenderer has already " +
+                "been released")
+        }
+    }
+
+    // See: b/236394768. Some test emulator instances have not picked up the fix so
+    // apply a workaround here for testing purposes
+    internal val forceFlush = AtomicBoolean(false)
+
+    private companion object {
+
+        const val TAG = "SingleBufferedCanvasV29"
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/TextureProducer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/TextureProducer.kt
new file mode 100644
index 0000000..ce14f61
--- /dev/null
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/TextureProducer.kt
@@ -0,0 +1,200 @@
+/*
+ * 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.graphics.lowlatency
+
+import android.graphics.Canvas
+import android.graphics.RenderNode
+import android.graphics.SurfaceTexture
+import android.os.Build
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Message
+import androidx.annotation.AnyThread
+import androidx.annotation.RequiresApi
+import androidx.annotation.WorkerThread
+import androidx.graphics.SurfaceTextureRenderer
+
+/**
+ * Class responsible for the producing side of SurfaceTextures that are rendered with content
+ * provided from a canvas. This class handles proxying all requests to an internal thread
+ * as well as throttles production of frames based on consumption rate.
+ */
+@RequiresApi(Build.VERSION_CODES.Q)
+internal class TextureProducer<T>(
+    val width: Int,
+    val height: Int,
+    val callbacks: Callbacks<T>
+) {
+
+    interface Callbacks<T> {
+        fun onTextureAvailable(texture: SurfaceTexture)
+
+        fun render(canvas: Canvas, width: Int, height: Int, param: T)
+    }
+
+    private var mIsReleasing = false
+    private var mReleaseCallback: (() -> Unit)? = null
+    private val mParams = ArrayList<T>()
+    private var mPendingRenders = 0
+    private val mProducerThread = HandlerThread("producerThread").apply { start() }
+    @Suppress("UNCHECKED_CAST")
+    private val mProducerHandler = Handler(mProducerThread.looper) { message ->
+        when (message.what) {
+            RENDER -> {
+                if (!mIsReleasing) {
+                    val param = message.obj as T
+                    mParams.add(param)
+                    doRender()
+                }
+            }
+            TEXTURE_CONSUMED -> {
+                mPendingRenders--
+                if (mIsReleasing && !isPendingRendering()) {
+                    teardown()
+                } else {
+                    doRender()
+                }
+            }
+            CANCEL_PENDING -> {
+                mParams.clear()
+            }
+            RELEASE -> {
+                mIsReleasing = true
+                mReleaseCallback = message.obj as (() -> Unit)?
+                if (!isPendingRendering()) {
+                    teardown()
+                }
+            }
+        }
+        true
+    }
+
+    @WorkerThread // ProducerThread
+    private fun teardown() {
+        mReleaseCallback?.invoke()
+        mSurfaceTextureRenderer.release()
+        mProducerThread.quit()
+    }
+
+    @WorkerThread // ProducerThread
+    private fun isPendingRendering() = mParams.isNotEmpty() || mPendingRenders > 0
+
+    private val mRenderNode = RenderNode("node").apply {
+        setPosition(
+            0,
+            0,
+            this@TextureProducer.width,
+            this@TextureProducer.height
+        )
+    }
+
+    private inline fun RenderNode.record(block: (Canvas) -> Unit) {
+        val canvas = beginRecording()
+        block(canvas)
+        endRecording()
+    }
+
+    private val mSurfaceTextureRenderer = SurfaceTextureRenderer(
+        mRenderNode,
+        width,
+        height,
+        mProducerHandler
+    ) { texture ->
+        callbacks.onTextureAvailable(texture)
+    }
+
+    @WorkerThread // ProducerThread
+    private fun doRender() {
+        if (mPendingRenders < MAX_PENDING_RENDERS) {
+            if (mParams.isNotEmpty()) {
+                mRenderNode.record { canvas ->
+                    for (p in mParams) {
+                        callbacks.render(canvas, width, height, p)
+                    }
+                }
+                mParams.clear()
+                mPendingRenders++
+                mSurfaceTextureRenderer.renderFrame()
+            }
+        }
+    }
+
+    @AnyThread
+    fun requestRender(param: T) {
+        mProducerHandler.sendMessage(Message.obtain(mProducerHandler, RENDER, param))
+    }
+
+    @AnyThread
+    fun cancelPending() {
+        mProducerHandler.removeMessages(RENDER)
+        mProducerHandler.sendMessage(Message.obtain(mProducerHandler, CANCEL_PENDING))
+    }
+
+    @AnyThread
+    fun markTextureConsumed() {
+        mProducerHandler.sendMessage(Message.obtain(mProducerHandler, TEXTURE_CONSUMED))
+    }
+
+    @AnyThread
+    fun execute(runnable: Runnable) {
+        mProducerHandler.post(runnable)
+    }
+
+    @AnyThread
+    fun remove(runnable: Runnable) {
+        mProducerHandler.removeCallbacks(runnable)
+    }
+
+    @AnyThread
+    fun release(cancelPending: Boolean, onReleaseComplete: (() -> Unit)? = null) {
+        if (cancelPending) {
+            cancelPending()
+        }
+        mProducerHandler.sendMessage(Message.obtain(mProducerHandler, RELEASE, onReleaseComplete))
+    }
+
+    private companion object {
+        /**
+         * Constant to indicate a request to render new content into a SurfaceTexture
+         * for consumption.
+         */
+        const val RENDER = 0
+
+        /**
+         * Constant to indicate that a previously produced frame has been consumed.
+         */
+        const val TEXTURE_CONSUMED = 1
+
+        /**
+         * Cancel all pending requests to render and clear all parameters that are to be consumed
+         * for an upcoming frame
+         */
+        const val CANCEL_PENDING = 2
+
+        /**
+         * Release the resources associated with this [TextureProducer] instance
+         */
+        const val RELEASE = 3
+
+        /**
+         * Maximum number of frames to produce before the producer pauses. Subsequent attempts
+         * to render will batch parameters and continue to produce frames when the consumer
+         * signals that the corresponding textures have been consumed.
+         */
+        const val MAX_PENDING_RENDERS = 2
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/QuadTextureRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/QuadTextureRenderer.kt
index c45e203..f838ec4 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/opengl/QuadTextureRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/opengl/QuadTextureRenderer.kt
@@ -260,7 +260,7 @@
             void main(void)
             {
                 gl_Position = $uVPMatrix * $aPosition;
-                $vTexCoord = vec2($tVPMatrix * vec4($aTexCoord, 1.0, 1.0));
+                $vTexCoord = vec2($tVPMatrix * vec4($aTexCoord.x, 1.0 - $aTexCoord.y, 1.0, 1.0));
             }
             """
 
diff --git a/gridlayout/OWNERS b/gridlayout/OWNERS
index c352bd1..235f0c3 100644
--- a/gridlayout/OWNERS
+++ b/gridlayout/OWNERS
@@ -1,2 +1,4 @@
 # Bug component: 461201
 alanv@google.com
+aelias@google.com
+ryanmentley@google.com
diff --git a/health/connect/connect-client-proto/src/main/proto/data.proto b/health/connect/connect-client-proto/src/main/proto/data.proto
index b5e10a0..8dac6c6 100644
--- a/health/connect/connect-client-proto/src/main/proto/data.proto
+++ b/health/connect/connect-client-proto/src/main/proto/data.proto
@@ -56,7 +56,7 @@
   optional int64 end_time_millis = 3;
 }
 
-// Next Id: 22
+// Next Id: 23
 message DataPoint {
   optional DataType data_type = 1;
   map<string, Value> values = 2;
@@ -90,7 +90,9 @@
   optional int32 start_zone_offset_seconds = 19;
   optional int32 end_zone_offset_seconds = 20;
 
-  optional SubTypeDataValue sub_type_data_values = 21;
+  reserved 21; // sub_type_data_values
+
+  map<string, SubTypeDataList> sub_type_data_lists = 22;
 
   message SubTypeDataList {
     repeated SubTypeDataValue values = 1;
diff --git a/health/health-services-client/OWNERS b/health/health-services-client/OWNERS
index 7079ccb..ff2eed8 100644
--- a/health/health-services-client/OWNERS
+++ b/health/health-services-client/OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 1126127
-aakanksha@google.com
 jlannin@google.com
 shobana@google.com
 smskelley@google.com
+sutterlin@google.com
diff --git a/inspection/OWNERS b/inspection/OWNERS
index 85c92a7..d238af3 100644
--- a/inspection/OWNERS
+++ b/inspection/OWNERS
@@ -1,3 +1,3 @@
+# Bug component: 1333602
 sergeyv@google.com
-davidherman@google.com
 yboyar@google.com
\ No newline at end of file
diff --git a/libraryversions.toml b/libraryversions.toml
index 333cc7a..09c3100 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -1,34 +1,31 @@
 [versions]
 ACTIVITY = "1.8.0-alpha02"
-ADS_IDENTIFIER = "1.0.0-alpha05"
+ADS_IDENTIFIER = "1.0.0-alpha06"
 ANNOTATION = "1.7.0-alpha01"
-ANNOTATION_KMP = "1.6.0-dev01"
 ANNOTATION_EXPERIMENTAL = "1.4.0-alpha01"
-ANNOTATION_EXPERIMENTAL_KMP = "1.4.0-dev01"
 APPACTIONS_INTERACTION = "1.0.0-alpha01"
 APPCOMPAT = "1.7.0-alpha03"
 APPSEARCH = "1.1.0-alpha03"
 ARCH_CORE = "2.3.0-alpha01"
 ASYNCLAYOUTINFLATER = "1.1.0-alpha02"
 AUTOFILL = "1.2.0-beta02"
-BENCHMARK = "1.2.0-alpha11"
+BENCHMARK = "1.2.0-alpha12"
 BIOMETRIC = "1.2.0-alpha06"
 BLUETOOTH = "1.0.0-alpha01"
 BROWSER = "1.6.0-alpha01"
 BUILDSRC_TESTS = "1.0.0-alpha01"
-CAMERA = "1.3.0-alpha04"
+CAMERA = "1.3.0-alpha05"
 CAMERA_PIPE = "1.0.0-alpha01"
 CARDVIEW = "1.1.0-alpha01"
 CAR_APP = "1.4.0-alpha01"
 COLLECTION = "1.3.0-alpha03"
-COLLECTION_KMP = "1.3.0-dev01"
 COMPOSE = "1.5.0-alpha01"
-COMPOSE_COMPILER = "1.4.3"
-COMPOSE_MATERIAL3 = "1.1.0-alpha08"
+COMPOSE_COMPILER = "1.4.4"
+COMPOSE_MATERIAL3 = "1.1.0-beta01"
 COMPOSE_RUNTIME_TRACING = "1.0.0-alpha03"
-CONSTRAINTLAYOUT = "2.2.0-alpha08"
-CONSTRAINTLAYOUT_COMPOSE = "1.1.0-alpha08"
-CONSTRAINTLAYOUT_CORE = "1.1.0-alpha08"
+CONSTRAINTLAYOUT = "2.2.0-alpha09"
+CONSTRAINTLAYOUT_COMPOSE = "1.1.0-alpha09"
+CONSTRAINTLAYOUT_CORE = "1.1.0-alpha09"
 CONTENTPAGER = "1.1.0-alpha01"
 COORDINATORLAYOUT = "1.3.0-alpha01"
 CORE = "1.11.0-alpha01"
@@ -43,29 +40,28 @@
 CORE_ROLE = "1.2.0-alpha01"
 CORE_SPLASHSCREEN = "1.1.0-alpha01"
 CORE_UWB = "1.0.0-alpha05"
-CREDENTIALS = "1.0.0-alpha04"
+CREDENTIALS = "1.0.0-alpha05"
 CURSORADAPTER = "1.1.0-alpha01"
 CUSTOMVIEW = "1.2.0-alpha03"
 CUSTOMVIEW_POOLINGCONTAINER = "1.1.0-alpha01"
 DATASTORE = "1.1.0-alpha02"
-DATASTORE_KMP = "1.1.0-dev01"
 DOCUMENTFILE = "1.1.0-alpha02"
 DRAGANDDROP = "1.1.0-alpha01"
-DRAWERLAYOUT = "1.2.0-rc01"
+DRAWERLAYOUT = "1.3.0-alpha01"
 DYNAMICANIMATION = "1.1.0-alpha04"
 DYNAMICANIMATION_KTX = "1.0.0-alpha04"
 EMOJI = "1.2.0-alpha03"
-EMOJI2 = "1.3.0-rc01"
+EMOJI2 = "1.4.0-alpha01"
 EMOJI2_QUARANTINE = "1.0.0-alpha03"
 ENTERPRISE = "1.1.0-rc01"
 EXIFINTERFACE = "1.4.0-alpha01"
-FRAGMENT = "1.6.0-alpha07"
+FRAGMENT = "1.6.0-alpha08"
 FUTURES = "1.2.0-alpha01"
 GLANCE = "1.0.0-alpha06"
 GLANCE_TEMPLATE = "1.0.0-alpha01"
 GRAPHICS_CORE = "1.0.0-alpha03"
-GRAPHICS_SHAPES = "1.0.0-alpha01"
 GRAPHICS_FILTERS = "1.0.0-alpha01"
+GRAPHICS_SHAPES = "1.0.0-alpha01"
 GRIDLAYOUT = "1.1.0-alpha01"
 HEALTH_CONNECT = "1.0.0-alpha11"
 HEALTH_SERVICES_CLIENT = "1.0.0-beta03"
@@ -90,19 +86,19 @@
 MEDIA2 = "1.3.0-alpha01"
 MEDIAROUTER = "1.4.0-beta02"
 METRICS = "1.0.0-alpha04"
-NAVIGATION = "2.6.0-alpha07"
+NAVIGATION = "2.6.0-alpha08"
 PAGING = "3.2.0-alpha05"
 PAGING_COMPOSE = "1.0.0-alpha19"
 PALETTE = "1.1.0-alpha01"
 PERCENTLAYOUT = "1.1.0-alpha01"
 PREFERENCE = "1.3.0-alpha01"
 PRINT = "1.1.0-beta01"
-PRIVACYSANDBOX_ADS = "1.0.0-beta01"
+PRIVACYSANDBOX_ADS = "1.0.0-beta02"
 PRIVACYSANDBOX_PLUGINS = "1.0.0-alpha01"
-PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha01"
-PRIVACYSANDBOX_TOOLS = "1.0.0-alpha03"
-PRIVACYSANDBOX_UI = "1.0.0-alpha01"
-PROFILEINSTALLER = "1.3.0-rc01"
+PRIVACYSANDBOX_SDKRUNTIME = "1.0.0-alpha02"
+PRIVACYSANDBOX_TOOLS = "1.0.0-alpha04"
+PRIVACYSANDBOX_UI = "1.0.0-alpha02"
+PROFILEINSTALLER = "1.4.0-alpha01"
 RECOMMENDATION = "1.1.0-alpha01"
 RECYCLERVIEW = "1.4.0-alpha01"
 RECYCLERVIEW_SELECTION = "1.2.0-alpha02"
@@ -130,10 +126,10 @@
 TESTSCREENSHOT = "1.0.0-alpha01"
 TEST_UIAUTOMATOR = "2.3.0-alpha03"
 TEXT = "1.0.0-alpha01"
-TRACING = "1.2.0-beta01"
-TRACING_PERFETTO = "1.0.0-alpha12"
+TRACING = "1.2.0-beta02"
+TRACING_PERFETTO = "1.0.0-alpha13"
 TRANSITION = "1.5.0-alpha01"
-TV = "1.0.0-alpha04"
+TV = "1.0.0-alpha05"
 TVPROVIDER = "1.1.0-alpha02"
 VECTORDRAWABLE = "1.2.0-beta02"
 VECTORDRAWABLE_ANIMATED = "1.2.0-beta01"
@@ -148,9 +144,9 @@
 WEAR_INPUT_TESTING = "1.2.0-alpha03"
 WEAR_ONGOING = "1.1.0-alpha01"
 WEAR_PHONE_INTERACTIONS = "1.1.0-alpha04"
-WEAR_PROTOLAYOUT = "1.0.0-alpha05"
+WEAR_PROTOLAYOUT = "1.0.0-alpha06"
 WEAR_REMOTE_INTERACTIONS = "1.1.0-alpha01"
-WEAR_TILES = "1.2.0-alpha01"
+WEAR_TILES = "1.2.0-alpha02"
 WEAR_WATCHFACE = "1.2.0-alpha07"
 WEBKIT = "1.7.0-beta01"
 WINDOW = "1.1.0-beta01"
@@ -178,7 +174,7 @@
 CAMERA = { group = "androidx.camera", atomicGroupVersion = "versions.CAMERA" }
 CARDVIEW = { group = "androidx.cardview", atomicGroupVersion = "versions.CARDVIEW" }
 CAR_APP = { group = "androidx.car.app", atomicGroupVersion = "versions.CAR_APP" }
-COLLECTION = { group = "androidx.collection", atomicGroupVersion = "versions.COLLECTION", multiplatformGroupVersion = "versions.COLLECTION_KMP" }
+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" }
@@ -196,7 +192,7 @@
 CREDENTIALS = { group = "androidx.credentials", atomicGroupVersion = "versions.CREDENTIALS" }
 CURSORADAPTER = { group = "androidx.cursoradapter", atomicGroupVersion = "versions.CURSORADAPTER" }
 CUSTOMVIEW = { group = "androidx.customview" }
-DATASTORE = { group = "androidx.datastore", atomicGroupVersion = "versions.DATASTORE", multiplatformGroupVersion = "versions.DATASTORE_KMP" }
+DATASTORE = { group = "androidx.datastore", atomicGroupVersion = "versions.DATASTORE" }
 DOCUMENTFILE = { group = "androidx.documentfile", atomicGroupVersion = "versions.DOCUMENTFILE" }
 DRAGANDDROP = { group = "androidx.draganddrop", atomicGroupVersion = "versions.DRAGANDDROP" }
 DRAWERLAYOUT = { group = "androidx.drawerlayout", atomicGroupVersion = "versions.DRAWERLAYOUT" }
@@ -208,7 +204,7 @@
 FRAGMENT = { group = "androidx.fragment", atomicGroupVersion = "versions.FRAGMENT" }
 GLANCE = { group = "androidx.glance", atomicGroupVersion = "versions.GLANCE" }
 GLANCE_TEMPLATE = { group = "androidx.template", atomicGroupVersion = "versions.GLANCE_TEMPLATE" }
-GRAPHICS = { group = "androidx.graphics"}
+GRAPHICS = { group = "androidx.graphics" }
 GRAPHICS_FILTERS = { group = "androidx.graphics.filters", atomicGroupVersion = "versions.GRAPHICS_FILTERS" }
 GRIDLAYOUT = { group = "androidx.gridlayout", atomicGroupVersion = "versions.GRIDLAYOUT" }
 HEALTH = { group = "androidx.health" }
@@ -217,7 +213,7 @@
 HILT = { group = "androidx.hilt" }
 INPUT = { group = "androidx.input" }
 INSPECTION = { group = "androidx.inspection", atomicGroupVersion = "versions.INSPECTION" }
-INSPECTION_EXTENSIONS = { group = "androidx.inspection.extensions", atomicGroupVersion = "versions.SQLITE_INSPECTOR", overrideInclude = [ ":sqlite:sqlite-inspection"] }
+INSPECTION_EXTENSIONS = { group = "androidx.inspection.extensions", atomicGroupVersion = "versions.SQLITE_INSPECTOR", overrideInclude = [ ":sqlite:sqlite-inspection" ] }
 INTERPOLATOR = { group = "androidx.interpolator", atomicGroupVersion = "versions.INTERPOLATOR" }
 JAVASCRIPTENGINE = { group = "androidx.javascriptengine", atomicGroupVersion = "versions.JAVASCRIPTENGINE" }
 LEANBACK = { group = "androidx.leanback" }
diff --git a/lifecycle/lifecycle-common/api/current.txt b/lifecycle/lifecycle-common/api/current.txt
index 263aec8..c68d98d 100644
--- a/lifecycle/lifecycle-common/api/current.txt
+++ b/lifecycle/lifecycle-common/api/current.txt
@@ -14,8 +14,10 @@
     ctor public Lifecycle();
     method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver observer);
     method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> getCurrentStateFlow();
     method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     property @MainThread public abstract androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
   }
 
   public enum Lifecycle.Event {
diff --git a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
index 263aec8..c68d98d 100644
--- a/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-common/api/public_plus_experimental_current.txt
@@ -14,8 +14,10 @@
     ctor public Lifecycle();
     method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver observer);
     method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> getCurrentStateFlow();
     method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     property @MainThread public abstract androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
   }
 
   public enum Lifecycle.Event {
diff --git a/lifecycle/lifecycle-common/api/restricted_current.txt b/lifecycle/lifecycle-common/api/restricted_current.txt
index 440f8b9..634b76f 100644
--- a/lifecycle/lifecycle-common/api/restricted_current.txt
+++ b/lifecycle/lifecycle-common/api/restricted_current.txt
@@ -21,8 +21,10 @@
     ctor public Lifecycle();
     method @MainThread public abstract void addObserver(androidx.lifecycle.LifecycleObserver observer);
     method @MainThread public abstract androidx.lifecycle.Lifecycle.State getCurrentState();
+    method public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> getCurrentStateFlow();
     method @MainThread public abstract void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     property @MainThread public abstract androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
   }
 
   public enum Lifecycle.Event {
diff --git a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.kt b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.kt
index b52e8f5..ac586d8 100644
--- a/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.kt
+++ b/lifecycle/lifecycle-common/src/main/java/androidx/lifecycle/Lifecycle.kt
@@ -28,6 +28,9 @@
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.flowOn
 
@@ -95,6 +98,22 @@
     @get:MainThread
     public abstract val currentState: State
 
+    /**
+     * Returns a [StateFlow] where the [StateFlow.value] represents
+     * the current [State] of this Lifecycle.
+     *
+     * @return [StateFlow] where the [StateFlow.value] represents
+     * the current [State] of this Lifecycle.
+     */
+    public open val currentStateFlow: StateFlow<Lifecycle.State>
+        get() {
+            val mutableStateFlow = MutableStateFlow(currentState)
+            LifecycleEventObserver { _, event ->
+                mutableStateFlow.value = event.targetState
+            }.also { addObserver(it) }
+            return mutableStateFlow.asStateFlow()
+        }
+
     public enum class Event {
         /**
          * Constant for onCreate event of the [LifecycleOwner].
diff --git a/lifecycle/lifecycle-runtime-testing/src/test/java/androidx/lifecycle/testing/LifecycleRegistryTest.kt b/lifecycle/lifecycle-runtime-testing/src/test/java/androidx/lifecycle/testing/LifecycleRegistryTest.kt
index 00e71a8..6f0c1ec 100644
--- a/lifecycle/lifecycle-runtime-testing/src/test/java/androidx/lifecycle/testing/LifecycleRegistryTest.kt
+++ b/lifecycle/lifecycle-runtime-testing/src/test/java/androidx/lifecycle/testing/LifecycleRegistryTest.kt
@@ -18,19 +18,34 @@
 
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleRegistry
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
+@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
 @RunWith(JUnit4::class)
 class LifecycleRegistryTest {
-    @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
+
+    private val dispatcher = UnconfinedTestDispatcher()
     private val lifecycleOwner = TestLifecycleOwner(
         Lifecycle.State.INITIALIZED,
-        UnconfinedTestDispatcher()
+        dispatcher
     )
+    private val testScope = TestScope(dispatcher)
+
+    @Before
+    fun setMainDispatcher() {
+        Dispatchers.setMain(dispatcher)
+    }
 
     @Test
     fun getCurrentState() {
@@ -42,6 +57,79 @@
     }
 
     @Test
+    fun getCurrentStateFlow() {
+        val lifecycle = lifecycleOwner.lifecycle
+        assertThat(lifecycle.currentStateFlow.value).isEqualTo(Lifecycle.State.INITIALIZED)
+
+        lifecycleOwner.currentState = Lifecycle.State.CREATED
+        assertThat(lifecycle.currentStateFlow.value).isEqualTo(Lifecycle.State.CREATED)
+
+        lifecycleOwner.currentState = Lifecycle.State.DESTROYED
+        assertThat(lifecycle.currentStateFlow.value).isEqualTo(Lifecycle.State.DESTROYED)
+    }
+
+    @Test
+    fun getCurrentStateFlowWithReentranceNoObservers() = testScope.runTest {
+        val stateFlow = lifecycleOwner.lifecycle.currentStateFlow
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+        assertThat(stateFlow.value).isEqualTo(Lifecycle.State.INITIALIZED)
+
+        backgroundScope.launch {
+            stateFlow.collect {
+                lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
+            }
+        }
+
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.CREATED)
+        assertThat(stateFlow.value).isEqualTo(Lifecycle.State.CREATED)
+    }
+
+    @Test
+    fun getCurrentStateFlowWithObserverReentrance() = testScope.runTest {
+        val stateFlow = lifecycleOwner.lifecycle.currentStateFlow
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+        assertThat(stateFlow.value).isEqualTo(Lifecycle.State.INITIALIZED)
+
+        lifecycleOwner.lifecycle.addObserver(
+            LifecycleEventObserver { owner, _ ->
+                (owner.lifecycle as LifecycleRegistry)
+                    .handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
+            }
+        )
+
+        backgroundScope.launch {
+            stateFlow.collect {}
+        }
+
+        lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        assertThat(stateFlow.value).isEqualTo(Lifecycle.State.RESUMED)
+    }
+
+    @Test
+    fun getCurrentStateFlowWithObserverWithFlowReentrance() = testScope.runTest {
+        val stateFlow = lifecycleOwner.lifecycle.currentStateFlow
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+        assertThat(stateFlow.value).isEqualTo(Lifecycle.State.INITIALIZED)
+
+        lateinit var event: Lifecycle.Event
+        lifecycleOwner.lifecycle.addObserver(
+            LifecycleEventObserver { _, e ->
+                event = e
+            }
+        )
+
+        backgroundScope.launch {
+            stateFlow.collect {
+                lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
+            }
+        }
+
+        assertThat(lifecycleOwner.currentState).isEqualTo(Lifecycle.State.CREATED)
+        assertThat(event).isEqualTo(Lifecycle.Event.ON_CREATE)
+    }
+
+    @Test
     fun observerCount() {
         lifecycleOwner.currentState = Lifecycle.State.STARTED
         assertThat(lifecycleOwner.observerCount).isEqualTo(0)
diff --git a/lifecycle/lifecycle-runtime/api/current.txt b/lifecycle/lifecycle-runtime/api/current.txt
index e72bd60..b3a4ef0 100644
--- a/lifecycle/lifecycle-runtime/api/current.txt
+++ b/lifecycle/lifecycle-runtime/api/current.txt
@@ -12,6 +12,7 @@
     method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
     property public androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
     property public int observerCount;
     field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
   }
diff --git a/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
index e72bd60..b3a4ef0 100644
--- a/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-runtime/api/public_plus_experimental_current.txt
@@ -12,6 +12,7 @@
     method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
     property public androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
     property public int observerCount;
     field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
   }
diff --git a/lifecycle/lifecycle-runtime/api/restricted_current.txt b/lifecycle/lifecycle-runtime/api/restricted_current.txt
index 704cdb4..8cfc8dc 100644
--- a/lifecycle/lifecycle-runtime/api/restricted_current.txt
+++ b/lifecycle/lifecycle-runtime/api/restricted_current.txt
@@ -12,6 +12,7 @@
     method public void removeObserver(androidx.lifecycle.LifecycleObserver observer);
     method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
     property public androidx.lifecycle.Lifecycle.State currentState;
+    property public kotlinx.coroutines.flow.StateFlow<androidx.lifecycle.Lifecycle.State> currentStateFlow;
     property public int observerCount;
     field public static final androidx.lifecycle.LifecycleRegistry.Companion Companion;
   }
diff --git a/lifecycle/lifecycle-runtime/build.gradle b/lifecycle/lifecycle-runtime/build.gradle
index fbbd6f1..5199df9 100644
--- a/lifecycle/lifecycle-runtime/build.gradle
+++ b/lifecycle/lifecycle-runtime/build.gradle
@@ -21,7 +21,7 @@
     // necessary for IJ to resolve dependencies.
     api("androidx.annotation:annotation:1.1.0")
     implementation("androidx.arch.core:core-runtime:2.2.0")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     testImplementation(libs.junit)
     testImplementation(libs.mockitoCore4)
diff --git a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
index 8da7e1e..88f3480 100644
--- a/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
+++ b/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/LifecycleRegistry.kt
@@ -21,6 +21,9 @@
 import androidx.arch.core.executor.ArchTaskExecutor
 import androidx.arch.core.internal.FastSafeIterableMap
 import java.lang.ref.WeakReference
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 
 /**
  * An implementation of [Lifecycle] that can handle multiple observers.
@@ -106,6 +109,10 @@
             moveToState(state)
         }
 
+    private val _currentStateFlow: MutableStateFlow<State> = MutableStateFlow(State.INITIALIZED)
+    override val currentStateFlow: StateFlow<State>
+        get() = _currentStateFlow.asStateFlow()
+
     /**
      * Sets the current state and notifies the observers.
      *
@@ -288,6 +295,7 @@
             }
         }
         newEventOccurred = false
+        _currentStateFlow.value = currentState
     }
 
     @SuppressLint("RestrictedApi")
diff --git a/navigation/navigation-common/build.gradle b/navigation/navigation-common/build.gradle
index eff9ca8..72b827e 100644
--- a/navigation/navigation-common/build.gradle
+++ b/navigation/navigation-common/build.gradle
@@ -41,7 +41,7 @@
     api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1")
     implementation("androidx.core:core-ktx:1.1.0")
     implementation("androidx.collection:collection-ktx:1.1.0")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     api(libs.kotlinStdlib)
     testImplementation(project(":navigation:navigation-testing"))
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
index c9eda60..603e078 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
@@ -20,6 +20,7 @@
 import android.os.Bundle
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.Fragment
+import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.navigation.NavOptions
@@ -48,6 +49,8 @@
         fm?.executePendingTransactions()
         val fragment = fm?.findFragmentById(R.id.nav_host)
 
+        val oldEntry = navController.currentBackStackEntry
+
         navController.navigate(
             R.id.empty_fragment,
             null,
@@ -61,6 +64,13 @@
         assertWithMessage("Replacement should be a new instance")
             .that(replacementFragment)
             .isNotSameInstanceAs(fragment)
+
+        assertWithMessage("Old Entry should have been DESTROYED")
+            .that(oldEntry!!.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.DESTROYED)
+        assertWithMessage("New Entry should be RESUMED")
+            .that(navController.currentBackStackEntry!!.lifecycle.currentState)
+            .isEqualTo(Lifecycle.State.RESUMED)
     }
 
     @Test
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
index b55be87..79013ab 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/OnBackPressedTest.kt
@@ -23,14 +23,15 @@
 import androidx.navigation.fragment.test.NavigationActivityWithFragmentTag
 import androidx.navigation.fragment.test.NavigationBaseActivity
 import androidx.navigation.fragment.test.R
+import androidx.navigation.navOptions
 import androidx.test.core.app.ActivityScenario
 import androidx.test.filters.MediumTest
 import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertWithMessage
+import java.util.concurrent.TimeUnit
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
-import java.util.concurrent.TimeUnit
 
 @Suppress("DEPRECATION")
 @MediumTest
@@ -78,6 +79,58 @@
     }
 
     @Test
+    fun testOnBackPressedAfterNavigateWithAnimators() {
+        with(ActivityScenario.launch(activityClass)) {
+            withActivity {
+                navController.setGraph(R.navigation.nav_simple)
+                navController.navigate(R.id.empty_fragment, null, navOptions {
+                    anim {
+                        enter = R.animator.fade_enter
+                        exit = R.animator.fade_exit
+                        popEnter = R.animator.fade_enter
+                        popExit = R.animator.fade_exit
+                    }
+                })
+                onBackPressed()
+                assertWithMessage("onBackPressed() should trigger NavController.popBackStack()")
+                    .that(navController.currentDestination?.id)
+                    .isEqualTo(R.id.start_fragment)
+            }
+        }
+    }
+
+    @Test
+    fun testOnBackPressedAfterNavigatePopUpTo() {
+        with(ActivityScenario.launch(activityClass)) {
+            withActivity {
+                navController.setGraph(R.navigation.nav_simple)
+
+                val navigator = navController.navigatorProvider.getNavigator(
+                    FragmentNavigator::class.java
+                )
+                val fragment = supportFragmentManager.findFragmentById(R.id.nav_host)
+                navController.navigate(R.id.empty_fragment)
+                fragment?.childFragmentManager?.executePendingTransactions()
+
+                navController.navigate(R.id.empty_fragment_2, null,
+                    navOptions { popUpTo(R.id.empty_fragment) { inclusive = true } }
+                )
+                fragment?.childFragmentManager?.executePendingTransactions()
+
+                onBackPressed()
+                fragment?.childFragmentManager?.executePendingTransactions()
+
+                assertWithMessage("onBackPressed() should trigger NavController.popBackStack()")
+                    .that(navController.currentDestination?.id)
+                    .isEqualTo(R.id.start_fragment)
+                assertWithMessage("navigator back stack should contain 1 entry")
+                    .that(navigator.backStack.value.size)
+                    .isEqualTo(1)
+            }
+        }
+    }
+
+    @Test
     fun testOnBackPressedAfterNavigate_notDefaultNavHost() {
         with(ActivityScenario.launch(activityClass)) {
             val countDownLatch = withActivity {
diff --git a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
index 2c9cbe7..b7488b2 100644
--- a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
+++ b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
@@ -72,11 +72,6 @@
      */
     internal val backStack get() = state.backStack
 
-    /**
-     * Temporarily stores entries that need to attach observer on its fragment
-     */
-    private val toAttachObserver = mutableListOf<String>()
-
     private val fragmentObserver = object : LifecycleEventObserver {
         override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
             if (event == Lifecycle.Event.ON_DESTROY) {
@@ -98,9 +93,8 @@
 
         fragmentManager.addFragmentOnAttachListener { _, fragment ->
             fragment.viewLifecycleOwnerLiveData.observe(fragment) {
-                val needToAttach = toAttachObserver.remove(fragment.tag)
                 // attach observer unless it was already popped at this point
-                if (needToAttach && !entriesToPop.contains(fragment.tag)) {
+                if (!entriesToPop.contains(fragment.tag)) {
                     val entry = state.backStack.value.last { it.id == fragment.tag }
                     attachObserver(entry, fragment)
                 }
@@ -121,13 +115,9 @@
             override fun onBackStackChangeStarted(fragment: Fragment, pop: Boolean) {
                 // We only care about the pop case here since in the navigate case by the time
                 // we get here the fragment will have already been moved to STARTED.
-                // In the case of a pop, we move the top most entry from RESUMED to STARTED by
-                // calling prepareForTransition.
+                // In the case of a pop, we move the entries to STARTED
                 if (pop) {
-                    val entry = state.backStack.value.lastOrNull {
-                        it.id == fragment.tag &&
-                            it.lifecycle.currentState == Lifecycle.State.RESUMED
-                    }
+                    val entry = state.backStack.value.lastOrNull { it.id == fragment.tag }
                     entry?.let { state.prepareForTransition(it) }
                 }
             }
@@ -136,36 +126,25 @@
                 val entry = (state.backStack.value + state.transitionsInProgress.value).lastOrNull {
                     it.id == fragment.tag
                 }
-                if (entry != null && fragmentWasPopped(fragment, entry)) {
-                    entriesToPop.remove(entry.id)
-                } else if (entry != null && fragmentWasAdded(fragment)) {
-                    attachObserver(entry, fragment)
-                } else if (fragmentShouldBePopped(fragment, pop)) {
+                if (pop && entry != null) {
+                    // The entry has already been removed from the back stack so just remove it
+                    // from the list
+                    if (!state.backStack.value.contains(entry)) {
+                        // remove it so we don't falsely identify a direct call to popBackStack
+                        entriesToPop.remove(entry.id)
+                    }
                     // This is the case of system back where we will need to make the call to
                     // popBackStack. Otherwise, popBackStack was called directly and this should
                     // end up being a no-op.
-                    var entryToPop = state.backStack.value.last()
-                    popBackStack(entryToPop, false)
-                    // remove it so we don't falsely identify a direct call to popBackStack
-                    entriesToPop.remove(entryToPop.id)
+                    else if (entriesToPop.isEmpty() && fragment.isRemoving) {
+                        state.popWithTransition(entry, false)
+                    }
                 }
             }
-
-            fun fragmentWasPopped(fragment: Fragment, entry: NavBackStackEntry): Boolean {
-                return fragment.view != null && entriesToPop.contains(entry.id)
-            }
-
-            fun fragmentWasAdded(fragment: Fragment): Boolean {
-                return fragment.view != null && fragment.isAdded
-            }
-
-            fun fragmentShouldBePopped(fragment: Fragment, pop: Boolean): Boolean {
-                return pop && entriesToPop.isEmpty() && !fragment.isAdded
-            }
         })
     }
 
-    internal fun attachObserver(entry: NavBackStackEntry, fragment: Fragment) {
+    private fun attachObserver(entry: NavBackStackEntry, fragment: Fragment) {
         val viewLifecycle = fragment.viewLifecycleOwner.lifecycle
         val currentState = viewLifecycle.currentState
         // We only need to add observers while the viewLifecycle has not reached a final
@@ -184,6 +163,7 @@
                     // Once the lifecycle reaches DESTROYED, we can mark the transition
                     // complete and remove the observer.
                     if (event == Lifecycle.Event.ON_DESTROY) {
+                        entriesToPop.remove(entry.id)
                         state.markTransitionComplete(entry)
                         viewLifecycle.removeObserver(this)
                     }
@@ -328,9 +308,6 @@
 
         if (!initialNavigation) {
             ft.addToBackStack(entry.id)
-        } else {
-            // not added to backstack so we need to make sure we attach fragment observer later
-            toAttachObserver.add(entry.id)
         }
 
         if (navigatorExtras is Extras) {
diff --git a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.kt b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.kt
index 12a5047..b44887e 100644
--- a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.kt
+++ b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/NavHostFragment.kt
@@ -25,6 +25,7 @@
 import androidx.annotation.NavigationRes
 import androidx.annotation.RestrictTo
 import androidx.core.content.res.use
+import androidx.core.os.bundleOf
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentContainerView
@@ -74,8 +75,44 @@
  * coupling to the navigation host.
  */
 public open class NavHostFragment : Fragment(), NavHost {
-    private var navHostController: NavHostController? = null
-    private var isPrimaryBeforeOnCreate: Boolean? = null
+    internal val navHostController: NavHostController by lazy {
+        val context = checkNotNull(context) {
+            "NavController cannot be created before the fragment is attached"
+        }
+        NavHostController(context).apply {
+            setLifecycleOwner(this@NavHostFragment)
+            setViewModelStore(viewModelStore)
+            onCreateNavHostController(this)
+            savedStateRegistry.consumeRestoredStateForKey(KEY_NAV_CONTROLLER_STATE)?.let {
+                restoreState(it)
+            }
+            savedStateRegistry.registerSavedStateProvider(KEY_NAV_CONTROLLER_STATE) {
+                saveState() ?: Bundle.EMPTY
+            }
+            savedStateRegistry.consumeRestoredStateForKey(KEY_GRAPH_ID)?.let { bundle ->
+                graphId = bundle.getInt(KEY_GRAPH_ID)
+            }
+            savedStateRegistry.registerSavedStateProvider(KEY_GRAPH_ID) {
+                if (graphId != 0) {
+                    bundleOf(KEY_GRAPH_ID to graphId)
+                } else {
+                    Bundle.EMPTY
+                }
+            }
+            if (graphId != 0) {
+                // Set from onInflate()
+                setGraph(graphId)
+            } else {
+                // See if it was set by NavHostFragment.create()
+                val args = arguments
+                val graphId = args?.getInt(KEY_GRAPH_ID) ?: 0
+                val startDestinationArgs = args?.getBundle(KEY_START_DESTINATION_ARGS)
+                if (graphId != 0) {
+                    setGraph(graphId, startDestinationArgs)
+                }
+            }
+        }
+    }
     private var viewParent: View? = null
 
     // State that will be saved and restored
@@ -91,14 +128,12 @@
      * @throws IllegalStateException if called before [onCreate]
      */
     final override val navController: NavController
-        get() {
-            checkNotNull(navHostController) { "NavController is not available before onCreate()" }
-            return navHostController as NavHostController
-        }
+        get() = navHostController
 
     @CallSuper
     public override fun onAttach(context: Context) {
         super.onAttach(context)
+
         // TODO This feature should probably be a first-class feature of the Fragment system,
         // but it can stay here until we can add the necessary attr resources to
         // the fragment lib.
@@ -111,43 +146,15 @@
 
     @CallSuper
     public override fun onCreate(savedInstanceState: Bundle?) {
-        val context = requireContext()
-        navHostController = NavHostController(context)
-        navHostController!!.setLifecycleOwner(this)
-        // Set the default state - this will be updated whenever
-        // onPrimaryNavigationFragmentChanged() is called
-        navHostController!!.enableOnBackPressed(
-            isPrimaryBeforeOnCreate != null && isPrimaryBeforeOnCreate as Boolean
-        )
-        isPrimaryBeforeOnCreate = null
-        navHostController!!.setViewModelStore(viewModelStore)
-        onCreateNavHostController(navHostController!!)
-        var navState: Bundle? = null
+        // We are accessing the NavController here to ensure that it is always created by this point
+        navHostController
         if (savedInstanceState != null) {
-            navState = savedInstanceState.getBundle(KEY_NAV_CONTROLLER_STATE)
             if (savedInstanceState.getBoolean(KEY_DEFAULT_NAV_HOST, false)) {
                 defaultNavHost = true
                 parentFragmentManager.beginTransaction()
                     .setPrimaryNavigationFragment(this)
                     .commit()
             }
-            graphId = savedInstanceState.getInt(KEY_GRAPH_ID)
-        }
-        if (navState != null) {
-            // Navigation controller state overrides arguments
-            navHostController!!.restoreState(navState)
-        }
-        if (graphId != 0) {
-            // Set from onInflate()
-            navHostController!!.setGraph(graphId)
-        } else {
-            // See if it was set by NavHostFragment.create()
-            val args = arguments
-            val graphId = args?.getInt(KEY_GRAPH_ID) ?: 0
-            val startDestinationArgs = args?.getBundle(KEY_START_DESTINATION_ARGS)
-            if (graphId != 0) {
-                navHostController!!.setGraph(graphId, startDestinationArgs)
-            }
         }
 
         // We purposefully run this last as this will trigger the onCreate() of
@@ -167,7 +174,8 @@
      *
      * By default, this adds a [DialogFragmentNavigator] and [FragmentNavigator].
      *
-     * This is only called once in [onCreate] and should not be called directly by
+     * This is only called once when the navController is called. This will be called in [onCreate]
+     * if the navController has not yet been called. This should not be called directly by
      * subclasses.
      *
      * @param navHostController The newly created [NavHostController] that will be
@@ -186,7 +194,8 @@
      *
      * By default, this adds a [DialogFragmentNavigator] and [FragmentNavigator].
      *
-     * This is only called once in [onCreate] and should not be called directly by
+     * This is only called once when the navController is called. This will be called in [onCreate]
+     * if the navController has not yet been called. This should not be called directly by
      * subclasses.
      *
      * @param navController The newly created [NavController].
@@ -203,15 +212,6 @@
         navController.navigatorProvider.addNavigator(createFragmentNavigator())
     }
 
-    @CallSuper
-    public override fun onPrimaryNavigationFragmentChanged(isPrimaryNavigationFragment: Boolean) {
-        if (navHostController != null) {
-            navHostController?.enableOnBackPressed(isPrimaryNavigationFragment)
-        } else {
-            isPrimaryBeforeOnCreate = isPrimaryNavigationFragment
-        }
-    }
-
     /**
      * Create the FragmentNavigator that this NavHostFragment will use. By default, this uses
      * [FragmentNavigator], which replaces the entire contents of the NavHostFragment.
@@ -299,16 +299,9 @@
     @CallSuper
     public override fun onSaveInstanceState(outState: Bundle) {
         super.onSaveInstanceState(outState)
-        val navState = navHostController!!.saveState()
-        if (navState != null) {
-            outState.putBundle(KEY_NAV_CONTROLLER_STATE, navState)
-        }
         if (defaultNavHost) {
             outState.putBoolean(KEY_DEFAULT_NAV_HOST, true)
         }
-        if (graphId != 0) {
-            outState.putInt(KEY_GRAPH_ID, graphId)
-        }
     }
 
     public override fun onDestroyView() {
@@ -355,12 +348,12 @@
             var findFragment: Fragment? = fragment
             while (findFragment != null) {
                 if (findFragment is NavHostFragment) {
-                    return findFragment.navHostController as NavController
+                    return findFragment.navHostController
                 }
                 val primaryNavFragment = findFragment.parentFragmentManager
                     .primaryNavigationFragment
                 if (primaryNavFragment is NavHostFragment) {
-                    return primaryNavFragment.navHostController as NavController
+                    return primaryNavFragment.navHostController
                 }
                 findFragment = findFragment.parentFragment
             }
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index abb391c..5e04fc2 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -58,6 +58,7 @@
 import androidx.testutils.test
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
+import kotlin.test.assertFailsWith
 import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.take
@@ -104,6 +105,22 @@
             }
     }
 
+    private val NESTED_NAV_GRAPH_2 =
+        navController.createGraph(route = "graph", startDestination = "dest1") {
+            test("dest1")
+            navigation(route = "nested", startDestination = "dest2") {
+                argument("longArg") {
+                    type = NavType.LongType
+                }
+                test("dest2") {
+                    argument("longArg") {
+                        type = NavType.LongType
+                    }
+                }
+                test("dest3")
+            }
+        }
+
     @UiThreadTest
     @Test
     fun testGetCurrentBackStackEntry() {
@@ -1653,6 +1670,23 @@
 
     @UiThreadTest
     @Test
+    fun testNavigateWithMissingNonNullableArg() {
+        val navController = createNavController()
+        navController.graph = NESTED_NAV_GRAPH_2
+        assertThat(navController.currentDestination?.route).isEqualTo("dest1")
+
+        val nestedId = ("android-app://androidx.navigation/nested").hashCode()
+
+        val expected = assertFailsWith<NullPointerException> {
+            navController.navigate(nestedId)
+        }
+        assertThat(expected.message).isEqualTo(
+            "null cannot be cast to non-null type kotlin.Long"
+        )
+    }
+
+    @UiThreadTest
+    @Test
     fun testNavigateMultipleParentsOnHierarchy() {
         val navController = createNavController()
         navController.setGraph(R.navigation.nav_root)
@@ -1670,6 +1704,34 @@
 
     @UiThreadTest
     @Test
+    fun testRebuildParentWithMissingNonNullableArg() {
+        val navController = createNavController()
+        navController.graph = NESTED_NAV_GRAPH_2
+        assertThat(navController.currentDestination?.route).isEqualTo("dest1")
+
+        val nestedId1 = ("android-app://androidx.navigation/nested").hashCode()
+
+        // navigate to nested graph first destination, provide non-nullable arg
+        navController.navigate(
+            nestedId1,
+            bundleOf("longArg" to 123L)
+        )
+        assertThat(navController.currentDestination?.route).isEqualTo("dest2")
+
+        val nestedId2 = ("android-app://androidx.navigation/dest3").hashCode()
+        // navigate to nested graph second destination after popping up to graph (inclusive)
+        // empty bundle to imitate navigating with NavDirections
+        navController.navigate(
+            nestedId2,
+            Bundle(),
+            NavOptions.Builder().setPopUpTo("nested", inclusive = true).build()
+        )
+        // [graph, dest1, nested, dest3]
+        assertThat(navController.currentBackStack.value.size).isEqualTo(4)
+    }
+
+    @UiThreadTest
+    @Test
     fun testNavigateWithOverriddenDefaultArgs() {
         val args = Bundle()
         args.putString(TEST_OVERRIDDEN_VALUE_ARG, TEST_OVERRIDDEN_VALUE_ARG_VALUE)
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 9c54f99..302dc96 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -2045,10 +2045,11 @@
         while (destination != null && findDestination(destination.id) !== destination) {
             val parent = destination.parent
             if (parent != null) {
+                val args = if (finalArgs?.isEmpty == true) null else finalArgs
                 val entry = restoredEntries.lastOrNull { restoredEntry ->
                     restoredEntry.destination == parent
                 } ?: NavBackStackEntry.create(
-                    context, parent, parent.addInDefaultArgs(finalArgs), hostLifecycleState,
+                    context, parent, parent.addInDefaultArgs(args), hostLifecycleState,
                     viewModel
                 )
                 hierarchy.addFirst(entry)
diff --git a/percentlayout/OWNERS b/percentlayout/OWNERS
index c49ddc7..073b112 100644
--- a/percentlayout/OWNERS
+++ b/percentlayout/OWNERS
@@ -1,2 +1,4 @@
 # Bug component: 461485
 alanv@google.com
+aelias@google.com
+ryanmentley@google.com
diff --git a/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta02.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/1.0.0-beta02.txt
@@ -0,0 +1,92 @@
+// 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 @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);
+    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 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 @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.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/public_plus_experimental_1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta02.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/public_plus_experimental_1.0.0-beta02.txt
@@ -0,0 +1,92 @@
+// 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 @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);
+    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 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 @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.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.0.0-beta02.txt b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/res-1.0.0-beta02.txt
diff --git a/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta02.txt
new file mode 100644
index 0000000..26eea8b
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices-java/api/restricted_1.0.0-beta02.txt
@@ -0,0 +1,92 @@
+// 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 @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);
+    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 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 @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.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/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
index cb16955..5d17da4 100644
--- a/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
+++ b/privacysandbox/ads/ads-adservices-java/src/androidTest/java/androidx/privacysandbox/ads/adservices/java/endtoend/TestUtil.java
@@ -24,15 +24,18 @@
 import android.os.Build;
 import android.util.Log;
 
+import androidx.core.os.BuildCompat;
 import androidx.test.core.app.ApplicationProvider;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class TestUtil {
     private Instrumentation mInstrumentation;
     private String mTag;
     // Used to get the package name. Copied over from com.android.adservices.AdServicesCommon
     private static final String TOPICS_SERVICE_NAME = "android.adservices.TOPICS_SERVICE";
+    private static final String EXT_SERVICES_PACKAGE_NAME = "ext.adservices";
     // The JobId of the Epoch Computation.
     private static final int EPOCH_JOB_ID = 2;
 
@@ -220,10 +223,18 @@
     // Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
     public String getAdServicesPackageName() {
         final Intent intent = new Intent(TOPICS_SERVICE_NAME);
-        final List<ResolveInfo> resolveInfos = ApplicationProvider.getApplicationContext()
+        List<ResolveInfo> resolveInfos = ApplicationProvider.getApplicationContext()
                 .getPackageManager()
                 .queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY);
 
+        // TODO: b/271866693 avoid hardcoding package names
+        if (resolveInfos != null && BuildCompat.isAtLeastT()) {
+            resolveInfos = resolveInfos.stream()
+                    .filter(info ->
+                            !info.serviceInfo.packageName.contains(EXT_SERVICES_PACKAGE_NAME))
+                    .collect(Collectors.toList());
+        }
+
         if (resolveInfos == null || resolveInfos.isEmpty()) {
             Log.e(mTag, "Failed to find resolveInfo for adServices service. Intent action: "
                             + TOPICS_SERVICE_NAME);
diff --git a/privacysandbox/ads/ads-adservices/api/1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices/api/1.0.0-beta02.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/1.0.0-beta02.txt
@@ -0,0 +1,345 @@
+// 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;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    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>);
+    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();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    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;
+  }
+
+}
+
+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);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  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;
+  }
+
+}
+
+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 @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);
+  }
+
+  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.TIRAMISU) 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.TIRAMISU) 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 @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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    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);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    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/public_plus_experimental_1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta02.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/public_plus_experimental_1.0.0-beta02.txt
@@ -0,0 +1,345 @@
+// 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;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    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>);
+    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();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    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;
+  }
+
+}
+
+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);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  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;
+  }
+
+}
+
+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 @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);
+  }
+
+  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.TIRAMISU) 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.TIRAMISU) 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 @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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    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);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    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/res-1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/res-1.0.0-beta02.txt
diff --git a/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta02.txt b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta02.txt
new file mode 100644
index 0000000..30cd307
--- /dev/null
+++ b/privacysandbox/ads/ads-adservices/api/restricted_1.0.0-beta02.txt
@@ -0,0 +1,345 @@
+// 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;
+  }
+
+  public abstract class AdSelectionManager {
+    method public static final androidx.privacysandbox.ads.adservices.adselection.AdSelectionManager? obtain(android.content.Context context);
+    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>);
+    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();
+    property public final long adSelectionId;
+    property public final android.net.Uri renderUri;
+  }
+
+  public final class ReportImpressionRequest {
+    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;
+  }
+
+}
+
+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);
+    method public String getMetadata();
+    method public android.net.Uri getRenderUri();
+    property public final String metadata;
+    property public final android.net.Uri renderUri;
+  }
+
+  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;
+  }
+
+}
+
+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 @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);
+  }
+
+  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.TIRAMISU) 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.TIRAMISU) 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 @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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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);
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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;
+  }
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) 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.topics {
+
+  public final class GetTopicsRequest {
+    ctor public GetTopicsRequest(optional String adsSdkName, optional boolean shouldRecordObservation);
+    method public String getAdsSdkName();
+    method public boolean getShouldRecordObservation();
+    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);
+    method public java.util.List<androidx.privacysandbox.ads.adservices.topics.Topic> getTopics();
+    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/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
index dc5e591..e316ab0 100644
--- a/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
+++ b/privacysandbox/ads/ads-adservices/src/main/java/androidx/privacysandbox/ads/adservices/measurement/MeasurementManager.kt
@@ -21,6 +21,7 @@
 import android.content.Context
 import android.net.Uri
 import android.os.ext.SdkExtensions
+import android.util.Log
 import android.view.InputEvent
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresExtension
@@ -250,6 +251,7 @@
         @JvmStatic
         @SuppressLint("NewApi", "ClassVerificationFailure")
         fun obtain(context: Context): MeasurementManager? {
+            Log.d("MeasurementManager", "AdServicesInfo.version=${AdServicesInfo.version()}")
             return if (AdServicesInfo.version() >= 5) {
                 Api33Ext5Impl(context)
             } else {
diff --git a/recyclerview/recyclerview/build.gradle b/recyclerview/recyclerview/build.gradle
index 1f6736c..7a03c8b 100644
--- a/recyclerview/recyclerview/build.gradle
+++ b/recyclerview/recyclerview/build.gradle
@@ -12,7 +12,7 @@
     implementation("androidx.collection:collection:1.0.0")
     api("androidx.customview:customview:1.0.0")
     implementation("androidx.customview:customview-poolingcontainer:1.0.0")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.1")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
index 474ae6c..5ecead7 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/TestDatabase.kt
@@ -18,32 +18,54 @@
 
 import androidx.room.Database
 import androidx.room.RoomDatabase
+import androidx.room.TypeConverter
+import androidx.room.TypeConverters
 import androidx.room.integration.kotlintestapp.dao.AbstractDao
 import androidx.room.integration.kotlintestapp.dao.BooksDao
 import androidx.room.integration.kotlintestapp.dao.CounterDao
 import androidx.room.integration.kotlintestapp.dao.DependencyDao
 import androidx.room.integration.kotlintestapp.dao.DerivedDao
+import androidx.room.integration.kotlintestapp.dao.MusicDao
+import androidx.room.integration.kotlintestapp.dao.PetDao
+import androidx.room.integration.kotlintestapp.dao.ToyDao
 import androidx.room.integration.kotlintestapp.dao.UsersDao
+import androidx.room.integration.kotlintestapp.vo.Album
+import androidx.room.integration.kotlintestapp.vo.Artist
 import androidx.room.integration.kotlintestapp.vo.Author
 import androidx.room.integration.kotlintestapp.vo.Book
 import androidx.room.integration.kotlintestapp.vo.BookAuthor
 import androidx.room.integration.kotlintestapp.vo.Counter
 import androidx.room.integration.kotlintestapp.vo.DataClassFromDependency
 import androidx.room.integration.kotlintestapp.vo.EntityWithJavaPojoList
+import androidx.room.integration.kotlintestapp.vo.Image
 import androidx.room.integration.kotlintestapp.vo.JavaEntity
 import androidx.room.integration.kotlintestapp.vo.NoArgClass
+import androidx.room.integration.kotlintestapp.vo.Pet
+import androidx.room.integration.kotlintestapp.vo.PetUser
+import androidx.room.integration.kotlintestapp.vo.PetWithUser
+import androidx.room.integration.kotlintestapp.vo.Playlist
+import androidx.room.integration.kotlintestapp.vo.PlaylistSongXRef
 import androidx.room.integration.kotlintestapp.vo.Publisher
+import androidx.room.integration.kotlintestapp.vo.Song
+import java.nio.ByteBuffer
+import java.util.Date
+import java.util.UUID
+import androidx.room.integration.kotlintestapp.vo.Toy
 import androidx.room.integration.kotlintestapp.vo.User
 
 @Database(
     entities = [
         Book::class, Author::class, Publisher::class, BookAuthor::class,
         NoArgClass::class, DataClassFromDependency::class, JavaEntity::class,
-        EntityWithJavaPojoList::class, User::class, Counter::class
+        EntityWithJavaPojoList::class, User::class, Counter::class, Toy::class,
+        Pet::class, PetUser::class, Song::class, Playlist::class, PlaylistSongXRef::class,
+        Artist::class, Album::class, Image::class
     ],
+    views = [PetWithUser::class],
     version = 1,
-    exportSchema = false
+    exportSchema = false,
 )
+@TypeConverters(TestDatabase.Converters::class)
 abstract class TestDatabase : RoomDatabase() {
 
     abstract fun usersDao(): UsersDao
@@ -57,4 +79,59 @@
     abstract fun abstractDao(): AbstractDao
 
     abstract fun counterDao(): CounterDao
+
+    abstract fun toyDao(): ToyDao
+
+    abstract fun petDao(): PetDao
+
+    abstract fun musicDao(): MusicDao
+
+    class Converters {
+        @TypeConverter
+        fun fromTimestamp(value: Long): Date {
+            return Date(value)
+        }
+
+        @TypeConverter
+        fun dateToTimestamp(date: Date): Long {
+            return date.time
+        }
+
+        @TypeConverter
+        fun decomposeDays(flags: Int): Set<androidx.room.integration.kotlintestapp.vo.Day> {
+            val result: MutableSet<androidx.room.integration.kotlintestapp.vo.Day> =
+                HashSet()
+            for (day in androidx.room.integration.kotlintestapp.vo.Day.values()) {
+                if (flags and (1 shl day.ordinal) != 0) {
+                    result.add(day)
+                }
+            }
+            return result
+        }
+
+        @TypeConverter
+        fun composeDays(days: Set<androidx.room.integration.kotlintestapp.vo.Day>): Int {
+            var result = 0
+            for (day in days) {
+                result = result or (1 shl day.ordinal)
+            }
+            return result
+        }
+
+        @TypeConverter
+        fun asUuid(bytes: ByteArray): UUID {
+            val bb = ByteBuffer.wrap(bytes)
+            val firstLong = bb.long
+            val secondLong = bb.long
+            return UUID(firstLong, secondLong)
+        }
+
+        @TypeConverter
+        fun asBytes(uuid: UUID): ByteArray {
+            val bb = ByteBuffer.wrap(ByteArray(16))
+            bb.putLong(uuid.mostSignificantBits)
+            bb.putLong(uuid.leastSignificantBits)
+            return bb.array()
+        }
+    }
 }
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/MusicDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/MusicDao.kt
new file mode 100644
index 0000000..0f5c62b
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/MusicDao.kt
@@ -0,0 +1,277 @@
+/*
+ * 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.room.integration.kotlintestapp.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.MapInfo
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.room.RewriteQueriesToDropUnusedColumns
+import androidx.room.Transaction
+import androidx.room.integration.kotlintestapp.vo.Album
+import androidx.room.integration.kotlintestapp.vo.AlbumNameAndBandName
+import androidx.room.integration.kotlintestapp.vo.AlbumWithSongs
+import androidx.room.integration.kotlintestapp.vo.Artist
+import androidx.room.integration.kotlintestapp.vo.Image
+import androidx.room.integration.kotlintestapp.vo.ImageFormat
+import androidx.room.integration.kotlintestapp.vo.ReleasedAlbum
+import androidx.room.integration.kotlintestapp.vo.Song
+import androidx.sqlite.db.SupportSQLiteQuery
+import com.google.common.collect.ImmutableListMultimap
+import com.google.common.collect.ImmutableMap
+import com.google.common.collect.ImmutableSetMultimap
+import io.reactivex.Flowable
+import java.nio.ByteBuffer
+import java.util.Date
+
+@JvmDefaultWithCompatibility
+@Dao
+interface MusicDao {
+    @Insert
+    fun addSongs(vararg songs: Song)
+
+    @Insert
+    fun addArtists(vararg artists: Artist)
+
+    @Insert
+    fun addAlbums(vararg albums: Album)
+    @Insert
+    fun addImages(vararg images: Image)
+
+    /* Map of Object to Object */
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getArtistAndFirstSongMap(): Map<Artist, Song>
+
+    @Query("SELECT * FROM Song JOIN Artist ON Song.mArtist = Artist.mArtistName")
+    fun getSongAndArtist(): Map<Song, Artist>
+
+    @Query("SELECT * FROM Artist JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    @Transaction
+    fun getAllArtistAndTheirAlbumsWithSongs(): Map<Artist, AlbumWithSongs>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQuery(query: SupportSQLiteQuery): Map<Artist, Song>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getAllArtistAndTheirSongsAsLiveData(): LiveData<Map<Artist, Song>>
+
+    /* Map of Object to List */
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getAllArtistAndTheirSongsList(): Map<Artist, List<Song>>
+
+    @Query(
+        "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist " +
+            "ORDER BY mArtistName ASC"
+    )
+    fun getAllArtistAndTheirSongsListOrdered(): Map<Artist, List<Song>>
+
+    @Query("SELECT * FROM Artist JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    @Transaction
+    fun getAllArtistAndTheirAlbumsWithSongsList(): Map<Artist, List<AlbumWithSongs>>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQueryList(query: SupportSQLiteQuery): Map<Artist, List<Song>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getAllArtistAndTheirSongsAsLiveDataList(): LiveData<Map<Artist, List<Song>>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getAllArtistAndTheirSongsAsFlowableList(): Flowable<Map<Artist, List<Song>>>
+
+    @Query(
+        "SELECT Album.mAlbumReleaseYear as mReleaseYear, Album.mAlbumName, Album.mAlbumArtist " +
+            "as mBandName" +
+            " from Album " +
+            "JOIN Song " +
+            "ON Album.mAlbumArtist = Song.mArtist AND Album.mAlbumName = Song.mAlbum"
+    )
+    fun getReleaseYearToAlbumsAndBandsList(): Map<ReleasedAlbum, List<AlbumNameAndBandName>>
+
+    /* Map of Object to Set */
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun getAllArtistAndTheirSongsSet(): Map<Artist, Set<Song>>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQuerySet(query: SupportSQLiteQuery): Map<Artist, Set<Song>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsAsLiveDataSet(): LiveData<Map<Artist, Set<Song>>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsAsFlowableSet(): Flowable<Map<Artist, Set<Song>>>
+
+    /* Guava ImmutableMap */
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsImmutableMap(): ImmutableMap<Artist, List<Song>>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQueryImmutableMap(
+        query: SupportSQLiteQuery
+    ): ImmutableMap<Artist, List<Song>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsAsLiveDataImmutableMap(): LiveData<ImmutableMap<Artist, Set<Song>>>
+
+    /* Guava Multimap */
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsGuavaImmutableSetMultimap(): ImmutableSetMultimap<Artist, Song>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsGuavaImmutableListMultimap(): ImmutableListMultimap<Artist, Song>
+
+    @Query("SELECT * FROM Artist JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    @Transaction
+    fun allArtistAndTheirAlbumsWithSongsGuavaImmutableSetMultimap():
+        ImmutableSetMultimap<Artist, AlbumWithSongs>
+
+    @Query("SELECT * FROM Artist JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    @Transaction
+    fun allArtistAndTheirAlbumsWithSongsGuavaImmutableListMultimap():
+        ImmutableListMultimap<Artist, AlbumWithSongs>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQueryGuavaImmutableSetMultimap(
+        query: SupportSQLiteQuery
+    ): ImmutableSetMultimap<Artist, Song>
+
+    @RawQuery
+    fun getAllArtistAndTheirSongsRawQueryGuavaImmutableListMultimap(
+        query: SupportSQLiteQuery
+    ): ImmutableListMultimap<Artist, Song>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsAsLiveDataGuavaImmutableSetMultimap():
+        LiveData<ImmutableSetMultimap<Artist, Song>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    fun allArtistAndTheirSongsAsLiveDataGuavaImmutableListMultimap():
+        LiveData<ImmutableListMultimap<Artist, Song>>
+
+    @Query("SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist")
+    @MapInfo(keyColumn = "mArtistName")
+    @RewriteQueriesToDropUnusedColumns
+    fun artistNameToSongs(): Map<String, List<Song>>
+
+    @Query("SELECT * FROM Album JOIN Song ON Song.mReleasedYear = Album.mAlbumReleaseYear")
+    @MapInfo(keyColumn = "mReleasedYear", valueColumn = "mReleasedYear")
+    @RewriteQueriesToDropUnusedColumns
+    fun releaseYearToAlbums(): Map<Int, List<Song>>
+
+    @Query("SELECT * FROM Album JOIN Song ON Song.mReleasedYear = Album.mAlbumReleaseYear")
+    @MapInfo(keyColumn = "mReleasedYear", valueColumn = "mTitle")
+    @RewriteQueriesToDropUnusedColumns
+    fun releaseYearToSongNames(): Map<Int, List<String>>
+
+    @RewriteQueriesToDropUnusedColumns
+    @MapInfo(keyColumn = "mArtistName", valueColumn = "mArtist")
+    @RawQuery
+    fun getArtistNameToSongsRawQuery(query: SupportSQLiteQuery): Map<String, List<Song>>
+
+    @RewriteQueriesToDropUnusedColumns
+    @MapInfo(keyColumn = "mReleasedYear", valueColumn = "mReleasedYear")
+    @RawQuery
+    fun getReleaseYearToAlbumsRawQuery(query: SupportSQLiteQuery): Map<Int, List<Song>>
+
+    @RewriteQueriesToDropUnusedColumns
+    @MapInfo(keyColumn = "mReleasedYear", valueColumn = "mTitle")
+    @RawQuery
+    fun getReleaseYearToSongNamesRawQuery(query: SupportSQLiteQuery): Map<Int, List<String>>
+
+    @Query(
+        "SELECT *, COUNT(mSongId) as songCount FROM Artist JOIN Song ON Artist.mArtistName = " +
+            "Song.mArtist GROUP BY mArtistName"
+    )
+    @MapInfo(valueColumn = "songCount")
+    @RewriteQueriesToDropUnusedColumns
+    fun artistAndSongCountMap(): Map<Artist, Int>
+
+    @RewriteQueriesToDropUnusedColumns
+    @MapInfo(valueColumn = "songCount")
+    @RawQuery
+    fun getArtistAndSongCountMapRawQuery(query: SupportSQLiteQuery): Map<Artist, Int>
+
+    // Other Map Key/Value Types
+    @Query("SELECT * FROM Artist JOIN Image ON Artist.mArtistName = Image.mArtistInImage")
+    @MapInfo(valueColumn = "mAlbumCover")
+    @RewriteQueriesToDropUnusedColumns
+    fun allArtistsWithAlbumCovers(): ImmutableMap<Artist, ByteBuffer>
+
+    @MapInfo(valueColumn = "mAlbumCover")
+    @RawQuery
+    fun getAllArtistsWithAlbumCoversRawQuery(query: SupportSQLiteQuery):
+        ImmutableMap<Artist, ByteBuffer>
+
+    @Query("SELECT * FROM Artist JOIN Image ON Artist.mArtistName = Image.mArtistInImage")
+    @MapInfo(valueColumn = "mImageYear")
+    @RewriteQueriesToDropUnusedColumns
+    fun allArtistsWithAlbumCoverYear(): ImmutableMap<Artist, Long>
+
+    @MapInfo(keyColumn = "mImageYear")
+    @RawQuery
+    fun getAllAlbumCoverYearToArtistsWithRawQuery(query: SupportSQLiteQuery):
+        ImmutableMap<Long, Artist>
+
+    @Query("SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image.mArtistInImage")
+    @MapInfo(keyColumn = "mAlbumCover", valueColumn = "mIsActive")
+    fun albumCoversWithBandActivity(): ImmutableMap<ByteBuffer, Boolean>
+
+    @MapInfo(keyColumn = "mAlbumCover", valueColumn = "mIsActive")
+    @RawQuery
+    fun getAlbumCoversWithBandActivityRawQuery(
+        query: SupportSQLiteQuery
+    ): ImmutableMap<ByteBuffer, Boolean>
+
+    @Query("SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image.mArtistInImage")
+    @MapInfo(keyColumn = "mDateReleased", valueColumn = "mIsActive")
+    fun albumDateWithBandActivity(): ImmutableMap<Date, Boolean>
+
+    @MapInfo(keyColumn = "mDateReleased", valueColumn = "mIsActive")
+    @RawQuery
+    fun getAlbumDateWithBandActivityRawQuery(query: SupportSQLiteQuery): ImmutableMap<Date, Boolean>
+
+    @Query("SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image.mArtistInImage")
+    @MapInfo(keyColumn = "mFormat", valueColumn = "mIsActive")
+    fun imageFormatWithBandActivity(): ImmutableMap<ImageFormat, Boolean>
+
+    @MapInfo(keyColumn = "mFormat", valueColumn = "mIsActive")
+    @RawQuery
+    fun getImageFormatWithBandActivityRawQuery(
+        query: SupportSQLiteQuery
+    ): ImmutableMap<ImageFormat, Boolean>
+
+    @MapInfo(keyColumn = "dog", valueColumn = "cat")
+    @RawQuery
+    fun getMapWithInvalidColumnRawQuery(query: SupportSQLiteQuery): Map<Artist, Int>
+
+    @Query("SELECT * FROM Artist LEFT JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    fun artistAndAlbumsLeftJoin(): Map<Artist, List<Album>>
+
+    @Query("SELECT * FROM Artist LEFT JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    fun artistAndAlbumsLeftJoinGuava(): ImmutableListMultimap<Artist, Album>
+
+    @Query("SELECT * FROM Artist LEFT JOIN Album ON Artist.mArtistName = Album.mAlbumArtist")
+    @MapInfo(valueColumn = "mAlbumName")
+    @RewriteQueriesToDropUnusedColumns
+    fun artistAndAlbumNamesLeftJoin(): Map<Artist, List<String>>
+
+    @Query("SELECT * FROM Album LEFT JOIN Artist ON Artist.mArtistName = Album.mAlbumArtist")
+    fun albumToArtistLeftJoin(): Map<Album, Artist>
+
+    @Query("SELECT * FROM Album LEFT JOIN Artist ON Artist.mArtistName = Album.mAlbumArtist")
+    fun artistToAlbumLeftJoin(): Map<Artist, Album>
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/PetDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/PetDao.kt
new file mode 100644
index 0000000..c45bc5b
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/PetDao.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import androidx.room.Transaction
+import androidx.room.integration.kotlintestapp.vo.Pet
+import androidx.room.integration.kotlintestapp.vo.PetAndOwner
+import androidx.room.integration.kotlintestapp.vo.PetWithToyIds
+import androidx.room.integration.kotlintestapp.vo.PetWithUser
+import com.google.common.base.Optional
+import com.google.common.util.concurrent.ListenableFuture
+import io.reactivex.Flowable
+
+@JvmDefaultWithCompatibility
+@Dao
+interface PetDao {
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun insertOrReplace(vararg pets: Pet)
+
+    @Insert
+    fun insertAll(pets: Array<Pet>)
+
+    @Query("SELECT COUNT(*) FROM Pet")
+    fun count(): Int
+
+    @Transaction
+    @Query("SELECT * FROM Pet ORDER BY Pet.mPetId ASC")
+    fun allPetsWithToyIds(): List<PetWithToyIds>
+
+    @Transaction
+    @Query("SELECT * FROM Pet")
+    fun allPetsWithOwners(): List<PetAndOwner>
+
+    @Query("SELECT * FROM Pet WHERE Pet.mPetId = :id")
+    fun petWithIdFuture(id: Int): ListenableFuture<Optional<Pet>>
+
+    @Query("SELECT * FROM Pet WHERE Pet.mPetId = :id")
+    fun petWithIdFlowable(id: Int): Flowable<Pet>
+
+    @Query("SELECT * FROM Pet WHERE Pet.mPetId = :id")
+    fun petWithId(id: Int): Pet
+
+    @Query("SELECT * FROM Pet WHERE Pet.mPetId = :id")
+    fun petWithIdLiveData(id: Int): LiveData<Pet>
+
+    @Query("SELECT * FROM PetWithUser WHERE mPetId = :id")
+    fun petWithUserLiveData(id: Int): LiveData<PetWithUser>
+
+    @Delete
+    fun delete(pet: Pet)
+
+    @Query("SELECT mPetId FROM Pet")
+    fun allIds(): IntArray
+
+    @Transaction
+    fun deleteAndInsert(oldPet: Pet, newPet: Pet, shouldFail: Boolean) {
+        delete(oldPet)
+        if (shouldFail) {
+            throw RuntimeException()
+        }
+        insertOrReplace(newPet)
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/ToyDao.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/ToyDao.kt
new file mode 100644
index 0000000..fbbd6c5
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/dao/ToyDao.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import androidx.room.Update
+import androidx.room.integration.kotlintestapp.vo.Toy
+
+@JvmDefaultWithCompatibility
+@Dao
+interface ToyDao {
+    @Insert
+    fun insert(vararg toys: Toy)
+
+    @Query("SELECT * FROM Toy WHERE mId = :id")
+    fun getToy(id: Int): Toy?
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun insertOrReplace(toy: Toy)
+
+    @Insert(onConflict = OnConflictStrategy.IGNORE)
+    fun insertOrIgnore(toy: Toy)
+
+    @Update(onConflict = OnConflictStrategy.REPLACE)
+    fun updateOrReplace(toy: Toy): Int
+
+    @Update(onConflict = OnConflictStrategy.IGNORE)
+    fun updateOrIgnore(toy: Toy): Int
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoConflictStrategyTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoConflictStrategyTest.kt
new file mode 100644
index 0000000..671fff8
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoConflictStrategyTest.kt
@@ -0,0 +1,103 @@
+/*
+ * 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.room.integration.kotlintestapp.test
+
+import android.content.Context
+import androidx.room.Room
+import androidx.room.integration.kotlintestapp.TestDatabase
+import androidx.room.integration.kotlintestapp.dao.PetDao
+import androidx.room.integration.kotlintestapp.dao.ToyDao
+import androidx.room.integration.kotlintestapp.vo.Pet
+import androidx.room.integration.kotlintestapp.vo.Toy
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DaoConflictStrategyTest {
+    private lateinit var mToyDao: ToyDao
+    private lateinit var mOriginalToy: Toy
+    private lateinit var mPetDao: PetDao
+    private lateinit var mPet: Pet
+
+    @Before
+    fun createDbAndSetUpToys() {
+        val context: Context = ApplicationProvider.getApplicationContext()
+        val db: TestDatabase =
+            Room.inMemoryDatabaseBuilder(context, TestDatabase::class.java).build()
+        mToyDao = db.toyDao()
+        mPetDao = db.petDao()
+        mPet = TestUtil.createPet(1)
+        mOriginalToy = Toy(10, "originalToy", 1)
+        mPetDao.insertOrReplace(mPet)
+        mToyDao.insert(mOriginalToy)
+    }
+
+    @Test
+    fun testInsertOnConflictReplace() {
+        val newToy = Toy(10, "newToy", 1)
+        mToyDao.insertOrReplace(newToy)
+        val output: Toy? = mToyDao.getToy(10)
+        assertThat(output).isNotNull()
+        assertThat(output!!.mName).isEqualTo(newToy.mName)
+    }
+
+    @Test
+    fun testInsertOnConflictIgnore() {
+        val newToy = Toy(10, "newToy", 1)
+        mToyDao.insertOrIgnore(newToy)
+        val output: Toy? = mToyDao.getToy(10)
+        assertThat(output).isNotNull()
+        assertThat(output!!.mName).isEqualTo(mOriginalToy.mName)
+    }
+
+    @Test
+    fun testUpdateOnConflictReplace() {
+        val newToy = Toy(11, "newToy", 1)
+        mToyDao.insert(newToy)
+        val conflictToy = Toy(11, "originalToy", 1)
+        mToyDao.updateOrReplace(conflictToy)
+
+        // Conflicting row is deleted
+        assertThat(mToyDao.getToy(10)).isNull()
+
+        // Row is updated
+        val output: Toy? = mToyDao.getToy(11)
+        assertThat(output).isNotNull()
+        assertThat(output!!.mName).isEqualTo(conflictToy.mName)
+    }
+
+    @Test
+    fun testUpdateOnConflictIgnore() {
+        val newToy = Toy(11, "newToy", 1)
+        mToyDao.insert(newToy)
+        val conflictToy = Toy(11, "newToy", 1)
+        mToyDao.updateOrIgnore(conflictToy)
+
+        // Conflicting row is kept
+        assertThat(mToyDao.getToy(10)).isNotNull()
+
+        // Row is not updated
+        val output: Toy? = mToyDao.getToy(11)
+        assertThat(output).isNotNull()
+        assertThat(output!!.mName).isEqualTo(newToy.mName)
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoNameConflictTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoNameConflictTest.kt
new file mode 100644
index 0000000..21e7ca9
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/DaoNameConflictTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.integration.kotlintestapp.test
+
+import androidx.room.Dao
+import androidx.room.Database
+import androidx.room.Entity
+import androidx.room.Insert
+import androidx.room.PrimaryKey
+import androidx.room.Query
+import androidx.room.Room.inMemoryDatabaseBuilder
+import androidx.room.RoomDatabase
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import org.hamcrest.CoreMatchers
+import org.hamcrest.MatcherAssert
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class DaoNameConflictTest {
+    private lateinit var mDb: ConflictDatabase
+    @Before
+    fun init() {
+        mDb = inMemoryDatabaseBuilder(
+            ApplicationProvider.getApplicationContext(),
+            ConflictDatabase::class.java
+        ).build()
+    }
+
+    @After
+    fun close() {
+        mDb.close()
+    }
+
+    @Test
+    fun readFromItem1() {
+        val item1 = Item1(1, "a")
+        mDb.item1Dao().insert(item1)
+        val item2 = Item2(2, "b")
+        mDb.item2Dao().insert(item2)
+        MatcherAssert.assertThat(
+            mDb.item1Dao().get(), CoreMatchers.`is`(item1)
+        )
+        MatcherAssert.assertThat(
+            mDb.item2Dao().get(), CoreMatchers.`is`(item2)
+        )
+    }
+
+    @Entity
+    class Item1(@field:PrimaryKey var id: Int, var name: String?) {
+        @Dao
+        interface Store {
+            @Query("SELECT * FROM Item1 LIMIT 1")
+            fun get(): Item1
+
+            @Insert
+            fun insert(vararg items: Item1)
+        }
+
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other == null || javaClass != other.javaClass) return false
+            val item1 = other as Item1
+            if (id != item1.id) return false
+            return if (name != null) name == item1.name else item1.name == null
+        }
+
+        override fun hashCode(): Int {
+            var result = id
+            result = 31 * result + if (name != null) name.hashCode() else 0
+            return result
+        }
+    }
+
+    @Entity
+    class Item2(@field:PrimaryKey var id: Int, var name: String?) {
+        @Dao
+        interface Store {
+            @Query("SELECT * FROM Item2 LIMIT 1")
+            fun get(): Item2
+
+            @Insert
+            fun insert(vararg items: Item2)
+        }
+
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other == null || javaClass != other.javaClass) return false
+            val item2 = other as Item2
+            if (id != item2.id) return false
+            return if (name != null) name == item2.name else item2.name == null
+        }
+
+        override fun hashCode(): Int {
+            var result = id
+            result = 31 * result + if (name != null) name.hashCode() else 0
+            return result
+        }
+    }
+
+    @Database(version = 1, exportSchema = false, entities = [Item1::class, Item2::class])
+    abstract class ConflictDatabase : RoomDatabase() {
+        abstract fun item1Dao(): Item1.Store
+        abstract fun item2Dao(): Item2.Store
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/MultimapQueryTest.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/MultimapQueryTest.kt
new file mode 100644
index 0000000..d9a6932
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/MultimapQueryTest.kt
@@ -0,0 +1,1133 @@
+/*
+ * 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.room.integration.kotlintestapp.test
+
+import android.content.Context
+import androidx.arch.core.executor.testing.CountingTaskExecutorRule
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.testing.TestLifecycleOwner
+import androidx.room.Room
+import androidx.room.integration.kotlintestapp.TestDatabase
+import androidx.room.integration.kotlintestapp.dao.MusicDao
+import androidx.room.integration.kotlintestapp.vo.Album
+import androidx.room.integration.kotlintestapp.vo.AlbumNameAndBandName
+import androidx.room.integration.kotlintestapp.vo.AlbumWithSongs
+import androidx.room.integration.kotlintestapp.vo.Artist
+import androidx.room.integration.kotlintestapp.vo.Image
+import androidx.room.integration.kotlintestapp.vo.ImageFormat
+import androidx.room.integration.kotlintestapp.vo.ReleasedAlbum
+import androidx.room.integration.kotlintestapp.vo.Song
+import androidx.sqlite.db.SimpleSQLiteQuery
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.ImmutableListMultimap
+import com.google.common.collect.ImmutableMap
+import com.google.common.collect.ImmutableMultimap
+import com.google.common.collect.ImmutableSet
+import com.google.common.collect.ImmutableSetMultimap
+import com.google.common.truth.Truth.assertThat
+import io.reactivex.Flowable
+import java.nio.ByteBuffer
+import java.util.Date
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests multimap return type for JOIN statements.
+ */
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class MultimapQueryTest {
+    private lateinit var mMusicDao: MusicDao
+    private val mRhcpSong1: Song = Song(
+        1,
+        "Dani California",
+        "Red Hot Chili Peppers",
+        "Stadium Arcadium",
+        442,
+        2006
+    )
+    private val mRhcpSong2: Song = Song(
+        2,
+        "Snow (Hey Oh)",
+        "Red Hot Chili Peppers",
+        "Stadium Arcadium",
+        514,
+        2006
+    )
+    private val mAcdcSong1: Song = Song(
+        3,
+        "Highway to Hell",
+        "AC/DC",
+        "Highway to Hell",
+        328,
+        1979
+    )
+    private val mPinkFloydSong1: Song = Song(
+        4,
+        "The Great Gig in the Sky",
+        "Pink Floyd",
+        "The Dark Side of the Moon",
+        443,
+        1973
+    )
+    private val mRhcp: Artist = Artist(
+        1,
+        "Red Hot Chili Peppers",
+        true
+    )
+    private val mAcDc: Artist = Artist(
+        2,
+        "AC/DC",
+        true
+    )
+    private val mTheClash: Artist = Artist(
+        3,
+        "The Clash",
+        false
+    )
+    private val mPinkFloyd: Artist = Artist(
+        4,
+        "Pink Floyd",
+        false
+    )
+    private val mGlassAnimals: Artist = Artist(
+        5,
+        "Glass Animals",
+        true
+    )
+    private val mStadiumArcadium: Album = Album(
+        1,
+        "Stadium Arcadium",
+        "Red Hot Chili Peppers",
+        2006,
+        "N/A"
+    )
+    private val mCalifornication: Album = Album(
+        2,
+        "Californication",
+        "Red Hot Chili Peppers",
+        1999,
+        "N/A"
+    )
+    private val mHighwayToHell: Album = Album(
+        3,
+        "Highway to Hell",
+        "AC/DC",
+        1979,
+        null
+    )
+    private val mTheDarkSideOfTheMoon: Album = Album(
+        4,
+        "The Dark Side of the Moon",
+        "Pink Floyd",
+        1973,
+        "N/A"
+    )
+    private val mDreamland: Album = Album(
+        5,
+        "Dreamland",
+        null,
+        2020,
+        null
+    )
+    private val mPinkFloydAlbumCover: Image = Image(
+        1,
+        1973L,
+        "Pink Floyd",
+        "dark_side_of_the_moon_image".toByteArray(),
+        Date(101779200000L),
+        ImageFormat.JPG
+    )
+    private val mRhcpAlbumCover: Image = Image(
+        2,
+        2006L,
+        "Red Hot Chili Peppers",
+        "stadium_arcadium_image".toByteArray(),
+        Date(1146787200000L),
+        ImageFormat.MPEG
+    )
+
+    @JvmField
+    @Rule
+    var mExecutorRule = CountingTaskExecutorRule()
+    @Throws(TimeoutException::class, InterruptedException::class)
+    private fun drain() {
+        mExecutorRule.drainTasks(1, TimeUnit.MINUTES)
+        assertThat(mExecutorRule.isIdle).isTrue()
+    }
+
+    private open inner class MyTestObserver<T> : TestObserver<T>() {
+        @Throws(TimeoutException::class, InterruptedException::class)
+        override fun drain() {
+            this@MultimapQueryTest.drain()
+        }
+    }
+
+    @Before
+    fun createDb() {
+        val context: Context = ApplicationProvider.getApplicationContext()
+        val db: TestDatabase =
+            Room.inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+                .build()
+        mMusicDao = db.musicDao()
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables.
+     */
+    @Test
+    fun testGetFirstSongForArtist() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: Map<Artist, Song> = mMusicDao.getArtistAndFirstSongMap()
+        assertThat(artistToSongsMap[mAcDc]).isEqualTo(mAcdcSong1)
+        assertThat(artistToSongsMap[mRhcp]).isEqualTo(mRhcpSong1)
+    }
+
+    @Test
+    fun testGetSongToArtistMapping() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val songToArtistMap: Map<Song, Artist> = mMusicDao.getSongAndArtist()
+        assertThat(songToArtistMap[mAcdcSong1]).isEqualTo(mAcDc)
+        assertThat(songToArtistMap[mPinkFloydSong1]).isEqualTo(mPinkFloyd)
+        assertThat(songToArtistMap[mRhcpSong1]).isEqualTo(mRhcp)
+        assertThat(songToArtistMap[mRhcpSong2]).isEqualTo(mRhcp)
+    }
+
+    @Test
+    fun testJoinByArtistNameList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: Map<Artist, List<Song>> = mMusicDao.getAllArtistAndTheirSongsList()
+        assertContentsOfResultMapWithList(artistToSongsMap)
+    }
+
+    @Test
+    fun testJoinByArtistNameListOrdered() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+
+        assertThat(mMusicDao.getAllArtistAndTheirSongsListOrdered().keys).containsExactlyElementsIn(
+            arrayOf(mRhcp, mAcDc, mPinkFloyd)
+        )
+    }
+
+    @Test
+    fun testJoinByArtistNameSet() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsSet: Map<Artist, Set<Song>> = mMusicDao.getAllArtistAndTheirSongsSet()
+        assertContentsOfResultMapWithSet(artistToSongsSet)
+    }
+
+    /**
+     * Tests a JOIN using [androidx.room.RawQuery] between two tables.
+     */
+    @Test
+    fun testJoinByArtistNameRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: Map<Artist, Song> = mMusicDao.getAllArtistAndTheirSongsRawQuery(
+            SimpleSQLiteQuery(
+                "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist"
+            )
+        )
+        assertThat(artistToSongsMap[mAcDc]).isEqualTo(mAcdcSong1)
+    }
+
+    @Test
+    fun testJoinByArtistNameRawQueryList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: Map<Artist, List<Song>> =
+            mMusicDao.getAllArtistAndTheirSongsRawQueryList(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist"
+                )
+            )
+        assertContentsOfResultMapWithList(artistToSongsMap)
+    }
+
+    @Test
+    fun testJoinByArtistNameRawQuerySet() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: Map<Artist, Set<Song>> =
+            mMusicDao.getAllArtistAndTheirSongsRawQuerySet(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist"
+                )
+            )
+        assertContentsOfResultMapWithSet(artistToSongsMap)
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables with a [LiveData] map return type.
+     */
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameLiveData() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<Map<Artist, Song>> =
+            mMusicDao.getAllArtistAndTheirSongsAsLiveData()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<Map<Artist, Song>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertThat(observer.get()?.get(mAcDc)).isEqualTo(mAcdcSong1)
+    }
+
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameLiveDataList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<Map<Artist, List<Song>>> =
+            mMusicDao.getAllArtistAndTheirSongsAsLiveDataList()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<Map<Artist, List<Song>>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertContentsOfResultMapWithList(observer.get()!!)
+    }
+
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameLiveDataSet() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<Map<Artist, Set<Song>>> =
+            mMusicDao.allArtistAndTheirSongsAsLiveDataSet()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<Map<Artist, Set<Song>>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertContentsOfResultMapWithSet(observer.get()!!)
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables with a [Flowable] map return type.
+     */
+    @Test
+    fun testJoinByArtistNameFlowableList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapFlowable: Flowable<Map<Artist, List<Song>>> =
+            mMusicDao.getAllArtistAndTheirSongsAsFlowableList()
+        assertContentsOfResultMapWithList(artistToSongsMapFlowable.blockingFirst())
+    }
+
+    @Test
+    fun testJoinByArtistNameFlowableSet() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapFlowable: Flowable<Map<Artist, Set<Song>>> =
+            mMusicDao.allArtistAndTheirSongsAsFlowableSet()
+        assertContentsOfResultMapWithSet(artistToSongsMapFlowable.blockingFirst())
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables with a return type of a map with a key that
+     * is an entity [Artist] and a POJO [AlbumWithSongs] that use
+     * [androidx.room.Embedded] and [androidx.room.Relation].
+     */
+    @Test
+    fun testPojoWithEmbeddedAndRelation() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val artistToAlbumsWithSongsMap: Map<Artist, AlbumWithSongs> =
+            mMusicDao.getAllArtistAndTheirAlbumsWithSongs()
+        val rhcpAlbum: AlbumWithSongs? = artistToAlbumsWithSongsMap[mRhcp]
+
+        assertThat(rhcpAlbum).isNotNull()
+        assertThat(artistToAlbumsWithSongsMap.keys).containsExactlyElementsIn(
+            arrayOf(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToAlbumsWithSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToAlbumsWithSongsMap[mPinkFloyd]?.album)
+            .isEqualTo(mTheDarkSideOfTheMoon)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc]?.album)
+            .isEqualTo(mHighwayToHell)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc]?.songs?.get(0)).isEqualTo(mAcdcSong1)
+        if (rhcpAlbum?.album?.equals(mStadiumArcadium) == true) {
+            assertThat(rhcpAlbum.songs).containsExactlyElementsIn(
+                listOf(mRhcpSong1, mRhcpSong2)
+            )
+        } else if (rhcpAlbum?.album?.equals(mCalifornication) == true) {
+            assertThat(rhcpAlbum.songs).isEmpty()
+        } else {
+            Assert.fail()
+        }
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables with a return type of a map with a key that
+     * is an entity [Artist] and a list of entity POJOs [AlbumWithSongs] that use
+     * [androidx.room.Embedded] and [androidx.room.Relation].
+     */
+    @Test
+    fun testPojoWithEmbeddedAndRelationList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val artistToAlbumsWithSongsMap: Map<Artist, List<AlbumWithSongs>> =
+            mMusicDao.getAllArtistAndTheirAlbumsWithSongsList()
+        mMusicDao.getAllArtistAndTheirAlbumsWithSongs()
+        val rhcpList: List<AlbumWithSongs> = artistToAlbumsWithSongsMap[mRhcp]!!
+        assertThat(artistToAlbumsWithSongsMap.keys).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToAlbumsWithSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToAlbumsWithSongsMap[mPinkFloyd]?.single()?.album)
+            .isEqualTo(mTheDarkSideOfTheMoon)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc]?.single()?.album)
+            .isEqualTo(mHighwayToHell)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc]?.single()?.songs?.get(0))
+            .isEqualTo(mAcdcSong1)
+        for (albumAndSong in rhcpList) {
+            when (albumAndSong.album) {
+                mStadiumArcadium -> {
+                    assertThat(albumAndSong.songs).containsExactlyElementsIn(
+                        listOf(mRhcpSong1, mRhcpSong2)
+                    )
+                }
+                mCalifornication -> {
+                    assertThat(albumAndSong.songs).isEmpty()
+                }
+                else -> {
+                    Assert.fail()
+                }
+            }
+        }
+    }
+
+    /**
+     * Tests a simple JOIN query between two tables with a return type of a map with a key
+     * [ReleasedAlbum] and value (list of [AlbumNameAndBandName]) that are non-entity
+     * POJOs.
+     */
+    @Test
+    fun testNonEntityPojosList() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: Map<ReleasedAlbum, List<AlbumNameAndBandName>> =
+            mMusicDao.getReleaseYearToAlbumsAndBandsList()
+        val allReleasedAlbums: Set<ReleasedAlbum> = map.keys
+        assertThat(allReleasedAlbums.size).isEqualTo(3)
+        allReleasedAlbums.forEach { album ->
+            when (album.mAlbumName) {
+                mStadiumArcadium.mAlbumName -> {
+                    assertThat(album.mReleaseYear).isEqualTo(
+                        mStadiumArcadium.mAlbumReleaseYear
+                    )
+                    val resultList = map[album] ?: emptyList()
+                    assertThat(resultList.size).isEqualTo(2)
+                    assertThat(resultList[0].mBandName)
+                        .isEqualTo(mRhcp.mArtistName)
+                    assertThat(resultList[0].mAlbumName)
+                        .isEqualTo(mStadiumArcadium.mAlbumName)
+                    assertThat(resultList[1].mBandName)
+                        .isEqualTo(mRhcp.mArtistName)
+                    assertThat(map[album]!![1].mAlbumName)
+                        .isEqualTo(mStadiumArcadium.mAlbumName)
+                }
+                mHighwayToHell.mAlbumName -> {
+                    assertThat(album.mReleaseYear).isEqualTo(mHighwayToHell.mAlbumReleaseYear)
+                    val resultList = map[album] ?: emptyList()
+                    assertThat(resultList.size).isEqualTo(1)
+                    assertThat(resultList[0].mBandName)
+                        .isEqualTo(mAcDc.mArtistName)
+                    assertThat(resultList[0].mAlbumName)
+                        .isEqualTo(mHighwayToHell.mAlbumName)
+                }
+                mTheDarkSideOfTheMoon.mAlbumName -> {
+                    assertThat(album.mReleaseYear)
+                        .isEqualTo(mTheDarkSideOfTheMoon.mAlbumReleaseYear)
+                    val resultList = map[album] ?: emptyList()
+                    assertThat(resultList.size).isEqualTo(1)
+                    assertThat(resultList[0].mBandName).isEqualTo(mPinkFloyd.mArtistName)
+                    assertThat(resultList[0].mAlbumName).isEqualTo(mTheDarkSideOfTheMoon.mAlbumName)
+                }
+                else -> {
+                    // Shouldn't get here as we expect only the 3 albums to be keys in the map
+                    Assert.fail()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testJoinByArtistNameGuavaImmutableListMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongs: ImmutableListMultimap<Artist, Song> =
+            mMusicDao.allArtistAndTheirSongsGuavaImmutableListMultimap()
+        assertContentsOfResultMultimap(artistToSongs)
+    }
+
+    @Test
+    fun testJoinByArtistNameGuavaImmutableSetMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongs: ImmutableSetMultimap<Artist, Song> =
+            mMusicDao.allArtistAndTheirSongsGuavaImmutableSetMultimap()
+        assertContentsOfResultMultimap(artistToSongs)
+    }
+
+    @Test
+    fun testJoinByArtistNameRawQueryGuavaImmutableListMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: ImmutableListMultimap<Artist, Song> =
+            mMusicDao.getAllArtistAndTheirSongsRawQueryGuavaImmutableListMultimap(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song" +
+                        ".mArtist"
+                )
+            )
+        assertThat(artistToSongsMap[mAcDc]).containsExactly(mAcdcSong1)
+    }
+
+    @Test
+    fun testJoinByArtistNameRawQueryGuavaImmutableSetMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: ImmutableSetMultimap<Artist, Song> =
+            mMusicDao.getAllArtistAndTheirSongsRawQueryGuavaImmutableSetMultimap(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song" +
+                        ".mArtist"
+                )
+            )
+        assertThat(artistToSongsMap[mAcDc]).containsExactly(mAcdcSong1)
+    }
+
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameLiveDataGuavaImmutableListMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<ImmutableListMultimap<Artist, Song>> =
+            mMusicDao.allArtistAndTheirSongsAsLiveDataGuavaImmutableListMultimap()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<ImmutableListMultimap<Artist, Song>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertContentsOfResultMultimap(observer.get()!!)
+    }
+
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameLiveDataGuavaImmutableSetMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<ImmutableSetMultimap<Artist, Song>> =
+            mMusicDao.allArtistAndTheirSongsAsLiveDataGuavaImmutableSetMultimap()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<ImmutableSetMultimap<Artist, Song>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertContentsOfResultMultimap(observer.get()!!)
+    }
+
+    @Test
+    fun testPojoWithEmbeddedAndRelationGuavaImmutableListMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val artistToAlbumsWithSongsMap: ImmutableListMultimap<Artist, AlbumWithSongs> =
+            mMusicDao.allArtistAndTheirAlbumsWithSongsGuavaImmutableListMultimap()
+        val rhcpList: ImmutableList<AlbumWithSongs> = artistToAlbumsWithSongsMap[mRhcp]
+        assertThat(artistToAlbumsWithSongsMap.keySet()).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToAlbumsWithSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToAlbumsWithSongsMap[mPinkFloyd][0].album)
+            .isEqualTo(mTheDarkSideOfTheMoon)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc][0].album)
+            .isEqualTo(mHighwayToHell)
+        assertThat(
+            artistToAlbumsWithSongsMap[mAcDc][0].songs[0]
+        ).isEqualTo(mAcdcSong1)
+        for (albumAndSong in rhcpList) {
+            when (albumAndSong.album) {
+                mStadiumArcadium -> {
+                    assertThat(albumAndSong.songs).containsExactlyElementsIn(
+                        listOf(mRhcpSong1, mRhcpSong2)
+                    )
+                }
+                mCalifornication -> {
+                    assertThat(albumAndSong.songs).isEmpty()
+                }
+                else -> {
+                    Assert.fail()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testPojoWithEmbeddedAndRelationGuavaImmutableSetMultimap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val artistToAlbumsWithSongsMap: ImmutableSetMultimap<Artist, AlbumWithSongs> =
+            mMusicDao.allArtistAndTheirAlbumsWithSongsGuavaImmutableSetMultimap()
+        val rhcpList: ImmutableSet<AlbumWithSongs> = artistToAlbumsWithSongsMap[mRhcp]
+        assertThat(artistToAlbumsWithSongsMap.keySet()).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToAlbumsWithSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToAlbumsWithSongsMap[mPinkFloyd].asList()[0].album)
+            .isEqualTo(mTheDarkSideOfTheMoon)
+        assertThat(artistToAlbumsWithSongsMap[mAcDc].asList()[0].album)
+            .isEqualTo(mHighwayToHell)
+        assertThat(
+            artistToAlbumsWithSongsMap[mAcDc].asList()[0].songs[0]
+        ).isEqualTo(mAcdcSong1)
+        for (albumAndSong in rhcpList) {
+            when (albumAndSong.album) {
+                mStadiumArcadium -> {
+                    assertThat(albumAndSong.songs).containsExactlyElementsIn(
+                        listOf(mRhcpSong1, mRhcpSong2)
+                    )
+                }
+                mCalifornication -> {
+                    assertThat(albumAndSong.songs).isEmpty()
+                }
+                else -> {
+                    Assert.fail()
+                }
+            }
+        }
+    }
+
+    @Test
+    fun testJoinByArtistNameImmutableMap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: ImmutableMap<Artist, List<Song>> =
+            mMusicDao.allArtistAndTheirSongsImmutableMap()
+        assertContentsOfResultMapWithList(artistToSongsMap)
+    }
+
+    @Test
+    fun testJoinByArtistNameRawQueryImmutableMap() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMap: ImmutableMap<Artist, List<Song>> =
+            mMusicDao.getAllArtistAndTheirSongsRawQueryImmutableMap(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song" +
+                        ".mArtist"
+                )
+            )
+        assertContentsOfResultMapWithList(artistToSongsMap)
+    }
+
+    @Test
+    @Throws(ExecutionException::class, InterruptedException::class, TimeoutException::class)
+    fun testJoinByArtistNameImmutableMapWithSet() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistToSongsMapLiveData: LiveData<ImmutableMap<Artist, Set<Song>>> =
+            mMusicDao.allArtistAndTheirSongsAsLiveDataImmutableMap()
+        val testOwner = TestLifecycleOwner(Lifecycle.State.CREATED)
+        val observer: TestObserver<ImmutableMap<Artist, Set<Song>>> = MyTestObserver()
+        TestUtil.observeOnMainThread(artistToSongsMapLiveData, testOwner, observer)
+        assertThat(observer.hasValue()).isFalse()
+        observer.reset()
+        testOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        assertThat(observer.get()).isNotNull()
+        assertContentsOfResultMapWithSet(observer.get()!!)
+    }
+
+    @Test
+    fun testStringToListOfSongs() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistNameToSongsMap: Map<String, List<Song>> = mMusicDao.artistNameToSongs()
+        assertThat(artistNameToSongsMap.containsKey("Pink Floyd")).isTrue()
+        assertThat(artistNameToSongsMap["Red Hot Chili Peppers"]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+    }
+
+    @Test
+    fun testIntegerToListOfAlbums() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val releaseYearToAlbumsMap: Map<Int, List<Song>> = mMusicDao.releaseYearToAlbums()
+        assertThat(releaseYearToAlbumsMap.containsKey(2006)).isTrue()
+        assertThat(releaseYearToAlbumsMap[2006]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+        assertThat(releaseYearToAlbumsMap[1979]).containsExactlyElementsIn(
+            listOf<Any>(mAcdcSong1)
+        )
+    }
+
+    @Test
+    fun testIntegerToStringOfAlbumNames() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val releaseYearToAlbumNameMap: Map<Int, List<String>> =
+            mMusicDao.releaseYearToSongNames()
+        assertThat(releaseYearToAlbumNameMap.containsKey(2006)).isTrue()
+        assertThat(releaseYearToAlbumNameMap[2006]).containsExactlyElementsIn(
+            listOf("Snow (Hey Oh)", "Dani California")
+        )
+    }
+
+    @Test
+    fun testStringToListOfSongsRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistNameToSongsMap: Map<String, List<Song>> = mMusicDao.getArtistNameToSongsRawQuery(
+            SimpleSQLiteQuery(
+                "SELECT * FROM Artist JOIN Song ON Artist.mArtistName = Song.mArtist"
+            )
+        )
+        assertThat(artistNameToSongsMap.containsKey("Pink Floyd")).isTrue()
+        assertThat(artistNameToSongsMap["Red Hot Chili Peppers"]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+    }
+
+    @Test
+    fun testIntegerToListOfAlbumsRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val releaseYearToAlbumsMap: Map<Int, List<Song>> =
+            mMusicDao.getReleaseYearToAlbumsRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Album JOIN Song ON Song.mReleasedYear = Album" +
+                        ".mAlbumReleaseYear"
+                )
+            )
+        assertThat(releaseYearToAlbumsMap.containsKey(2006)).isTrue()
+        assertThat(releaseYearToAlbumsMap[2006]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+        assertThat(releaseYearToAlbumsMap[1979]).containsExactlyElementsIn(
+            listOf<Any>(mAcdcSong1)
+        )
+    }
+
+    @Test
+    fun testIntegerToStringOfAlbumNamesRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val releaseYearToAlbumNameMap: Map<Int, List<String>> =
+            mMusicDao.getReleaseYearToSongNamesRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Album JOIN Song ON Song.mReleasedYear = Album" +
+                        ".mAlbumReleaseYear"
+                )
+            )
+        assertThat(releaseYearToAlbumNameMap.containsKey(2006)).isTrue()
+        assertThat(releaseYearToAlbumNameMap[2006]).containsExactlyElementsIn(
+            listOf("Snow (Hey Oh)", "Dani California")
+        )
+    }
+
+    @Test
+    fun testArtistToSongCount() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistNameToSongsMap: Map<Artist, Int> = mMusicDao.artistAndSongCountMap()
+        assertThat(artistNameToSongsMap.containsKey(mPinkFloyd)).isTrue()
+        assertThat(artistNameToSongsMap[mRhcp]).isEqualTo(2)
+    }
+
+    @Test
+    fun testArtistToSongCountWithRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        val artistNameToSongsMap: Map<Artist, Int> = mMusicDao.getArtistAndSongCountMapRawQuery(
+            SimpleSQLiteQuery(
+                "SELECT *, COUNT(mSongId) as songCount FROM Artist JOIN Song ON Artist" +
+                    ".mArtistName = Song.mArtist GROUP BY mArtistName"
+            )
+        )
+        assertThat(artistNameToSongsMap.containsKey(mPinkFloyd)).isTrue()
+        assertThat(artistNameToSongsMap[mRhcp]).isEqualTo(2)
+    }
+
+    @Test
+    fun testArtistToImage() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val artistNameToImagesMap: ImmutableMap<Artist, ByteBuffer> =
+            mMusicDao.allArtistsWithAlbumCovers()
+        assertThat(artistNameToImagesMap.containsKey(mPinkFloyd)).isTrue()
+        assertThat(artistNameToImagesMap[mRhcp]).isEqualTo(
+            ByteBuffer.wrap("stadium_arcadium_image".toByteArray())
+        )
+    }
+
+    @Test
+    fun testArtistToImageRawQuery() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val artistNameToImagesMap: ImmutableMap<Artist, ByteBuffer> =
+            mMusicDao.getAllArtistsWithAlbumCoversRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Artist JOIN Image ON Artist.mArtistName = Image" +
+                        ".mArtistInImage"
+                )
+            )
+        assertThat(artistNameToImagesMap.containsKey(mPinkFloyd)).isTrue()
+        assertThat(artistNameToImagesMap[mRhcp]).isEqualTo(
+            ByteBuffer.wrap("stadium_arcadium_image".toByteArray())
+        )
+    }
+
+    @Test
+    fun testArtistToImageYear() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val artistNameToImagesMap: ImmutableMap<Artist, Long> =
+            mMusicDao.allArtistsWithAlbumCoverYear()
+        assertThat(artistNameToImagesMap[mRhcp]).isEqualTo(2006L)
+    }
+
+    @Test
+    fun testImageYearToArtistRawQuery() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<Long, Artist> =
+            mMusicDao.getAllAlbumCoverYearToArtistsWithRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image" +
+                        ".mArtistInImage"
+                )
+            )
+        assertThat(imageToArtistsMap[2006L]).isEqualTo(mRhcp)
+        assertThat(
+            imageToArtistsMap.keys
+        ).containsExactlyElementsIn(
+            listOf(2006L, 1973L)
+        )
+    }
+
+    @Test
+    fun testAlbumCoversWithBandActivity() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<ByteBuffer, Boolean> =
+            mMusicDao.albumCoversWithBandActivity()
+        assertThat(
+            imageToArtistsMap[ByteBuffer.wrap("stadium_arcadium_image".toByteArray())]
+        ).isEqualTo(true)
+        assertThat(
+            imageToArtistsMap[ByteBuffer.wrap("dark_side_of_the_moon_image".toByteArray())]
+        ).isEqualTo(false)
+    }
+
+    @Test
+    fun testAlbumCoversWithBandActivityRawQuery() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<ByteBuffer, Boolean> =
+            mMusicDao.getAlbumCoversWithBandActivityRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image" +
+                        ".mArtistInImage"
+                )
+            )
+        assertThat(imageToArtistsMap[ByteBuffer.wrap("stadium_arcadium_image".toByteArray())])
+            .isEqualTo(true)
+        assertThat(
+            imageToArtistsMap[ByteBuffer.wrap("dark_side_of_the_moon_image".toByteArray())]
+        ).isEqualTo(false)
+    }
+
+    @Test
+    fun testAlbumReleaseDateWithBandActivity() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<Date, Boolean> =
+            mMusicDao.albumDateWithBandActivity()
+        assertThat(imageToArtistsMap[Date(101779200000L)]).isEqualTo(false)
+        assertThat(imageToArtistsMap[Date(1146787200000L)]).isEqualTo(true)
+    }
+
+    @Test
+    fun testAlbumReleaseDateWithBandActivityRawQuery() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<Date, Boolean> =
+            mMusicDao.getAlbumDateWithBandActivityRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image" +
+                        ".mArtistInImage"
+                )
+            )
+        assertThat(imageToArtistsMap[Date(101779200000L)]).isEqualTo(false)
+        assertThat(imageToArtistsMap[Date(1146787200000L)]).isEqualTo(true)
+    }
+
+    @Test
+    fun testEnumMap() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<ImageFormat, Boolean> =
+            mMusicDao.imageFormatWithBandActivity()
+        assertThat(imageToArtistsMap[ImageFormat.JPG]).isEqualTo(false)
+        assertThat(imageToArtistsMap[ImageFormat.MPEG]).isEqualTo(true)
+    }
+
+    @Test
+    fun testEnumMapWithRawQuery() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addImages(mPinkFloydAlbumCover, mRhcpAlbumCover)
+        val imageToArtistsMap: ImmutableMap<ImageFormat, Boolean> =
+            mMusicDao.getImageFormatWithBandActivityRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT * FROM Image JOIN Artist ON Artist.mArtistName = Image" +
+                        ".mArtistInImage"
+                )
+            )
+        assertThat(imageToArtistsMap[ImageFormat.JPG]).isEqualTo(false)
+        assertThat(imageToArtistsMap[ImageFormat.MPEG]).isEqualTo(true)
+    }
+
+    @Test
+    fun testInvalidMapInfoColumnsWithRawQuery() {
+        mMusicDao.addSongs(mRhcpSong1, mRhcpSong2, mAcdcSong1, mPinkFloydSong1)
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        try {
+            mMusicDao.getMapWithInvalidColumnRawQuery(
+                SimpleSQLiteQuery(
+                    "SELECT *, COUNT(mSongId) as songCount FROM Artist JOIN Song ON Artist" +
+                        ".mArtistName = Song.mArtist GROUP BY mArtistName"
+                )
+            )
+        } catch (e: IllegalArgumentException) {
+            assertThat(e.message!!.contains("column 'cat' does not exist"))
+        }
+    }
+
+    @Test
+    fun testLeftJoin() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: Map<Artist, List<Album>> = mMusicDao.artistAndAlbumsLeftJoin()
+        assertThat(map.containsKey(mTheClash))
+        assertThat(map[mTheClash]).isEmpty()
+    }
+
+    @Test
+    fun testLeftJoinGuava() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: ImmutableListMultimap<Artist, Album> = mMusicDao.artistAndAlbumsLeftJoinGuava()
+        assertThat(map.containsKey(mTheClash))
+        assertThat(map[mTheClash]).isEmpty()
+    }
+
+    @Test
+    fun testNonPojoLeftJoin() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: Map<Artist, List<String>> = mMusicDao.artistAndAlbumNamesLeftJoin()
+        assertThat(map.containsKey(mTheClash))
+        assertThat(map[mTheClash]).isEmpty()
+    }
+
+    @Test
+    fun nullKeyColumnLeftJoin() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: Map<Album, Artist> = mMusicDao.albumToArtistLeftJoin()
+        assertThat(map.containsKey(mHighwayToHell))
+        assertThat(map[mHighwayToHell]).isEqualTo(mAcDc)
+    }
+
+    @Test
+    fun nullValueColumnLeftJoin() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell
+        )
+        val map: Map<Artist, Album> = mMusicDao.artistToAlbumLeftJoin()
+        assertThat(map.containsKey(mAcDc))
+        assertThat(map[mAcDc]).isEqualTo(mHighwayToHell)
+    }
+
+    @Test
+    fun nullAlbumAddedLeftJoin() {
+        mMusicDao.addArtists(mRhcp, mAcDc, mTheClash, mPinkFloyd, mGlassAnimals)
+        mMusicDao.addAlbums(
+            mStadiumArcadium,
+            mCalifornication,
+            mTheDarkSideOfTheMoon,
+            mHighwayToHell,
+            mDreamland
+        )
+        val map: Map<Artist, Album> = mMusicDao.artistToAlbumLeftJoin()
+        assertThat(map.containsKey(mGlassAnimals)).isFalse()
+    }
+
+    /**
+     * Checks that the contents of the map are as expected.
+     *
+     * @param artistToSongsMap Map of Artists to list of Songs joined by the artist name
+     */
+    private fun assertContentsOfResultMapWithList(artistToSongsMap: Map<Artist, List<Song>>) {
+        assertThat(artistToSongsMap.keys).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToSongsMap[mPinkFloyd]).containsExactly(mPinkFloydSong1)
+        assertThat(artistToSongsMap[mRhcp]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+        assertThat(artistToSongsMap[mAcDc]).containsExactly(mAcdcSong1)
+    }
+
+    /**
+     * Checks that the contents of the map are as expected.
+     *
+     * @param artistToSongsMap Map of Artists to set of Songs joined by the artist name
+     */
+    private fun assertContentsOfResultMapWithSet(artistToSongsMap: Map<Artist, Set<Song>>) {
+        assertThat(artistToSongsMap.keys).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToSongsMap[mPinkFloyd]).containsExactly(mPinkFloydSong1)
+        assertThat(artistToSongsMap[mRhcp]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+        assertThat(artistToSongsMap[mAcDc]).containsExactly(mAcdcSong1)
+    }
+
+    /**
+     * Checks that the contents of the map are as expected.
+     *
+     * @param artistToSongsMap Map of Artists to Collection of Songs joined by the artist name
+     */
+    private fun assertContentsOfResultMultimap(artistToSongsMap: ImmutableMultimap<Artist, Song>) {
+        assertThat(artistToSongsMap.keySet()).containsExactlyElementsIn(
+            listOf<Any>(mRhcp, mAcDc, mPinkFloyd)
+        )
+        assertThat(artistToSongsMap.containsKey(mTheClash)).isFalse()
+        assertThat(artistToSongsMap[mPinkFloyd]).containsExactly(mPinkFloydSong1)
+        assertThat(artistToSongsMap[mRhcp]).containsExactlyElementsIn(
+            listOf<Any>(mRhcpSong1, mRhcpSong2)
+        )
+        assertThat(artistToSongsMap[mAcDc]).containsExactly(mAcdcSong1)
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestObserver.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestObserver.kt
new file mode 100644
index 0000000..fffd296
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestObserver.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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.integration.kotlintestapp.test
+
+import androidx.lifecycle.Observer
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.TimeoutException
+
+abstract class TestObserver<T> : Observer<T> {
+    private var mLastData: T? = null
+    private var mHasValue = false
+    fun reset() {
+        mHasValue = false
+        mLastData = null
+    }
+
+    override fun onChanged(value: T) {
+        mLastData = value
+        mHasValue = true
+    }
+
+    @Throws(TimeoutException::class, InterruptedException::class)
+    fun hasValue(): Boolean {
+        drain()
+        return mHasValue
+    }
+
+    @Throws(InterruptedException::class, TimeoutException::class)
+    fun get(): T? {
+        drain()
+        assertThat(hasValue()).isTrue()
+        return mLastData
+    }
+
+    @Throws(TimeoutException::class, InterruptedException::class)
+    protected abstract fun drain()
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
index c94c1cb..1b401bc 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/TestUtil.kt
@@ -24,18 +24,21 @@
 import androidx.room.integration.kotlintestapp.vo.Book
 import androidx.room.integration.kotlintestapp.vo.BookAuthor
 import androidx.room.integration.kotlintestapp.vo.Lang
+import androidx.room.integration.kotlintestapp.vo.Pet
 import androidx.room.integration.kotlintestapp.vo.Publisher
+import java.util.Date
+import java.util.UUID
 import java.util.concurrent.FutureTask
 
 class TestUtil {
 
     companion object {
-        fun observeOnMainThread(
-            liveData: LiveData<Book>,
+        fun <T> observeOnMainThread(
+            liveData: LiveData<T>,
             provider: LifecycleOwner,
-            observer: Observer<Book>
+            observer: Observer<T>
         ) {
-            val futureTask = FutureTask<Unit> {
+            val futureTask = FutureTask {
                 liveData.observe(provider, observer)
             }
             ArchTaskExecutor.getInstance().executeOnMainThread(futureTask)
@@ -65,5 +68,13 @@
         val BOOK_AUTHOR_1_1 = BookAuthor(BOOK_1.bookId, AUTHOR_1.authorId)
         val BOOK_AUTHOR_1_2 = BookAuthor(BOOK_1.bookId, AUTHOR_2.authorId)
         val BOOK_AUTHOR_2_2 = BookAuthor(BOOK_2.bookId, AUTHOR_2.authorId)
+
+        fun createPet(id: Int): Pet {
+            val pet = Pet()
+            pet.mPetId = id
+            pet.mName = UUID.randomUUID().toString()
+            pet.mAdoptionDate = Date()
+            return pet
+        }
     }
 }
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/AlbumNameAndBandName.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/AlbumNameAndBandName.kt
index 96dec5c..492913c 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/AlbumNameAndBandName.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/AlbumNameAndBandName.kt
@@ -15,4 +15,4 @@
  */
 package androidx.room.integration.kotlintestapp.vo
 
-data class AlbumNameAndBandName(val albumName: String?, val bandName: String?)
\ No newline at end of file
+data class AlbumNameAndBandName(val mAlbumName: String?, val mBandName: String?)
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Day.kt
similarity index 72%
copy from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
copy to room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Day.kt
index 3d299bc..d71dcc5 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Day.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.room.integration.kotlintestapp.vo
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-import androidx.compose.ui.input.pointer.PointerIcon
-
-internal expect val textPointerIcon: PointerIcon
\ No newline at end of file
+enum class Day {
+    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Experiment.kt
similarity index 68%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
rename to room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Experiment.kt
index 54ee1ec..99a7600 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Experiment.kt
@@ -14,10 +14,14 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.copypasta
+package androidx.room.androidx.room.integration.kotlintestapp.vo
 
-/**
- * This is a temporary workaround and should be removed after proper mouse handling is settled
- * (b/171402426).
- */
-internal val isInTouchMode: Boolean = true
\ No newline at end of file
+@JvmInline
+value class Schrodinger(val experiment: Experiment)
+
+@JvmInline
+value class Cat(val catStatus: CatStatus)
+
+data class Experiment(val isCatAlive: String)
+
+data class CatStatus(val isCatAlive: String)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Image.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Image.kt
new file mode 100644
index 0000000..d6493a4
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Image.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.room.integration.kotlintestapp.vo
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.util.Date
+
+@Entity
+class Image(
+    @field:PrimaryKey val mImageId: Int,
+    val mImageYear: Long,
+    val mArtistInImage: String,
+    val mAlbumCover: ByteArray,
+    val mDateReleased: Date,
+    format: ImageFormat
+) {
+    val mFormat: ImageFormat
+
+    init {
+        mFormat = format
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ImageFormat.kt
similarity index 72%
copy from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
copy to room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ImageFormat.kt
index 3d299bc..9fcdb1c 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ImageFormat.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.room.integration.kotlintestapp.vo
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-import androidx.compose.ui.input.pointer.PointerIcon
-
-internal expect val textPointerIcon: PointerIcon
\ No newline at end of file
+enum class ImageFormat {
+    JPG, GIF, MPEG
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Pet.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Pet.kt
new file mode 100644
index 0000000..92d22dc
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Pet.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.vo
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.TypeConverters
+import androidx.room.integration.kotlintestapp.TestDatabase
+import java.util.Date
+
+@Entity
+@TypeConverters(TestDatabase.Converters::class)
+class Pet {
+    @PrimaryKey
+    var mPetId = 0
+    var mUserId = 0
+
+    @ColumnInfo(name = "mPetName")
+    var mName: String? = null
+    var mAdoptionDate: Date? = null
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || javaClass != other.javaClass) return false
+        val pet = other as Pet
+        if (mPetId != pet.mPetId) return false
+        if (mUserId != pet.mUserId) return false
+        if (if (mName != null) mName != pet.mName else pet.mName != null) return false
+        return if (mAdoptionDate != null) mAdoptionDate == pet.mAdoptionDate else
+            pet.mAdoptionDate == null
+    }
+
+    override fun hashCode(): Int {
+        var result = mPetId
+        result = 31 * result + mUserId
+        result = 31 * result + if (mName != null) mName.hashCode() else 0
+        result = 31 * result + if (mAdoptionDate != null) mAdoptionDate.hashCode() else 0
+        return result
+    }
+
+    override fun toString(): String {
+        return ("Pet{" +
+            "mPetId=" + mPetId +
+            ", mUserId=" + mUserId +
+            ", mName='" + mName + '\'' +
+            ", mAdoptionDate=" + mAdoptionDate +
+            '}')
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetAndOwner.kt
similarity index 63%
copy from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
copy to room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetAndOwner.kt
index 54ee1ec..566ad1d 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetAndOwner.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * 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.
@@ -13,11 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.room.integration.kotlintestapp.vo
 
-package androidx.compose.foundation.newtext.text.copypasta
+import androidx.room.Embedded
+import androidx.room.Relation
 
-/**
- * This is a temporary workaround and should be removed after proper mouse handling is settled
- * (b/171402426).
- */
-internal val isInTouchMode: Boolean = true
\ No newline at end of file
+class PetAndOwner(
+    @field:Embedded val mPet: Pet,
+    @field:Relation(
+        parentColumn = "mUserId",
+        entityColumn = "mId"
+    ) val mUser: PetUser
+)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetUser.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetUser.kt
new file mode 100644
index 0000000..d0e5261
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetUser.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.vo
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.TypeConverters
+import androidx.room.integration.kotlintestapp.TestDatabase
+import java.lang.Float.floatToIntBits
+import java.util.Date
+
+@Entity
+@TypeConverters(TestDatabase.Converters::class)
+class PetUser {
+    @PrimaryKey
+    var mId = 0
+    var mName: String? = null
+    var mLastName: String? = null
+    var mAge = 0
+    var mAdmin = false
+    var mWeight = 0f
+    var mBirthday: Date? = null
+
+    @ColumnInfo(name = "custommm", collate = ColumnInfo.NOCASE)
+    var mCustomField: String? = null
+
+    // bit flags
+    lateinit var mWorkDays: Set<Day>
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || javaClass != other.javaClass) return false
+        val user = other as PetUser
+        if (mId != user.mId) return false
+        if (mAge != user.mAge) return false
+        if (mAdmin != user.mAdmin) return false
+        if (user.mWeight.compareTo(mWeight) != 0) return false
+        if (if (mName != null) mName != user.mName else user.mName != null) return false
+        if (if (mLastName != null) mLastName != user.mLastName else user.mLastName != null) {
+            return false
+        }
+        if (if (mBirthday != null) mBirthday != user.mBirthday else user.mBirthday != null) {
+            return false
+        }
+        if (if (mCustomField != null) mCustomField != user.mCustomField else
+            user.mCustomField != null) {
+            return false
+        }
+        return mWorkDays == user.mWorkDays
+    }
+
+    override fun hashCode(): Int {
+        var result = mId
+        result = 31 * result + if (mName != null) mName.hashCode() else 0
+        result = 31 * result + if (mLastName != null) mLastName.hashCode() else 0
+        result = 31 * result + mAge
+        result = 31 * result + if (mAdmin) 1 else 0
+        result = 31 * result + if (mWeight != +0.0f) floatToIntBits(mWeight) else 0
+        result = 31 * result + if (mBirthday != null) mBirthday.hashCode() else 0
+        result = 31 * result + if (mCustomField != null) mCustomField.hashCode() else 0
+        result = 31 * result + mWorkDays.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return ("User{" +
+            "mId=" + mId +
+            ", mName='" + mName + '\'' +
+            ", mLastName='" + mLastName + '\'' +
+            ", mAge=" + mAge +
+            ", mAdmin=" + mAdmin +
+            ", mWeight=" + mWeight +
+            ", mBirthday=" + mBirthday +
+            ", mCustomField='" + mCustomField + '\'' +
+            ", mWorkDays=" + mWorkDays +
+            '}')
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithToyIds.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithToyIds.kt
new file mode 100644
index 0000000..f78770c
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithToyIds.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.vo
+
+import androidx.room.Embedded
+import androidx.room.Ignore
+import androidx.room.Relation
+
+class PetWithToyIds {
+    @Embedded
+    val mPet: Pet?
+
+    @Relation(
+        parentColumn = "mPetId",
+        entityColumn = "mPetId",
+        projection = ["mId"],
+        entity = Toy::class
+    )
+    var mToyIds: List<Int>? = null
+
+    // for the relation
+    constructor(pet: Pet?) {
+        this.mPet = pet
+    }
+
+    @Ignore
+    constructor(pet: Pet?, toyIds: List<Int>?) {
+        this.mPet = pet
+        this.mToyIds = toyIds
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || javaClass != other.javaClass) return false
+        val that = other as PetWithToyIds
+        if (if (mPet != null) !mPet.equals(that.mPet) else that.mPet != null) return false
+        return if (mToyIds != null) mToyIds == that.mToyIds else that.mToyIds == null
+    }
+
+    override fun hashCode(): Int {
+        var result = mPet?.hashCode() ?: 0
+        result = 31 * result + if (mToyIds != null) mToyIds.hashCode() else 0
+        return result
+    }
+
+    override fun toString(): String {
+        return ("PetWithToyIds{" +
+            "pet=" + mPet +
+            ", toyIds=" + mToyIds +
+            '}')
+    }
+}
\ No newline at end of file
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithUser.kt
similarity index 60%
copy from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
copy to room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithUser.kt
index 54ee1ec..91c347e 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TouchMode.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PetWithUser.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,11 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.room.integration.kotlintestapp.vo
 
-package androidx.compose.foundation.newtext.text.copypasta
+import androidx.room.DatabaseView
+import androidx.room.Embedded
 
-/**
- * This is a temporary workaround and should be removed after proper mouse handling is settled
- * (b/171402426).
- */
-internal val isInTouchMode: Boolean = true
\ No newline at end of file
+@DatabaseView(
+    "SELECT Pet.*, PetUser.* FROM Pet INNER JOIN PetUser ON Pet.mUserId = PetUser.mId"
+)
+data class PetWithUser(
+    @Embedded
+    var mPet: Pet,
+    @Embedded
+    var mUser: PetUser
+)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistMultiSongXRefView.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistMultiSongXRefView.kt
new file mode 100644
index 0000000..770db72
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistMultiSongXRefView.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.room.integration.kotlintestapp.vo
+
+import androidx.room.DatabaseView
+
+// View of join table with playlists with more than 1 song
+@DatabaseView(
+    "SELECT * FROM PlaylistSongXRef WHERE mPlaylistId IN (SELECT mPlaylistId FROM" +
+        " PlaylistSongXRef GROUP BY mPlaylistId HAVING COUNT(mSongId) > 1)"
+)
+class PlaylistMultiSongXRefView(val mPlaylistId: Int, val mSongId: Int)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistWithSongTitles.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistWithSongTitles.kt
new file mode 100644
index 0000000..a0194e2
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/PlaylistWithSongTitles.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.room.integration.kotlintestapp.vo
+
+import androidx.room.Embedded
+import androidx.room.Junction
+import androidx.room.Relation
+
+data class PlaylistWithSongTitles(
+    @Embedded
+    var playlist: Playlist,
+    @Relation(
+        parentColumn = "mPlaylistId",
+        entity = Song::class,
+        entityColumn = "mSongId",
+        associateBy = Junction(
+            PlaylistSongXRef::class
+        ),
+        projection = ["mTitle"]
+    )
+    var titles: List<String>
+)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ReleasedAlbum.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ReleasedAlbum.kt
index 811b5e315..0642cf6 100644
--- a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ReleasedAlbum.kt
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/ReleasedAlbum.kt
@@ -15,4 +15,4 @@
  */
 package androidx.room.integration.kotlintestapp.vo
 
-data class ReleasedAlbum(val releaseYear: Int, val albumName: String?)
\ No newline at end of file
+data class ReleasedAlbum(val mReleaseYear: Int, val mAlbumName: String?)
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/SchrodingerConverter.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/SchrodingerConverter.kt
new file mode 100755
index 0000000..edf961a
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/SchrodingerConverter.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.androidx.room.integration.kotlintestapp.vo
+
+import androidx.room.TypeConverter
+
+object SchrodingerConverter {
+    @TypeConverter
+    fun schrodingerToCat(schrodinger: Schrodinger): Cat {
+        return Cat(CatStatus(schrodinger.experiment.isCatAlive))
+    }
+
+    @TypeConverter
+    fun catToIsCatAlive(cat: Cat): String {
+        return cat.catStatus.isCatAlive
+    }
+
+    @TypeConverter
+    fun isCatAliveToCat(isCatAlive: String): Cat {
+        return Cat(CatStatus(isCatAlive))
+    }
+
+    @TypeConverter
+    fun catToSchrodinger(cat: Cat): Schrodinger {
+        return Schrodinger(Experiment(cat.catStatus.isCatAlive))
+    }
+}
diff --git a/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Toy.kt b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Toy.kt
new file mode 100644
index 0000000..56cf4b7
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/vo/Toy.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.room.integration.kotlintestapp.vo
+
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.Index
+import androidx.room.PrimaryKey
+
+/**
+ * The toys of a pet.
+ */
+@Entity(
+    indices = [Index(value = ["mName"], unique = true), Index(value = ["mPetId"])],
+    foreignKeys = [ForeignKey(
+        entity = Pet::class,
+        parentColumns = ["mPetId"],
+        childColumns = ["mPetId"],
+        deferred = true
+    )]
+)
+data class Toy(
+    @PrimaryKey(autoGenerate = true)
+    val mId: Int,
+    var mName: String?,
+    var mPetId: Int
+) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || javaClass != other.javaClass) return false
+        val toy = other as Toy
+        if (mId != toy.mId) return false
+        if (mPetId != toy.mPetId) return false
+        return if (mName != null) mName == toy.mName else toy.mName == null
+    }
+
+    override fun hashCode(): Int {
+        var result = mId
+        result = 31 * result + if (mName != null) mName.hashCode() else 0
+        result = 31 * result + mPetId
+        return result
+    }
+}
\ No newline at end of file
diff --git a/room/integration-tests/kotlintestapp/src/androidTestWithKsp/java/androidx/room/integration/kotlintestapp/NullabilityAwareTypeConversionTest.kt b/room/integration-tests/kotlintestapp/src/androidTestWithKspGenJava/java/androidx/room/integration/kotlintestapp/NullabilityAwareTypeConversionTest.kt
similarity index 100%
rename from room/integration-tests/kotlintestapp/src/androidTestWithKsp/java/androidx/room/integration/kotlintestapp/NullabilityAwareTypeConversionTest.kt
rename to room/integration-tests/kotlintestapp/src/androidTestWithKspGenJava/java/androidx/room/integration/kotlintestapp/NullabilityAwareTypeConversionTest.kt
diff --git a/room/integration-tests/kotlintestapp/src/androidTestWithKspGenKotlin/java/androidx/room/integration/kotlintestapp/test/ValueClassConverterWrapperTest.kt b/room/integration-tests/kotlintestapp/src/androidTestWithKspGenKotlin/java/androidx/room/integration/kotlintestapp/test/ValueClassConverterWrapperTest.kt
new file mode 100644
index 0000000..673ebd7
--- /dev/null
+++ b/room/integration-tests/kotlintestapp/src/androidTestWithKspGenKotlin/java/androidx/room/integration/kotlintestapp/test/ValueClassConverterWrapperTest.kt
@@ -0,0 +1,183 @@
+/*
+ * 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.integration.kotlintestapp.test
+
+import android.content.Context
+import androidx.room.Dao
+import androidx.room.Database
+import androidx.room.Entity
+import androidx.room.Insert
+import androidx.room.PrimaryKey
+import androidx.room.Query
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.room.TypeConverters
+import androidx.room.androidx.room.integration.kotlintestapp.vo.Experiment
+import androidx.room.androidx.room.integration.kotlintestapp.vo.Schrodinger
+import androidx.room.androidx.room.integration.kotlintestapp.vo.SchrodingerConverter
+import androidx.room.integration.kotlintestapp.vo.DateConverter
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import java.util.Date
+import java.util.UUID
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ValueClassConverterWrapperTest {
+
+    @JvmInline
+    value class UserWithInt(val password: Int)
+
+    @JvmInline
+    value class UserWithString(val password: String)
+
+    @JvmInline
+    value class UserWithUUID(val password: UUID)
+
+    @JvmInline
+    value class UserWithByte(val password: Byte)
+
+    @JvmInline
+    value class UserWithDate(val password: Date)
+
+    @JvmInline
+    value class UserWithGeneric<T>(val password: T)
+
+    enum class Season {
+        WINTER, SUMMER, SPRING, FALL
+    }
+
+    @JvmInline
+    value class UserWithEnum(val password: Season)
+
+    @JvmInline
+    value class UserWithStringInternal(internal val password: String)
+
+    @JvmInline
+    value class UserWithByteArray(val password: ByteArray)
+
+    @Entity
+    @TypeConverters(DateConverter::class, SchrodingerConverter::class)
+    class UserInfo(
+        @PrimaryKey
+        val pk: Int,
+        val userIntPwd: UserWithInt,
+        val userStringPwd: UserWithString,
+        val userUUIDPwd: UserWithUUID,
+        val userBytePwd: UserWithByte,
+        val userEnumPwd: UserWithEnum,
+        val userDatePwd: UserWithDate,
+        val userStringInternalPwd: UserWithStringInternal,
+        val userGenericPwd: UserWithGeneric<String>,
+        val userByteArrayPwd: UserWithByteArray,
+        val schrodingerUser: Schrodinger
+    ) {
+        override fun equals(other: Any?): Boolean {
+            val otherEntity = other as UserInfo
+            return pk == otherEntity.pk &&
+                userIntPwd == otherEntity.userIntPwd &&
+                userStringPwd == otherEntity.userStringPwd &&
+                userBytePwd == otherEntity.userBytePwd &&
+                userUUIDPwd == otherEntity.userUUIDPwd &&
+                userEnumPwd == otherEntity.userEnumPwd &&
+                userDatePwd == otherEntity.userDatePwd &&
+                userStringInternalPwd == otherEntity.userStringInternalPwd &&
+                userGenericPwd == otherEntity.userGenericPwd &&
+                userByteArrayPwd.password.contentEquals(otherEntity.userByteArrayPwd.password) &&
+                schrodingerUser.experiment.isCatAlive ==
+                otherEntity.schrodingerUser.experiment.isCatAlive
+        }
+
+        override fun hashCode(): Int {
+            return 1
+        }
+    }
+
+    @Dao
+    interface SampleDao {
+        @Query("SELECT * FROM UserInfo")
+        fun getEntity(): UserInfo
+
+        @Insert
+        fun insert(item: UserInfo)
+    }
+
+    @Database(
+        entities = [UserInfo::class],
+        version = 1,
+        exportSchema = false
+    )
+    abstract class ValueClassConverterWrapperDatabase : RoomDatabase() {
+        abstract fun dao(): SampleDao
+    }
+
+    private lateinit var db: ValueClassConverterWrapperDatabase
+    private val pk = 0
+    private val intPwd = UserWithInt(123)
+    private val stringPwd = UserWithString("open_sesame")
+    private val uuidPwd = UserWithUUID(UUID.randomUUID())
+    private val bytePwd = UserWithByte(Byte.MIN_VALUE)
+    private val enumPwd = UserWithEnum(Season.SUMMER)
+    private val datePwd = UserWithDate(Date(2023L))
+    private val internalPwd = UserWithStringInternal("open_sesame")
+    private val genericPwd = UserWithGeneric("open_sesame")
+    private val byteArrayPwd = UserWithByteArray(byteArrayOf(Byte.MIN_VALUE))
+    private val shrodingerPwd = Schrodinger(Experiment("the cat is alive!"))
+
+    @Test
+    fun readAndWriteValueClassToDatabase() {
+        val customerInfo = UserInfo(
+            pk = pk,
+            userIntPwd = intPwd,
+            userStringPwd = stringPwd,
+            userUUIDPwd = uuidPwd,
+            userBytePwd = bytePwd,
+            userEnumPwd = enumPwd,
+            userDatePwd = datePwd,
+            userStringInternalPwd = internalPwd,
+            userGenericPwd = genericPwd,
+            userByteArrayPwd = byteArrayPwd,
+            schrodingerUser = shrodingerPwd
+        )
+
+        db.dao().insert(customerInfo)
+
+        val readEntity = db.dao().getEntity()
+
+        assertThat(readEntity).isEqualTo(customerInfo)
+    }
+
+    @Before
+    fun initDb() {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        db = Room.inMemoryDatabaseBuilder(
+            context,
+            ValueClassConverterWrapperDatabase::class.java
+        ).build()
+    }
+
+    @After
+    fun teardown() {
+        db.close()
+    }
+}
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index cb426c3..6267016 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -40,13 +40,12 @@
     buildFeatures {
         aidl = true
     }
-    buildTypes {
-        debug {
-            // Need to make sure androidx.tracing.Trace gets put in primary dex for legacy multidex
-            // as it is needed by androidx.test.runner.AndroidJUnitRunner
-            multiDexKeepFile file('multidex-config.txt')
-        }
+    buildTypes.all {
+        // Need to make sure certain classes are put in primary dex as they're used early in
+        // process creation, and would fail to load on non-native-multidex API versions
+        multiDexKeepProguard file('multidex-rules.pro')
     }
+
     sourceSets {
         androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
         androidTest.assets.srcDirs += files("$projectDir/databases".toString())
@@ -122,16 +121,19 @@
     androidTestImplementation(project(":room:room-guava"))
     androidTestImplementation(project(":room:room-paging"))
     androidTestImplementation("androidx.arch.core:core-testing:2.0.1")
-    androidTestImplementation(projectOrArtifact(":annotation:annotation-experimental"))
-    androidTestImplementation(projectOrArtifact(":arch:core:core-runtime"))
     androidTestImplementation(projectOrArtifact(":paging:paging-runtime"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-runtime-testing"))
     androidTestImplementation(projectOrArtifact(":lifecycle:lifecycle-livedata"))
 
+    // guavaAndroid is a implementation dependency instead of androidTestImplementation because
+    // if it's in the androidTest apk it causes the test APK to be multidex in ways that break
+    // non-native multidex (< API 21). This should be changed back to androidTestImplementation
+    // once this app is minApi 21
+    implementation(libs.guavaAndroid)
+
     // libs.findbugs dependency resolves an app/testapp version conflict.
     androidTestImplementation(libs.findbugs)
-    androidTestImplementation(libs.guavaAndroid)
     androidTestImplementation(libs.rxjava2)
     androidTestImplementation(libs.rxjava3)
     androidTestImplementation(libs.testExtJunit)
diff --git a/room/integration-tests/testapp/multidex-config.txt b/room/integration-tests/testapp/multidex-config.txt
deleted file mode 100644
index c108ccb..0000000
--- a/room/integration-tests/testapp/multidex-config.txt
+++ /dev/null
@@ -1 +0,0 @@
-androidx/tracing/Trace.class
diff --git a/room/integration-tests/testapp/multidex-rules.pro b/room/integration-tests/testapp/multidex-rules.pro
new file mode 100644
index 0000000..b05591c
--- /dev/null
+++ b/room/integration-tests/testapp/multidex-rules.pro
@@ -0,0 +1 @@
+-keep class androidx.tracing.Trace
\ No newline at end of file
diff --git a/room/room-common/build.gradle b/room/room-common/build.gradle
index 8930841..151639e 100644
--- a/room/room-common/build.gradle
+++ b/room/room-common/build.gradle
@@ -28,7 +28,7 @@
     testImplementation(libs.junit)
     testImplementation(libs.mockitoCore4)
     testImplementation(libs.guava)
-    testImplementation(libs.truth)
+    testImplementation(project(":internal-testutils-kmp"))
 }
 
 androidx {
diff --git a/room/room-common/src/test/java/androidx/room/AmbiguousColumnResolverTest.kt b/room/room-common/src/test/java/androidx/room/AmbiguousColumnResolverTest.kt
index 79d4f9c..80885a53 100644
--- a/room/room-common/src/test/java/androidx/room/AmbiguousColumnResolverTest.kt
+++ b/room/room-common/src/test/java/androidx/room/AmbiguousColumnResolverTest.kt
@@ -16,7 +16,7 @@
 
 package androidx.room
 
-import com.google.common.truth.Truth.assertThat
+import androidx.kruth.assertThat
 import java.util.Locale
 import org.junit.Test
 import org.junit.Ignore
diff --git a/room/room-common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt b/room/room-common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
index 55c1c81..43a60e5 100644
--- a/room/room-common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
+++ b/room/room-common/src/test/java/androidx/room/AnnotationRetentionPolicyTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room
 
+import androidx.kruth.assertThat
 import com.google.common.reflect.ClassPath
 import org.junit.Test
 import java.lang.annotation.Retention
@@ -36,10 +37,7 @@
         // For Room to be incremental, all annotations need to have CLASS retention policy.
         annotations.forEach {
             val retentionPolicy = it.getAnnotation(Retention::class.java)?.value
-            assert(retentionPolicy == RetentionPolicy.CLASS) {
-                "Expected ${it.name} annotation to have retention policy CLASS" +
-                    " but it is $retentionPolicy"
-            }
+            assertThat(retentionPolicy).isEqualTo(RetentionPolicy.CLASS)
         }
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableParameterElement.kt
index b5148d4..8454bd9 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XExecutableParameterElement.kt
@@ -20,6 +20,21 @@
  * Parameter of a method.
  */
 interface XExecutableParameterElement : XVariableElement {
+    /**
+     * Returns `true` if this parameter is a synthetic Continuation parameter of a suspend function.
+     */
+    fun isContinuationParam(): Boolean
+
+    /**
+     * Returns `true` if this parameter represents the receiver of an extension function.
+     */
+    fun isReceiverParam(): Boolean
+
+    /**
+     * Returns `true` if this parameter represents the single parameter of a Kotlin property setter
+     * method.
+     */
+    fun isKotlinPropertyParam(): Boolean
 
     /**
      * The enclosing [XExecutableElement] this parameter belongs to.
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
index efaa56e..4b1a7e9 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
@@ -19,9 +19,8 @@
 import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.javac.JavacProcessingEnv
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
-import com.google.devtools.ksp.processing.CodeGenerator
-import com.google.devtools.ksp.processing.KSPLogger
 import com.google.devtools.ksp.processing.Resolver
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
 import com.squareup.javapoet.ArrayTypeName
 import com.squareup.javapoet.TypeName
 import com.squareup.kotlinpoet.javapoet.KClassName
@@ -206,15 +205,11 @@
         @JvmStatic
         @JvmOverloads
         fun create(
-            options: Map<String, String>,
+            symbolProcessorEnvironment: SymbolProcessorEnvironment,
             resolver: Resolver,
-            codeGenerator: CodeGenerator,
-            logger: KSPLogger,
             config: XProcessingEnvConfig = XProcessingEnvConfig.DEFAULT
         ): XProcessingEnv = KspProcessingEnv(
-            options = options,
-            codeGenerator = codeGenerator,
-            logger = logger,
+            delegate = symbolProcessorEnvironment,
             config = config
         ).also { it.resolver = resolver }
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
index 0c6ab9a..1874984 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/compat/XConverters.kt
@@ -31,7 +31,6 @@
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.XVariableElement
-import androidx.room.compiler.processing.compat.XConverters.toXProcessing
 import androidx.room.compiler.processing.javac.JavacAnnotation
 import androidx.room.compiler.processing.javac.JavacAnnotationValue
 import androidx.room.compiler.processing.javac.JavacElement
@@ -54,7 +53,10 @@
 import androidx.room.compiler.processing.ksp.KspProcessingEnv
 import androidx.room.compiler.processing.ksp.KspType
 import androidx.room.compiler.processing.ksp.KspTypeElement
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticContinuationParameterElement
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
+import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticReceiverParameterElement
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
 import com.google.devtools.ksp.symbol.KSAnnotated
 import com.google.devtools.ksp.symbol.KSAnnotation
 import com.google.devtools.ksp.symbol.KSClassDeclaration
@@ -168,10 +170,20 @@
         (env as JavacProcessingEnv).wrap(this, null, null)
 
     @JvmStatic
+    fun XProcessingEnv.toKS(): SymbolProcessorEnvironment = (this as KspProcessingEnv).delegate
+
+    @JvmStatic
     fun XTypeElement.toKS(): KSClassDeclaration = (this as KspTypeElement).declaration
 
     @JvmStatic
-    fun XElement.toKS(): KSAnnotated = (this as KspElement).declaration
+    fun XElement.toKS(): KSAnnotated =
+        when (this) {
+            is KspElement -> this.declaration
+            is KspSyntheticPropertyMethodElement -> this.field.declaration
+            is KspSyntheticContinuationParameterElement -> this.enclosingElement.declaration
+            is KspSyntheticReceiverParameterElement -> this.enclosingElement.declaration
+            else -> error("Don't know how to convert element of type '${this::class}' to KSP")
+        }
 
     @JvmStatic
     fun XExecutableElement.toKS(): KSFunctionDeclaration =
@@ -249,6 +261,9 @@
         return when (this) {
             is JavacElement -> this.env
             is KspElement -> this.env
+            is KspSyntheticContinuationParameterElement -> this.env
+            is KspSyntheticPropertyMethodElement -> this.env
+            is KspSyntheticReceiverParameterElement -> this.env
             else -> error("Unexpected element: $this")
         }
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodParameter.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodParameter.kt
index 27aeaa5..88fe3b7 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodParameter.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodParameter.kt
@@ -30,6 +30,19 @@
     kotlinMetadataFactory: () -> KmValueParameterContainer?,
     val argIndex: Int
 ) : JavacVariableElement(env, element), XExecutableParameterElement {
+    override fun isContinuationParam() =
+        enclosingElement is JavacMethodElement &&
+        enclosingElement.isSuspendFunction() &&
+        enclosingElement.parameters.last() == this
+
+    override fun isReceiverParam() =
+        enclosingElement is JavacMethodElement &&
+        enclosingElement.isExtensionFunction() &&
+        enclosingElement.parameters.first() == this
+
+    override fun isKotlinPropertyParam() =
+        enclosingElement is JavacMethodElement &&
+        enclosingElement.isKotlinPropertyMethod()
 
     override val kotlinMetadata by lazy { kotlinMetadataFactory() }
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
index dade470..9a24b90 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
@@ -38,9 +38,7 @@
     private val logger = DelegateLogger(symbolProcessorEnvironment.logger)
 
     private val xEnv = KspProcessingEnv(
-        options = symbolProcessorEnvironment.options,
-        codeGenerator = symbolProcessorEnvironment.codeGenerator,
-        logger = logger,
+        delegate = symbolProcessorEnvironment,
         config = config
     )
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index 8a6ed9a..fe11246 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -36,6 +36,11 @@
 ) : KspElement(env, parameter),
     XExecutableParameterElement,
     XAnnotated by KspAnnotated.create(env, parameter, NO_USE_SITE_OR_METHOD_PARAMETER) {
+    override fun isContinuationParam() = false
+
+    override fun isReceiverParam() = false
+
+    override fun isKotlinPropertyParam() = false
 
     override val name: String
         get() = parameter.name?.asString() ?: "_no_param_name"
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 75cd2c3..232bacd 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
@@ -28,9 +28,8 @@
 import androidx.room.compiler.processing.javac.XTypeElementStore
 import com.google.devtools.ksp.KspExperimental
 import com.google.devtools.ksp.getClassDeclarationByName
-import com.google.devtools.ksp.processing.CodeGenerator
-import com.google.devtools.ksp.processing.KSPLogger
 import com.google.devtools.ksp.processing.Resolver
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
 import com.google.devtools.ksp.symbol.ClassKind
 import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSFile
@@ -43,12 +42,13 @@
 import com.google.devtools.ksp.symbol.Variance
 
 internal class KspProcessingEnv(
-    override val options: Map<String, String>,
-    codeGenerator: CodeGenerator,
-    logger: KSPLogger,
+    val delegate: SymbolProcessorEnvironment,
     override val config: XProcessingEnvConfig,
 ) : XProcessingEnv {
     override val backend: XProcessingEnv.Backend = XProcessingEnv.Backend.KSP
+    override val options = delegate.options
+    private val logger = delegate.logger
+    private val codeGenerator = delegate.codeGenerator
 
     // No API to get this but Kotlin's default is 8, so go with it for now.
     // TODO: https://github.com/google/ksp/issues/810
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index a9d786c..8fb91f6 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -248,7 +248,9 @@
     }
 
     override fun isValueClass(): Boolean {
-        return Modifier.INLINE in declaration.modifiers
+        // The inline modifier for inline classes is deprecated in Kotlin but we still include it
+        // in this check.
+        return Modifier.VALUE in declaration.modifiers || Modifier.INLINE in declaration.modifiers
     }
 
     override fun isFunctionalInterface(): Boolean {
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
index 9fe597a..447fbf3 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
@@ -39,7 +39,7 @@
  * this is what KAPT generates and Room needs it as long as it generates java code.
  */
 internal class KspSyntheticContinuationParameterElement(
-    private val env: KspProcessingEnv,
+    val env: KspProcessingEnv,
     override val enclosingElement: KspMethodElement
 ) : XExecutableParameterElement,
     XEquality,
@@ -48,6 +48,11 @@
         delegate = null, // does not matter, this is synthetic and has no annotations.
         filter = NO_USE_SITE
     ) {
+    override fun isContinuationParam() = true
+
+    override fun isReceiverParam() = false
+
+    override fun isKotlinPropertyParam() = false
 
     override val name: String by lazy {
         // KAPT uses `continuation` but it doesn't check for conflicts, we do.
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index d6bf00e..ec5190d 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -232,6 +232,11 @@
                 delegate = enclosingElement.field.declaration.setter?.parameter,
                 filter = NO_USE_SITE_OR_SET_PARAM
             ) {
+            override fun isContinuationParam() = false
+
+            override fun isReceiverParam() = false
+
+            override fun isKotlinPropertyParam() = true
 
             private val jvmTypeResolutionScope = KspJvmTypeResolutionScope.PropertySetterParameter(
                 declaration = enclosingElement
@@ -323,4 +328,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
index 1c7bf1e..acef3af 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticReceiverParameterElement.kt
@@ -42,6 +42,12 @@
         filter = KspAnnotated.UseSiteFilter.NO_USE_SITE
     ) {
 
+    override fun isContinuationParam() = false
+
+    override fun isReceiverParam() = true
+
+    override fun isKotlinPropertyParam() = false
+
     override val name: String by lazy {
         // KAPT uses `$this$<functionName>`
         "$" + "this" + "$" + enclosingElement.name
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 73c87b1..91ff9e3 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
@@ -445,6 +445,7 @@
                     assertThat(method.parameters.first().type.asTypeName()).isEqualTo(
                         String::class.asClassName()
                     )
+                    assertThat(method.parameters.first().isKotlinPropertyParam()).isTrue()
                     assertThat(method.isPublic()).isTrue()
                     assertThat(method.parameters.first().type.nullability).isEqualTo(
                         XNullability.NONNULL
@@ -986,6 +987,7 @@
                 element.getDeclaredMethodByJvmName("ext1").let { method ->
                     assertThat(method.isExtensionFunction()).isTrue()
                     assertThat(method.parameters.size).isEqualTo(1)
+                    assertThat(method.parameters[0].isReceiverParam()).isTrue()
                     assertThat(method.parameters[0].name).isEqualTo("\$this\$ext1")
                     assertThat(method.parameters[0].type.asTypeName())
                         .isEqualTo(String::class.asClassName())
@@ -1028,6 +1030,7 @@
                     assertThat(method.parameters.size).isEqualTo(2)
                     assertThat(method.parameters[0].type.asTypeName())
                         .isEqualTo(String::class.asClassName())
+                    assertThat(method.parameters[1].isContinuationParam()).isTrue()
                     assertThat(method.parameters[1].type.typeName).isEqualTo(
                         ParameterizedTypeName.get(
                             ClassName.get("kotlin.coroutines", "Continuation"),
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index 330d1b4..24449d4 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -408,11 +408,7 @@
             assertThat(getModifiers("DataClass"))
                 .containsExactly("public", "final", "class", "data")
             assertThat(getModifiers("InlineClass")).apply {
-                if (isPreCompiled && invocation.isKsp) {
-                    containsExactly("public", "final", "class")
-                } else {
-                    containsExactly("public", "final", "class", "value")
-                }
+                containsExactly("public", "final", "class", "value")
             }
             assertThat(getModifiers("FunInterface"))
                 .containsExactly("public", "abstract", "interface", "fun")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
index 2676100..472f46e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
@@ -23,6 +23,7 @@
 import androidx.room.compiler.processing.XTypeElement
 import androidx.room.log.RLog
 import androidx.room.processor.Context
+import androidx.room.processor.Context.BooleanProcessorOptions.GENERATE_KOTLIN
 import androidx.room.processor.DatabaseProcessor
 import androidx.room.processor.ProcessorErrors
 import androidx.room.util.SchemaFileResolver
@@ -45,9 +46,10 @@
         elementsByAnnotation: Map<String, Set<XElement>>,
         isLastRound: Boolean
     ): Set<XTypeElement> {
-        check(env.config == ENV_CONFIG) {
-            "Room Processor expected $ENV_CONFIG but was invoked with a different configuration:" +
-                "${env.config}"
+        check(env.config == getEnvConfig(env.options)) {
+            "Room Processor expected ${getEnvConfig(env.options)} " +
+                "but was invoked with a different " +
+                "configuration: ${env.config}"
         }
         val context = Context(env)
 
@@ -175,8 +177,9 @@
     }
 
     companion object {
-        internal val ENV_CONFIG = XProcessingEnvConfig.DEFAULT.copy(
-            excludeMethodsWithInvalidJvmSourceNames = true
-        )
+        internal fun getEnvConfig(options: Map<String, String>) =
+            XProcessingEnvConfig.DEFAULT.copy(
+                excludeMethodsWithInvalidJvmSourceNames = !GENERATE_KOTLIN.getValue(options)
+            )
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/RoomKspProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/RoomKspProcessor.kt
index 0a37134..e2f9e3f 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/RoomKspProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/RoomKspProcessor.kt
@@ -16,7 +16,6 @@
 
 package androidx.room
 
-import androidx.room.DatabaseProcessingStep.Companion.ENV_CONFIG
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.XRoundEnv
 import androidx.room.compiler.processing.ksp.KspBasicAnnotationProcessor
@@ -33,7 +32,10 @@
  */
 class RoomKspProcessor(
     environment: SymbolProcessorEnvironment
-) : KspBasicAnnotationProcessor(environment, ENV_CONFIG) {
+) : KspBasicAnnotationProcessor(
+    symbolProcessorEnvironment = environment,
+    config = DatabaseProcessingStep.getEnvConfig(environment.options)
+) {
     init {
         // print a warning if null aware converter is disabled because we'll remove that ability
         // soon.
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/RoomProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/RoomProcessor.kt
index 5c7daee..00d1e5a 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/RoomProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/RoomProcessor.kt
@@ -16,7 +16,6 @@
 
 package androidx.room
 
-import androidx.room.DatabaseProcessingStep.Companion.ENV_CONFIG
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.XRoundEnv
 import androidx.room.compiler.processing.javac.JavacBasicAnnotationProcessor
@@ -36,9 +35,11 @@
 /**
  * The annotation processor for Room.
  */
-class RoomProcessor : JavacBasicAnnotationProcessor({
-    ENV_CONFIG
-}) {
+class RoomProcessor : JavacBasicAnnotationProcessor(
+    configureEnv = { options ->
+        DatabaseProcessingStep.getEnvConfig(options)
+    }
+) {
 
     /** Helper variable to avoid reporting the warning twice. */
     private var jdkVersionHasBugReported = false
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
index 487bafc..5c36768 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xelement_ext.kt
@@ -18,6 +18,7 @@
 
 import kotlin.contracts.contract
 import androidx.room.compiler.processing.XElement
+import androidx.room.compiler.processing.XFieldElement
 import androidx.room.compiler.processing.XTypeElement
 
 fun XElement.isEntityElement(): Boolean {
@@ -27,6 +28,13 @@
     return this.hasAnnotation(androidx.room.Entity::class)
 }
 
+fun XTypeElement.getValueClassUnderlyingProperty(): XFieldElement {
+    check(this.isValueClass()) {
+        "Can't get value class property, type element '$this' is not a value class"
+    }
+    return this.getDeclaredFields().single()
+}
+
 /**
  * Suffix of the Kotlin synthetic class created interface method implementations.
  */
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
index 3221bd5..07ee499 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
@@ -274,8 +274,16 @@
             return getInputValue(processingEnv) ?: defaultValue
         }
 
+        fun getValue(options: Map<String, String>): Boolean {
+            return getInputValue(options) ?: defaultValue
+        }
+
         fun getInputValue(processingEnv: XProcessingEnv): Boolean? {
-            return processingEnv.options[argName]?.takeIf {
+            return getInputValue(processingEnv.options)
+        }
+
+        private fun getInputValue(options: Map<String, String>): Boolean? {
+            return options[argName]?.takeIf {
                 it.isNotBlank()
             }?.toBoolean()
         }
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
index 1645d65..5c72f35 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/FieldProcessor.kt
@@ -17,6 +17,7 @@
 package androidx.room.processor
 
 import androidx.room.ColumnInfo
+import androidx.room.compiler.codegen.CodeLanguage
 import androidx.room.compiler.processing.XFieldElement
 import androidx.room.compiler.processing.XType
 import androidx.room.parser.Collate
@@ -82,6 +83,13 @@
             nonNull = nonNull
         )
 
+        // TODO(b/273592453): Figure out a way to detect value classes in KAPT and guard against it.
+        if (member.typeElement?.isValueClass() == true &&
+            context.codeLanguage != CodeLanguage.KOTLIN
+        ) {
+            onBindingError(field, ProcessorErrors.VALUE_CLASS_ONLY_SUPPORTED_IN_KSP)
+        }
+
         when (bindingScope) {
             BindingScope.TWO_WAY -> {
                 field.statementBinder = adapter
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
index 414e98f..0367eeb 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
@@ -255,6 +255,9 @@
     val CANNOT_FIND_COLUMN_TYPE_ADAPTER = "Cannot figure out how to save this field into" +
         " database. You can consider adding a type converter for it."
 
+    val VALUE_CLASS_ONLY_SUPPORTED_IN_KSP = "Kotlin value classes are only supported " +
+        "in Room using KSP and generating Kotlin (room.generateKotlin=true)."
+
     val CANNOT_FIND_STMT_BINDER = "Cannot figure out how to bind this field into a statement."
 
     val CANNOT_FIND_CURSOR_READER = "Cannot figure out how to read this field from a cursor."
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 329e023..030d092 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -28,6 +28,7 @@
 import androidx.room.ext.CollectionTypeNames.LONG_SPARSE_ARRAY
 import androidx.room.ext.CommonTypeNames
 import androidx.room.ext.GuavaTypeNames
+import androidx.room.ext.getValueClassUnderlyingProperty
 import androidx.room.ext.isByteBuffer
 import androidx.room.ext.isEntityElement
 import androidx.room.ext.isNotByte
@@ -115,6 +116,7 @@
 import androidx.room.solver.types.StringColumnTypeAdapter
 import androidx.room.solver.types.TypeConverter
 import androidx.room.solver.types.UuidColumnTypeAdapter
+import androidx.room.solver.types.ValueClassConverterWrapper
 import androidx.room.vo.BuiltInConverterFlags
 import androidx.room.vo.MapInfo
 import androidx.room.vo.ShortcutQueryParameter
@@ -278,7 +280,7 @@
         if (adapterByTypeConverter != null) {
             return adapterByTypeConverter
         }
-        val defaultAdapter = createDefaultTypeAdapter(input)
+        val defaultAdapter = createDefaultTypeAdapter(input, affinity)
         if (defaultAdapter != null) {
             return defaultAdapter
         }
@@ -316,7 +318,7 @@
             return typeConverterAdapter
         }
 
-        val defaultAdapter = createDefaultTypeAdapter(output)
+        val defaultAdapter = createDefaultTypeAdapter(output, affinity)
         if (defaultAdapter != null) {
             return defaultAdapter
         }
@@ -361,7 +363,7 @@
         }
 
         if (!skipDefaultConverter) {
-            val defaultAdapter = createDefaultTypeAdapter(out)
+            val defaultAdapter = createDefaultTypeAdapter(out, affinity)
             if (defaultAdapter != null) {
                 return defaultAdapter
             }
@@ -369,8 +371,27 @@
         return null
     }
 
-    private fun createDefaultTypeAdapter(type: XType): ColumnTypeAdapter? {
+    private fun createDefaultTypeAdapter(
+        type: XType,
+        affinity: SQLTypeAffinity?
+    ): ColumnTypeAdapter? {
         val typeElement = type.typeElement
+        if (typeElement?.isValueClass() == true) {
+            // Extract the type value of the Value class element
+            val underlyingProperty = typeElement.getValueClassUnderlyingProperty()
+            val underlyingTypeColumnAdapter = findColumnTypeAdapter(
+                out = underlyingProperty.asMemberOf(type),
+                affinity = affinity,
+                skipDefaultConverter = false
+            ) ?: return null
+
+            return ValueClassConverterWrapper(
+                valueTypeColumnAdapter = underlyingTypeColumnAdapter,
+                affinity = underlyingTypeColumnAdapter.typeAffinity,
+                out = type,
+                valuePropertyName = underlyingProperty.name
+            )
+        }
         return when {
             builtInConverterFlags.enums.isEnabled() &&
                 typeElement?.isEnum() == true -> EnumColumnTypeAdapter(typeElement, type)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/types/ValueClassConverterWrapper.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/types/ValueClassConverterWrapper.kt
new file mode 100644
index 0000000..57a2247
--- /dev/null
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/types/ValueClassConverterWrapper.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.solver.types
+
+import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.processing.XNullability
+import androidx.room.compiler.processing.XType
+import androidx.room.parser.SQLTypeAffinity
+import androidx.room.solver.CodeGenScope
+
+/**
+ * ColumnTypeAdapter for Kotlin value classes that simply wraps and forwards calls to a found
+ * adapter for the underlying type.
+ */
+class ValueClassConverterWrapper(
+    val valueTypeColumnAdapter: ColumnTypeAdapter,
+    val affinity: SQLTypeAffinity,
+    out: XType,
+    val valuePropertyName: String
+) : ColumnTypeAdapter(out, affinity) {
+    override fun readFromCursor(
+        outVarName: String,
+        cursorVarName: String,
+        indexVarName: String,
+        scope: CodeGenScope
+    ) {
+        scope.builder.apply {
+            fun XCodeBlock.Builder.addTypeToValueClassStatement() {
+                val propertyValueVarName = scope.getTmpVar("_$valuePropertyName")
+                addLocalVariable(propertyValueVarName, valueTypeColumnAdapter.outTypeName)
+                valueTypeColumnAdapter.readFromCursor(
+                    propertyValueVarName,
+                    cursorVarName,
+                    indexVarName,
+                    scope
+                )
+                addStatement(
+                    format = "%L = %L",
+                    outVarName,
+                    XCodeBlock.ofNewInstance(
+                        language,
+                        out.asTypeName(),
+                        "%N",
+                        propertyValueVarName
+                    )
+                )
+            }
+            if (out.nullability == XNullability.NONNULL) {
+                addTypeToValueClassStatement()
+            } else {
+                beginControlFlow("if (%L.isNull(%L))", cursorVarName, indexVarName)
+                    .addStatement("%L = null", outVarName)
+                nextControlFlow("else")
+                    .addTypeToValueClassStatement()
+                endControlFlow()
+            }
+        }
+    }
+
+    override fun bindToStmt(
+        stmtName: String,
+        indexVarName: String,
+        valueVarName: String,
+        scope: CodeGenScope
+    ) {
+        scope.builder.apply {
+            val propertyName = scope.getTmpVar("_$valuePropertyName")
+            addLocalVariable(
+                name = propertyName,
+                typeName = valueTypeColumnAdapter.outTypeName,
+                assignExpr = XCodeBlock.of(
+                    scope.language,
+                    "%L.%L",
+                    valueVarName,
+                    valuePropertyName
+                )
+            )
+
+            if (out.nullability == XNullability.NONNULL) {
+                valueTypeColumnAdapter.bindToStmt(
+                    stmtName,
+                    indexVarName,
+                    propertyName,
+                    scope
+                )
+            } else {
+                beginControlFlow(
+                    "if (%L == null)",
+                    propertyName
+                ).addStatement("%L.bindNull(%L)", stmtName, indexVarName)
+                nextControlFlow("else")
+                valueTypeColumnAdapter.bindToStmt(
+                    stmtName,
+                    indexVarName,
+                    propertyName,
+                    scope
+                )
+                endControlFlow()
+            }
+        }
+    }
+}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/RoomTestEnvConfigProvider.kt b/room/room-compiler/src/test/kotlin/androidx/room/RoomTestEnvConfigProvider.kt
index addefbc..761159f 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/RoomTestEnvConfigProvider.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/RoomTestEnvConfigProvider.kt
@@ -21,6 +21,6 @@
 
 class RoomTestEnvConfigProvider : XProcessingEnvironmentTestConfigProvider {
     override fun configure(options: Map<String, String>): XProcessingEnvConfig {
-        return DatabaseProcessingStep.ENV_CONFIG
+        return DatabaseProcessingStep.getEnvConfig(options)
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 558e6c0..f5c3ac3 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -22,6 +22,7 @@
 import androidx.room.Dao
 import androidx.room.compiler.codegen.XCodeBlock
 import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.XTypeName.Companion.PRIMITIVE_INT
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.XRawType
 import androidx.room.compiler.processing.isTypeElement
@@ -62,18 +63,20 @@
 import androidx.room.solver.shortcut.binderprovider.RxCallableUpsertMethodBinderProvider
 import androidx.room.solver.types.BoxedPrimitiveColumnTypeAdapter
 import androidx.room.solver.types.ByteBufferColumnTypeAdapter
+import androidx.room.solver.types.ColumnTypeAdapter
 import androidx.room.solver.types.CompositeAdapter
 import androidx.room.solver.types.CustomTypeConverterWrapper
 import androidx.room.solver.types.EnumColumnTypeAdapter
 import androidx.room.solver.types.PrimitiveColumnTypeAdapter
 import androidx.room.solver.types.SingleStatementTypeConverter
+import androidx.room.solver.types.StringColumnTypeAdapter
 import androidx.room.solver.types.TypeConverter
 import androidx.room.solver.types.UuidColumnTypeAdapter
+import androidx.room.solver.types.ValueClassConverterWrapper
 import androidx.room.testing.context
 import androidx.room.vo.BuiltInConverterFlags
 import androidx.room.vo.ReadQueryMethod
 import com.google.common.truth.Truth.assertThat
-import java.util.UUID
 import org.hamcrest.CoreMatchers.instanceOf
 import org.hamcrest.CoreMatchers.`is`
 import org.hamcrest.CoreMatchers.notNullValue
@@ -221,6 +224,99 @@
     }
 
     @Test
+    fun testKotlinLangValueClassCompilesWithoutError() {
+        val source = Source.kotlin(
+            "Foo.kt",
+            """
+            import androidx.room.*
+            @JvmInline
+            value class IntValueClass(val data: Int)
+            @JvmInline
+            value class StringValueClass(val data: String)
+            class EntityWithValueClass {
+                val intData = IntValueClass(123)
+                val stringData = StringValueClass("bla")
+            }
+            """.trimIndent()
+        )
+        var results: Map<String, String?> = mutableMapOf()
+
+        runProcessorTest(
+            sources = listOf(source)
+        ) { invocation ->
+            val typeAdapterStore = TypeAdapterStore.create(
+                context = invocation.context,
+                builtInConverterFlags = BuiltInConverterFlags.DEFAULT
+            )
+            val subject = invocation.processingEnv.requireTypeElement("EntityWithValueClass")
+            results = subject.getAllFieldsIncludingPrivateSupers().associate { field ->
+                val columnAdapter = typeAdapterStore.findColumnTypeAdapter(
+                    out = field.type,
+                    affinity = null,
+                    false
+                )
+
+                val typeElementColumnAdapter: ColumnTypeAdapter? =
+                    if (columnAdapter is ValueClassConverterWrapper) {
+                        columnAdapter.valueTypeColumnAdapter
+                    } else {
+                        columnAdapter
+                    }
+
+                when (typeElementColumnAdapter) {
+                    is PrimitiveColumnTypeAdapter -> {
+                        field.name to "primitive"
+                    }
+
+                    is StringColumnTypeAdapter -> {
+                        field.name to "string"
+                    }
+
+                    else -> {
+                        field.name to null
+                    }
+                }
+            }
+        }
+        assertThat(results).containsExactlyEntriesIn(
+            mapOf(
+                "intData" to "primitive",
+                "stringData" to "string"
+            )
+        )
+    }
+
+    @Test
+    fun testValueClassWithDifferentTypeVal() {
+        val source = Source.kotlin(
+            "Foo.kt",
+            """
+            import androidx.room.*
+            @JvmInline
+            value class Foo(val value : Int) {
+                val double
+                    get() = value * 2
+            }
+            """.trimIndent()
+        )
+
+        runProcessorTest(
+            sources = listOf(source)
+        ) { invocation ->
+            TypeAdapterStore.create(
+                context = invocation.context,
+                builtInConverterFlags = BuiltInConverterFlags.DEFAULT
+            )
+            val typeElement = invocation
+                .processingEnv
+                .requireTypeElement("Foo")
+            assertThat(typeElement.getDeclaredFields()).hasSize(1)
+            assertThat(typeElement.getDeclaredFields().single().type.asTypeName())
+                .isEqualTo(PRIMITIVE_INT)
+        }
+    }
+
+    @Test
     fun testJavaLangByteBufferCompilesWithoutError() {
         runProcessorTest { invocation ->
             val store = TypeAdapterStore.create(
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
index 15f4065..7cf8c7f 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
@@ -2145,4 +2145,46 @@
             expectedFilePath = getTestGoldenPath(testName)
         )
     }
+
+    @Test
+    fun valueClassConverter() {
+        val testName = object {}.javaClass.enclosingMethod!!.name
+        val src = Source.kotlin(
+            "MyDao.kt",
+            """
+            import androidx.room.*
+            import java.util.UUID
+
+            @Dao
+            interface MyDao {
+              @Query("SELECT * FROM MyEntity")
+              fun getEntity(): MyEntity
+
+              @Insert
+              fun addEntity(item: MyEntity)
+            }
+
+            @JvmInline
+            value class LongValueClass(val data: Long)
+
+            @JvmInline
+            value class UUIDValueClass(val data: UUID)
+
+            @JvmInline
+            value class GenericValueClass<T>(val password: T)
+
+            @Entity
+            data class MyEntity (
+                @PrimaryKey
+                val pk: LongValueClass,
+                val uuidData: UUIDValueClass,
+                val genericData: GenericValueClass<String>
+            )
+            """.trimIndent()
+        )
+        runTest(
+            sources = listOf(src, databaseSrc),
+            expectedFilePath = getTestGoldenPath(testName)
+        )
+    }
 }
\ No newline at end of file
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/valueClassConverter.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/valueClassConverter.kt
new file mode 100644
index 0000000..0d3b34d
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/valueClassConverter.kt
@@ -0,0 +1,96 @@
+import android.database.Cursor
+import androidx.room.EntityInsertionAdapter
+import androidx.room.RoomDatabase
+import androidx.room.RoomSQLiteQuery
+import androidx.room.RoomSQLiteQuery.Companion.acquire
+import androidx.room.util.convertByteToUUID
+import androidx.room.util.convertUUIDToByte
+import androidx.room.util.getColumnIndexOrThrow
+import androidx.room.util.query
+import androidx.sqlite.db.SupportSQLiteStatement
+import java.lang.Class
+import java.util.UUID
+import javax.`annotation`.processing.Generated
+import kotlin.Int
+import kotlin.Long
+import kotlin.String
+import kotlin.Suppress
+import kotlin.Unit
+import kotlin.collections.List
+import kotlin.jvm.JvmStatic
+
+@Generated(value = ["androidx.room.RoomProcessor"])
+@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION"])
+public class MyDao_Impl(
+    __db: RoomDatabase,
+) : MyDao {
+    private val __db: RoomDatabase
+
+    private val __insertionAdapterOfMyEntity: EntityInsertionAdapter<MyEntity>
+    init {
+        this.__db = __db
+        this.__insertionAdapterOfMyEntity = object : EntityInsertionAdapter<MyEntity>(__db) {
+            public override fun createQuery(): String =
+                "INSERT OR ABORT INTO `MyEntity` (`pk`,`uuidData`,`genericData`) VALUES (?,?,?)"
+
+            public override fun bind(statement: SupportSQLiteStatement, entity: MyEntity): Unit {
+                val _data: Long = entity.pk.data
+                statement.bindLong(1, _data)
+                val _data_1: UUID = entity.uuidData.data
+                statement.bindBlob(2, convertUUIDToByte(_data_1))
+                val _password: String = entity.genericData.password
+                statement.bindString(3, _password)
+            }
+        }
+    }
+
+    public override fun addEntity(item: MyEntity): Unit {
+        __db.assertNotSuspendingTransaction()
+        __db.beginTransaction()
+        try {
+            __insertionAdapterOfMyEntity.insert(item)
+            __db.setTransactionSuccessful()
+        } finally {
+            __db.endTransaction()
+        }
+    }
+
+    public override fun getEntity(): MyEntity {
+        val _sql: String = "SELECT * FROM MyEntity"
+        val _statement: RoomSQLiteQuery = acquire(_sql, 0)
+        __db.assertNotSuspendingTransaction()
+        val _cursor: Cursor = query(__db, _statement, false, null)
+        try {
+            val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
+            val _cursorIndexOfUuidData: Int = getColumnIndexOrThrow(_cursor, "uuidData")
+            val _cursorIndexOfGenericData: Int = getColumnIndexOrThrow(_cursor, "genericData")
+            val _result: MyEntity
+            if (_cursor.moveToFirst()) {
+                val _tmpPk: LongValueClass
+                val _data: Long
+                _data = _cursor.getLong(_cursorIndexOfPk)
+                _tmpPk = LongValueClass(_data)
+                val _tmpUuidData: UUIDValueClass
+                val _data_1: UUID
+                _data_1 = convertByteToUUID(_cursor.getBlob(_cursorIndexOfUuidData))
+                _tmpUuidData = UUIDValueClass(_data_1)
+                val _tmpGenericData: GenericValueClass<String>
+                val _password: String
+                _password = _cursor.getString(_cursorIndexOfGenericData)
+                _tmpGenericData = GenericValueClass<String>(_password)
+                _result = MyEntity(_tmpPk,_tmpUuidData,_tmpGenericData)
+            } else {
+                error("Cursor was empty, but expected a single item.")
+            }
+            return _result
+        } finally {
+            _cursor.close()
+            _statement.release()
+        }
+    }
+
+    public companion object {
+        @JvmStatic
+        public fun getRequiredConverters(): List<Class<*>> = emptyList()
+    }
+}
\ No newline at end of file
diff --git a/room/settings.gradle b/room/settings.gradle
index cde30ee..b253b61 100644
--- a/room/settings.gradle
+++ b/room/settings.gradle
@@ -33,6 +33,7 @@
         if (name == ":annotation:annotation-experimental-lint") return true
         if (name == ":annotation:annotation-experimental-lint-integration-tests") return true
         if (name == ":internal-testutils-truth") return true
+        if (name == ":internal-testutils-kmp") return true
         return false
     })
 }
diff --git a/settings.gradle b/settings.gradle
index b2f892c..58bfa61 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -510,7 +510,6 @@
 includeProject(":compose:foundation:foundation-lint", [BuildType.COMPOSE])
 includeProject(":compose:foundation:foundation:integration-tests:foundation-demos", [BuildType.COMPOSE])
 includeProject(":compose:foundation:foundation:foundation-samples", "compose/foundation/foundation/samples", [BuildType.COMPOSE])
-includeProject(":compose:foundation:foundation-do-not-ship-newtext", "compose/foundation/foundation-newtext", [BuildType.COMPOSE])
 includeProject(":compose:integration-tests", [BuildType.COMPOSE])
 includeProject(":compose:integration-tests:demos", [BuildType.COMPOSE])
 includeProject(":compose:integration-tests:demos:common", [BuildType.COMPOSE])
@@ -1062,7 +1061,7 @@
 includeProject(":internal-testutils-fonts", "testutils/testutils-fonts", [BuildType.MAIN, BuildType.GLANCE, BuildType.MEDIA, BuildType.FLAN, BuildType.COMPOSE, BuildType.WEAR])
 includeProject(":internal-testutils-truth", "testutils/testutils-truth")
 includeProject(":internal-testutils-ktx", "testutils/testutils-ktx")
-includeProject(":internal-testutils-kmp", "testutils/testutils-kmp", [BuildType.MAIN, BuildType.KMP])
+includeProject(":internal-testutils-kmp", "testutils/testutils-kmp", [BuildType.MAIN, BuildType.KMP, BuildType.COMPOSE])
 includeProject(":internal-testutils-macrobenchmark", "testutils/testutils-macrobenchmark", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":internal-testutils-navigation", "testutils/testutils-navigation", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN])
 includeProject(":internal-testutils-paging", "testutils/testutils-paging", [BuildType.MAIN, BuildType.COMPOSE])
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
index 7b87886..b83c9be 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
@@ -48,7 +48,6 @@
 public class UiObject2Test extends BaseTest {
     private static final int TIMEOUT_MS = 10_000;
     private static final int SPEED_MS = 100;
-    private static final int SCROLL_MARGIN = 50;
 
     @Test
     public void testClear() {
@@ -562,7 +561,6 @@
         launchTestActivity(SwipeTestActivity.class);
 
         UiObject2 swipeRegion = mDevice.findObject(By.res(TEST_APP, "swipe_region"));
-        swipeRegion.setGestureMargin(SCROLL_MARGIN);
 
         swipeRegion.swipe(Direction.LEFT, 0.9f);
         assertTrue(swipeRegion.wait(Until.textEquals("swipe_left"), TIMEOUT_MS));
@@ -613,11 +611,10 @@
 
         // Scroll down to bottom where is two-screen-height distant from the top.
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
 
         Rect bounds = scrollView.getVisibleBounds();
         float percent =
-                (float) (mDevice.getDisplayHeight() * 2 / (bounds.height() - 2 * SCROLL_MARGIN));
+                (float) (mDevice.getDisplayHeight() * 2 / (bounds.height() - 100));
         scrollView.scroll(Direction.DOWN, percent);
 
         assertTrue(mDevice.hasObject(By.res(TEST_APP, "bottom_text")));
@@ -630,7 +627,6 @@
 
         // Scroll until end (scroll method returns false).
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
         while (scrollView.scroll(Direction.DOWN, 1.0f)) {
             // Continue until bottom.
         }
@@ -645,7 +641,6 @@
 
         // Scroll until end
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
         assertNotNull(scrollView.scrollUntil(Direction.DOWN,
                 Until.findObject(By.res(TEST_APP, "bottom_text"))));
         assertTrue(mDevice.hasObject(By.res(TEST_APP, "bottom_text")));
@@ -658,7 +653,6 @@
         assertFalse(mDevice.hasObject(By.res(TEST_APP, "bottom_text")));
 
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
         // fail to find text that doesn't exist.
         assertNull(scrollView.scrollUntil(Direction.DOWN,
                 Until.findObject(By.res(TEST_APP, "nonexistent_text"))));
@@ -673,7 +667,6 @@
         assertFalse(mDevice.hasObject(By.res(TEST_APP, "bottom_text")));
 
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
         // Scroll for the event condition that occurs early before scrolling to the end.
         Integer result = scrollView.scrollUntil(Direction.DOWN,
                 new EventCondition<Integer>() {
@@ -704,7 +697,6 @@
         assertFalse(mDevice.hasObject(By.res(TEST_APP, "bottom_text")));
 
         UiObject2 scrollView = mDevice.findObject(By.res(TEST_APP, "scroll_view"));
-        scrollView.setGestureMargin(SCROLL_MARGIN); // Avoid touching too close to the edges.
         // Scroll for the event condition that doesn't occur.
         Integer result = scrollView.scrollUntil(Direction.DOWN,
                 new EventCondition<Integer>() {
@@ -733,9 +725,7 @@
     public void testFling_direction() {
         launchTestActivity(FlingTestActivity.class);
 
-        // Avoid touching too close to the edges.
         UiObject2 flingRegion = mDevice.findObject(By.res(TEST_APP, "fling_region"));
-        flingRegion.setGestureMargin(SCROLL_MARGIN);
 
         // No fling yet.
         assertEquals("no_fling", flingRegion.getText());
@@ -750,9 +740,7 @@
     public void testFling_directionAndSpeed() {
         launchTestActivity(FlingTestActivity.class);
 
-        // Avoid touching too close to the edges.
         UiObject2 flingRegion = mDevice.findObject(By.res(TEST_APP, "fling_region"));
-        flingRegion.setGestureMargin(SCROLL_MARGIN);
 
         // No fling yet.
         assertEquals("no_fling", flingRegion.getText());
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObjectTest.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObjectTest.java
index 3a5945f..36aaeb6 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObjectTest.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObjectTest.java
@@ -501,15 +501,15 @@
 
     @Test
     public void testIsLongClickable() throws Exception {
-        launchTestActivity(LongClickTestActivity.class);
+        launchTestActivity(IsLongClickableTestActivity.class);
 
-        UiObject button = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id/button"));
-        UiObject expectedButton = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
-                + "/button").text("I've been long clicked!"));
+        UiObject longClickableButton = mDevice.findObject(
+                new UiSelector().resourceId(TEST_APP + ":id/long_clickable_button"));
+        UiObject nonLongClickableButton = mDevice.findObject(
+                new UiSelector().resourceId(TEST_APP + ":id/non_long_clickable_button"));
 
-        assertEquals("Long Click Me!", button.getText());
-        button.longClick();
-        assertTrue(expectedButton.waitForExists(TIMEOUT_MS));
+        assertTrue(longClickableButton.isLongClickable());
+        assertFalse(nonLongClickableButton.isLongClickable());
     }
 
     @Test
diff --git a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/LongClickTestActivity.java b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/LongClickTestActivity.java
index b4b9e84..f0137a3 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/LongClickTestActivity.java
+++ b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/LongClickTestActivity.java
@@ -18,10 +18,8 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
 import android.widget.Button;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 public class LongClickTestActivity extends Activity {
@@ -29,14 +27,12 @@
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
         setContentView(R.layout.long_click_test_activity);
 
-        Button button = (Button) findViewById(R.id.button);
-        button.setOnClickListener(this::onButtonLongClick);
-    }
-
-    public void onButtonLongClick(@NonNull View v) {
-        ((Button) v).setText("I've been long clicked!");
+        Button button = findViewById(R.id.button);
+        button.setOnLongClickListener(v -> {
+            button.setText("I've been long clicked!");
+            return true;
+        });
     }
 }
diff --git a/test/uiautomator/uiautomator/api/current.txt b/test/uiautomator/uiautomator/api/current.txt
index 6c6f650..2948288 100644
--- a/test/uiautomator/uiautomator/api/current.txt
+++ b/test/uiautomator/uiautomator/api/current.txt
@@ -313,6 +313,8 @@
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.Condition<? super androidx.test.uiautomator.UiObject2,U!>);
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.EventCondition<U!>);
     method public void setGestureMargin(int);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=0.5f) float);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
     method public void setGestureMargins(int, int, int, int);
     method public void setText(String?);
     method public void swipe(androidx.test.uiautomator.Direction, float);
diff --git a/test/uiautomator/uiautomator/api/public_plus_experimental_current.txt b/test/uiautomator/uiautomator/api/public_plus_experimental_current.txt
index 6c6f650..2948288 100644
--- a/test/uiautomator/uiautomator/api/public_plus_experimental_current.txt
+++ b/test/uiautomator/uiautomator/api/public_plus_experimental_current.txt
@@ -313,6 +313,8 @@
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.Condition<? super androidx.test.uiautomator.UiObject2,U!>);
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.EventCondition<U!>);
     method public void setGestureMargin(int);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=0.5f) float);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
     method public void setGestureMargins(int, int, int, int);
     method public void setText(String?);
     method public void swipe(androidx.test.uiautomator.Direction, float);
diff --git a/test/uiautomator/uiautomator/api/restricted_current.txt b/test/uiautomator/uiautomator/api/restricted_current.txt
index 6c6f650..2948288 100644
--- a/test/uiautomator/uiautomator/api/restricted_current.txt
+++ b/test/uiautomator/uiautomator/api/restricted_current.txt
@@ -313,6 +313,8 @@
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.Condition<? super androidx.test.uiautomator.UiObject2,U!>);
     method public <U> U! scrollUntil(androidx.test.uiautomator.Direction, androidx.test.uiautomator.EventCondition<U!>);
     method public void setGestureMargin(int);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=0.5f) float);
+    method public void setGestureMarginPercent(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
     method public void setGestureMargins(int, int, int, int);
     method public void setText(String?);
     method public void swipe(androidx.test.uiautomator.Direction, float);
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/Gestures.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/Gestures.java
index 4468216..c0436c5 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/Gestures.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/Gestures.java
@@ -23,10 +23,13 @@
 /** Factory methods for constructing {@link PointerGesture}s. */
 class Gestures {
 
+    // Duration of a long press (with multiplier to ensure detection).
+    private static final long LONG_PRESS_DURATION_MS =
+            (long) (ViewConfiguration.getLongPressTimeout() * 1.5f);
+
     // Constants used by pinch gestures
     private static final int INNER = 0;
     private static final int OUTER = 1;
-    private static final int INNER_MARGIN = 5;
 
     private Gestures() {
     }
@@ -68,7 +71,7 @@
      */
     public static PointerGesture longClick(Point point, int displayId) {
         // A long click is a click with a duration that exceeds a certain threshold.
-        return click(point, ViewConfiguration.getLongPressTimeout(), displayId);
+        return click(point, LONG_PRESS_DURATION_MS, displayId);
     }
 
     /**
@@ -185,12 +188,12 @@
     private static void calcPinchCoordinates(Rect area, float percent,
             Point[] bottomLeft, Point[] topRight) {
 
-        int offsetX = (int)((area.width() - 2 * INNER_MARGIN) / 2 * percent);
-        int offsetY = (int)((area.height() - 2 * INNER_MARGIN) / 2 * percent);
+        int offsetX = (int) (area.width() / 2 * percent);
+        int offsetY = (int) (area.height() / 2 * percent);
 
         // Outer set of pinch coordinates
-        bottomLeft[OUTER] = new Point(area.left + INNER_MARGIN, area.bottom - INNER_MARGIN);
-        topRight[OUTER]   = new Point(area.right - INNER_MARGIN, area.top + INNER_MARGIN);
+        bottomLeft[OUTER] = new Point(area.left, area.bottom);
+        topRight[OUTER]   = new Point(area.right, area.top);
 
         // Inner set of pinch coordinates
         bottomLeft[INNER] = new Point(bottomLeft[OUTER]);
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/InteractionController.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/InteractionController.java
index 379d940..490209f 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/InteractionController.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/InteractionController.java
@@ -50,6 +50,10 @@
 
     private static final String TAG = InteractionController.class.getSimpleName();
 
+    // Duration of a long press (with multiplier to ensure detection).
+    private static final long LONG_PRESS_DURATION_MS =
+            (long) (ViewConfiguration.getLongPressTimeout() * 1.5f);
+
     private final KeyCharacterMap mKeyCharacterMap =
             KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
 
@@ -187,7 +191,7 @@
      * @return true if events are received, else false if timeout.
      */
     public boolean clickAndSync(final int x, final int y, long timeout) {
-        return runAndWaitForEvents(clickRunnable(x, y), new WaitForAnyEventPredicate(
+        return runAndWaitForEvents(() -> clickNoSync(x, y), new WaitForAnyEventPredicate(
                 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED |
                 AccessibilityEvent.TYPE_VIEW_SELECTED), timeout) != null;
     }
@@ -202,46 +206,12 @@
      * @return true if both events occurred in the expected order
      */
     public boolean clickAndWaitForNewWindow(final int x, final int y, long timeout) {
-        return runAndWaitForEvents(clickRunnable(x, y), new WaitForAllEventPredicate(
+        return runAndWaitForEvents(() -> clickNoSync(x, y), new WaitForAllEventPredicate(
                 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED |
                 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED), timeout) != null;
     }
 
     /**
-     * Returns a Runnable for use in
-     * {@link #runAndWaitForEvents(Runnable, AccessibilityEventFilter, long) to perform a click.
-     *
-     * @param x coordinate
-     * @param y coordinate
-     * @return Runnable
-     */
-    private Runnable clickRunnable(final int x, final int y) {
-        return () -> {
-            if (touchDown(x, y)) {
-                SystemClock.sleep(REGULAR_CLICK_LENGTH);
-                touchUp(x, y);
-            }
-        };
-    }
-
-    /**
-     * Returns a Runnable for use in
-     * {@link #runAndWaitForEvents(Runnable, AccessibilityEventFilter, long) to perform a long tap.
-     *
-     * @param x coordinate
-     * @param y coordinate
-     * @return Runnable
-     */
-    private Runnable longTapRunnable(final int x, final int y) {
-        return () -> {
-            if (touchDown(x, y)) {
-                SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
-                touchUp(x, y);
-            }
-        };
-    }
-
-    /**
      * Touches down for a long press at the specified coordinates.
      *
      * @param x
@@ -250,7 +220,7 @@
      */
     public boolean longTapNoSync(int x, int y) {
         if (touchDown(x, y)) {
-            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            SystemClock.sleep(LONG_PRESS_DURATION_MS);
             return touchUp(x, y);
         }
         return false;
@@ -266,7 +236,7 @@
      * @return true if events are received, else false if timeout.
      */
     public boolean longTapAndSync(final int x, final int y, long timeout) {
-        return runAndWaitForEvents(longTapRunnable(x, y), new WaitForAnyEventPredicate(
+        return runAndWaitForEvents(() -> longTapNoSync(x, y), new WaitForAnyEventPredicate(
                 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED |
                 AccessibilityEvent.TYPE_VIEW_SELECTED), timeout) != null;
     }
@@ -360,7 +330,7 @@
         ret = touchDown(downX, downY);
         SystemClock.sleep(MOTION_EVENT_INJECTION_DELAY_MILLIS);
         if (drag)
-            SystemClock.sleep(ViewConfiguration.getLongPressTimeout());
+            SystemClock.sleep(LONG_PRESS_DURATION_MS);
         for(int i = 1; i < swipeSteps; i++) {
             ret &= touchMove(downX + (int)(xStep * i), downY + (int)(yStep * i));
             if (!ret) {
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
index 61c44be..90573b1 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
@@ -38,6 +38,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.DoNotInline;
+import androidx.annotation.FloatRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -59,6 +60,9 @@
 
     private static final String TAG = UiObject2.class.getSimpleName();
 
+    // default percentage of margins for gestures.
+    private static final float DEFAULT_GESTURE_MARGIN_PERCENT = 0.1f;
+
     // default percentage of each scroll in scrollUntil().
     private static final float DEFAULT_SCROLL_UNTIL_PERCENT = 0.8f;
 
@@ -78,12 +82,10 @@
     private final int mDisplayId;
     private final float mDisplayDensity;
     private AccessibilityNodeInfo mCachedNode;
-
-    // Margins used for gestures (avoids touching too close to the object's edge).
-    private int mMarginLeft = 5;
-    private int mMarginTop = 5;
-    private int mMarginRight = 5;
-    private int mMarginBottom = 5;
+    private Margins mMargins = new PercentMargins(DEFAULT_GESTURE_MARGIN_PERCENT,
+            DEFAULT_GESTURE_MARGIN_PERCENT,
+            DEFAULT_GESTURE_MARGIN_PERCENT,
+            DEFAULT_GESTURE_MARGIN_PERCENT);
 
     /** Package-private constructor. Used by {@link UiDevice#findObject(BySelector)}. */
     UiObject2(UiDevice device, BySelector selector, AccessibilityNodeInfo cachedNode) {
@@ -134,6 +136,36 @@
 
     // Settings
 
+    /**
+     * Sets the percentage of gestures' margins to avoid touching too close to the edges, e.g.
+     * when scrolling up, phone open quick settings instead if gesture is close to the top.
+     * The percentage is based on the object's visible size, e.g. to set 20% margins:
+     * <pre>mUiObject2.setGestureMarginPercent(0.2f);</pre>
+     *
+     * @Param percent Float between [0, 0.5] for four margins: left, top, right, and bottom.
+     */
+    public void setGestureMarginPercent(@FloatRange(from = 0f, to = 0.5f) float percent) {
+        setGestureMarginPercent(percent, percent, percent, percent);
+    }
+
+    /**
+     * Sets the percentage of gestures' margins to avoid touching too close to the edges, e.g.
+     * when scrolling up, phone open quick settings instead if gesture is close to the top.
+     * The percentage is based on the object's visible size, e.g. to set 20% bottom margin only:
+     * <pre>mUiObject2.setGestureMarginPercent(0f, 0f, 0f, 0.2f);</pre>
+     *
+     * @Param left Float between [0, 1] for left margin
+     * @Param top Float between [0, 1] for top margin
+     * @Param right Float between [0, 1] for right margin
+     * @Param bottom Float between [0, 1] for bottom margin
+     */
+    public void setGestureMarginPercent(@FloatRange(from = 0f, to = 1f) float left,
+            @FloatRange(from = 0f, to = 1f) float top,
+            @FloatRange(from = 0f, to = 1f) float right,
+            @FloatRange(from = 0f, to = 1f) float bottom) {
+        mMargins = new PercentMargins(left, top, right, bottom);
+    }
+
     /** Sets the margins used for gestures in pixels. */
     public void setGestureMargin(int margin) {
         setGestureMargins(margin, margin, margin, margin);
@@ -141,10 +173,7 @@
 
     /** Sets the margins used for gestures in pixels. */
     public void setGestureMargins(int left, int top, int right, int bottom) {
-        mMarginLeft = left;
-        mMarginTop = top;
-        mMarginRight = right;
-        mMarginBottom = bottom;
+        mMargins = new SimpleMargins(left, top, right, bottom);
     }
 
     // Wait functions
@@ -240,11 +269,7 @@
     /** Returns this object's visible bounds with the margins removed. */
     private Rect getVisibleBoundsForGestures() {
         Rect ret = getVisibleBounds();
-        ret.left = ret.left + mMarginLeft;
-        ret.top = ret.top + mMarginTop;
-        ret.right = ret.right - mMarginRight;
-        ret.bottom = ret.bottom - mMarginBottom;
-        return ret;
+        return mMargins.apply(ret);
     }
 
     /** Updates a {@code point} to ensure it is within this object's visible bounds. */
@@ -937,4 +962,44 @@
             return accessibilityWindowInfo.getDisplayId();
         }
     }
+
+    private interface Margins {
+        Rect apply(Rect bounds);
+    }
+
+    private static class SimpleMargins implements Margins {
+        int mLeft, mTop, mRight, mBottom;
+        SimpleMargins(int left, int top, int right, int bottom) {
+            mLeft = left;
+            mTop = top;
+            mRight = right;
+            mBottom = bottom;
+        }
+
+        @Override
+        public Rect apply(Rect bounds) {
+            return new Rect(bounds.left + mLeft,
+                    bounds.top + mTop,
+                    bounds.right - mRight,
+                    bounds.bottom - mBottom);
+        }
+    }
+
+    private static class PercentMargins implements Margins {
+        float mLeft, mTop, mRight, mBottom;
+        PercentMargins(float left, float top, float right, float bottom) {
+            mLeft = left;
+            mTop = top;
+            mRight = right;
+            mBottom = bottom;
+        }
+
+        @Override
+        public Rect apply(Rect bounds) {
+            return new Rect(bounds.left + (int) (bounds.width() * mLeft),
+                    bounds.top + (int) (bounds.height() * mTop),
+                    bounds.right - (int) (bounds.width() * mRight),
+                    bounds.bottom - (int) (bounds.height() * mBottom));
+        }
+    }
 }
diff --git a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
index 87cf1b2..5ef04c5 100644
--- a/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
+++ b/testutils/testutils-kmp/src/commonMain/kotlin/androidx/kruth/Subject.kt
@@ -163,7 +163,7 @@
         this == null && expected == null -> true
         this == null || expected == null -> false
         this is ByteArray && expected is ByteArray -> contentEquals(expected)
-        this is Array<*> && expected is Array<*> -> contentEquals(expected)
+        this is Array<*> && expected is Array<*> -> contentDeepEquals(expected)
         isIntegralBoxedPrimitive() && expected.isIntegralBoxedPrimitive() -> {
             integralValue() == expected.integralValue()
         }
diff --git a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
index 2f7b4fc..8cb19f9 100644
--- a/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
+++ b/testutils/testutils-kmp/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
@@ -176,6 +176,40 @@
     }
 
     @Test
+    fun isEqualToNestedArrays() {
+        fun getArray(): Array<*> =
+            arrayOf(
+                intArrayOf(1, 2, 3),
+                arrayOf(
+                    intArrayOf(1, 2, 3),
+                    arrayOf("a", null, "b"),
+                ),
+                listOf(1, 2, 3),
+                "a",
+            )
+
+        assertThat(getArray()).isEqualTo(getArray())
+    }
+
+    @Test
+    fun isEqualToNestedArraysFailsNotEqual() {
+        fun getArray(arg: Int): Array<*> =
+            arrayOf(
+                intArrayOf(1, 2, 3),
+                arrayOf(
+                    intArrayOf(1, arg, 3),
+                    arrayOf("a", null, "b"),
+                ),
+                listOf(1, 2, 3),
+                "a",
+            )
+
+        assertFailsWith<AssertionError> {
+            assertThat(getArray(arg = 10)).isEqualTo(getArray(arg = 20))
+        }
+    }
+
+    @Test
     fun isNotEqualToWithNulls() {
         val o: Any? = null
         assertThat(o).isNotEqualTo("a")
diff --git a/text/text/src/androidTest/java/androidx/compose/ui/text/android/FontPaddingTest.kt b/text/text/src/androidTest/java/androidx/compose/ui/text/android/FontPaddingTest.kt
index f7e466f..d84f481 100644
--- a/text/text/src/androidTest/java/androidx/compose/ui/text/android/FontPaddingTest.kt
+++ b/text/text/src/androidTest/java/androidx/compose/ui/text/android/FontPaddingTest.kt
@@ -18,10 +18,8 @@
 
 import android.graphics.Typeface
 import android.text.TextPaint
-import android.os.Build
 import androidx.core.content.res.ResourcesCompat
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.testutils.fonts.R
@@ -181,12 +179,7 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = 33) // b/262909049: Failing on SDK 34
     fun tallTypefaceTextIsTwiceTheHeightOfLatinTypefaceTextMultiLine() {
-        if (Build.VERSION.SDK_INT == 33 && Build.VERSION.CODENAME != "REL") {
-            return // b/262909049: Do not run this test on pre-release Android U.
-        }
-
         val latinLayout = TextLayout(latinTextMultiLine, typeface = latinTypeface)
         val tallLayout = TextLayout(tallTextMultiLine, typeface = tallTypeface)
 
@@ -212,7 +205,8 @@
             charSequence = text,
             textPaint = textPaint,
             includePadding = includePadding,
-            fallbackLineSpacing = false
+            fallbackLineSpacing = false,
+            width = fontSize * 1.5f
         )
     }
-}
\ No newline at end of file
+}
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 d8cf4f8..009740b 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
@@ -22,7 +22,7 @@
 import android.text.TextPaint
 import androidx.compose.ui.text.android.style.LetterSpacingSpanEm
 import androidx.compose.ui.text.android.style.LetterSpacingSpanPx
-import androidx.compose.ui.text.android.style.LineHeightSpan
+import androidx.compose.ui.text.android.style.LineHeightStyleSpan
 import androidx.core.content.res.ResourcesCompat
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -60,7 +60,7 @@
     @Test
     fun intrinsicWidth_with_letterSpacing_and_lineHeight_createsOneLine() {
         val text = defaultText.apply {
-            setSpan(LineHeightSpan(lineHeight))
+            setLineHeight(lineHeight)
             setSpan(LetterSpacingSpanPx(letterSpacingPx))
         }
 
@@ -71,8 +71,9 @@
     fun intrinsicWidth_with_letterSpacing_and_lineHeight_createsOneLine_multipleSpans() {
         val text = defaultText.apply {
             for (i in 0..8) {
-                setSpan(LineHeightSpan(lineHeight), i, i + 1)
-                setSpan(LetterSpacingSpanPx(letterSpacingPx), i, i + 1)
+                val end = i + 1
+                setLineHeight(lineHeight, i, end)
+                setSpan(LetterSpacingSpanPx(letterSpacingPx), i, end)
             }
         }
 
@@ -82,7 +83,7 @@
     @Test
     fun intrinsicWidth_with_letterSpacingEm_and_lineHeight_createsOneLine() {
         val text = defaultText.apply {
-            setSpan(LineHeightSpan(lineHeight))
+            setLineHeight(lineHeight)
             setSpan(LetterSpacingSpanEm(letterSpacingEm))
         }
 
@@ -92,7 +93,7 @@
     @Test
     fun intrinsicWidth_with_paintLetterSpacing_and_lineHeight_createsOneLine() {
         val text = defaultText.apply {
-            setSpan(LineHeightSpan(lineHeight))
+            setLineHeight(lineHeight)
         }
 
         val paint = defaultPaint.apply {
@@ -114,7 +115,7 @@
     @Test
     fun intrinsicWidth_with_noLetterSpacing_and_withLineHeight_createsOneLine() {
         val text = defaultText.apply {
-            setSpan(LineHeightSpan(lineHeight))
+            setLineHeight(lineHeight)
         }
 
         assertLineCount(text)
@@ -158,9 +159,21 @@
         ).isEqualTo(1)
     }
 
-    fun Spannable.setSpan(span: Any, start: Int = 0, end: Int = length) {
+    private fun Spannable.setSpan(span: Any, start: Int = 0, end: Int = length) {
         this.setSpan(span, start, end, SPAN_INCLUSIVE_INCLUSIVE)
     }
 
-    fun Float.spToPx(): Float = this * fontScale * density
+    private fun Float.spToPx(): Float = this * fontScale * density
+
+    private fun Spannable.setLineHeight(lineHeight: Float, start: Int = 0, end: Int = length) {
+        val span = LineHeightStyleSpan(
+            lineHeight = lineHeight,
+            startIndex = start,
+            endIndex = end,
+            trimFirstLineTop = true,
+            trimLastLineBottom = true,
+            topRatio = -1f /* default: proportional */
+        )
+        setSpan(span, start, end)
+    }
 }
\ No newline at end of file
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 2621b1e..4de574f 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
@@ -53,7 +53,7 @@
 
     @Test
     fun constructor_default_values() {
-        val textLayout = TextLayout(charSequence = "", textPaint = TextPaint())
+        val textLayout = TextLayout(charSequence = "", textPaint = TextPaint(), width = 0f)
         val frameworkLayout = textLayout.layout
 
         assertThat(frameworkLayout.width).isEqualTo(0)
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt b/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
index cb51b971..d55d854 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
@@ -114,7 +114,7 @@
 @InternalPlatformTextApi
 class TextLayout constructor(
     charSequence: CharSequence,
-    width: Float = 0.0f,
+    width: Float,
     textPaint: TextPaint,
     @TextLayoutAlignment alignment: Int = DEFAULT_ALIGNMENT,
     ellipsize: TextUtils.TruncateAt? = null,
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt
deleted file mode 100644
index 9fe46043..0000000
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package androidx.compose.ui.text.android.style
-
-import android.graphics.Paint.FontMetricsInt
-import androidx.compose.ui.text.android.InternalPlatformTextApi
-import kotlin.math.ceil
-
-/**
- * The span which modifies the height of the covered paragraphs. A paragraph is defined as a
- * segment of string divided by '\n' character. To make sure the span work as expected, the
- * boundary of this span should align with paragraph boundary.
- * @constructor Create a LineHeightSpan which sets the line height to `height` physical pixels.
- * @param lineHeight The specified line height in pixel unit, which is the space between the
- * baseline of adjacent lines.
- *
- * @suppress
- */
-@InternalPlatformTextApi
-class LineHeightSpan(
-    val lineHeight: Float
-) : android.text.style.LineHeightSpan {
-
-    override fun chooseHeight(
-        text: CharSequence,
-        start: Int,
-        end: Int,
-        spanstartVertical: Int,
-        lineHeight: Int,
-        fontMetricsInt: FontMetricsInt
-    ) {
-        // In StaticLayout, line height is computed with descent - ascent
-        val currentHeight = fontMetricsInt.lineHeight()
-        // If current height is not positive, do nothing.
-        if (currentHeight <= 0) {
-            return
-        }
-        val ceiledLineHeight = ceil(this.lineHeight).toInt()
-        val ratio = ceiledLineHeight * 1.0f / currentHeight
-        fontMetricsInt.descent = ceil(fontMetricsInt.descent * ratio.toDouble()).toInt()
-        fontMetricsInt.ascent = fontMetricsInt.descent - ceiledLineHeight
-    }
-}
\ No newline at end of file
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
index d0a755a..97a9aa6 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
@@ -50,13 +50,13 @@
     private val endIndex: Int,
     private val trimFirstLineTop: Boolean,
     val trimLastLineBottom: Boolean,
-    @FloatRange(from = 0.0, to = 1.0) private val topRatio: Float
+    @FloatRange(from = -1.0, to = 1.0) private val topRatio: Float
 ) : android.text.style.LineHeightSpan {
 
-    private var firstAscent: Int = 0
-    private var ascent: Int = 0
-    private var descent: Int = 0
-    private var lastDescent: Int = 0
+    private var firstAscent: Int = Int.MIN_VALUE
+    private var ascent: Int = Int.MIN_VALUE
+    private var descent: Int = Int.MIN_VALUE
+    private var lastDescent: Int = Int.MIN_VALUE
 
     /** Holds the firstAscent - fontMetricsInt.ascent */
     var firstAscentDiff = 0
@@ -90,7 +90,9 @@
         // if single line and should not apply, return
         if (isFirstLine && isLastLine && trimFirstLineTop && trimLastLineBottom) return
 
-        if (isFirstLine) calculateTargetMetrics(fontMetricsInt)
+        if (firstAscent == Int.MIN_VALUE) {
+            calculateTargetMetrics(fontMetricsInt)
+        }
 
         fontMetricsInt.ascent = if (isFirstLine) firstAscent else ascent
         fontMetricsInt.descent = if (isLastLine) lastDescent else descent
diff --git a/tracing/tracing-ktx/api/1.2.0-beta02.txt b/tracing/tracing-ktx/api/1.2.0-beta02.txt
new file mode 100644
index 0000000..13d99d1
--- /dev/null
+++ b/tracing/tracing-ktx/api/1.2.0-beta02.txt
@@ -0,0 +1,12 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class TraceKt {
+    method public static inline <T> T! trace(String label, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static inline <T> T! trace(kotlin.jvm.functions.Function0<java.lang.String> lazyLabel, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static suspend inline <T> Object? traceAsync(String methodName, int cookie, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T>);
+    method public static inline <T> T! traceAsync(kotlin.jvm.functions.Function0<java.lang.String> lazyMethodName, kotlin.jvm.functions.Function0<java.lang.Integer> lazyCookie, kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+}
+
diff --git a/tracing/tracing-ktx/api/public_plus_experimental_1.2.0-beta02.txt b/tracing/tracing-ktx/api/public_plus_experimental_1.2.0-beta02.txt
new file mode 100644
index 0000000..13d99d1
--- /dev/null
+++ b/tracing/tracing-ktx/api/public_plus_experimental_1.2.0-beta02.txt
@@ -0,0 +1,12 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class TraceKt {
+    method public static inline <T> T! trace(String label, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static inline <T> T! trace(kotlin.jvm.functions.Function0<java.lang.String> lazyLabel, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static suspend inline <T> Object? traceAsync(String methodName, int cookie, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T>);
+    method public static inline <T> T! traceAsync(kotlin.jvm.functions.Function0<java.lang.String> lazyMethodName, kotlin.jvm.functions.Function0<java.lang.Integer> lazyCookie, kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+}
+
diff --git a/tracing/tracing-ktx/api/res-1.2.0-beta02.txt b/tracing/tracing-ktx/api/res-1.2.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tracing/tracing-ktx/api/res-1.2.0-beta02.txt
diff --git a/tracing/tracing-ktx/api/restricted_1.2.0-beta02.txt b/tracing/tracing-ktx/api/restricted_1.2.0-beta02.txt
new file mode 100644
index 0000000..13d99d1
--- /dev/null
+++ b/tracing/tracing-ktx/api/restricted_1.2.0-beta02.txt
@@ -0,0 +1,12 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class TraceKt {
+    method public static inline <T> T! trace(String label, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static inline <T> T! trace(kotlin.jvm.functions.Function0<java.lang.String> lazyLabel, kotlin.jvm.functions.Function0<? extends T> block);
+    method public static suspend inline <T> Object? traceAsync(String methodName, int cookie, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super T>,?> block, kotlin.coroutines.Continuation<? super T>);
+    method public static inline <T> T! traceAsync(kotlin.jvm.functions.Function0<java.lang.String> lazyMethodName, kotlin.jvm.functions.Function0<java.lang.Integer> lazyCookie, kotlin.jvm.functions.Function0<? extends T> block);
+  }
+
+}
+
diff --git a/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc b/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
index 149d7e0..6b374c9 100644
--- a/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
+++ b/tracing/tracing-perfetto-binary/src/main/cpp/tracing_perfetto.cc
@@ -25,7 +25,7 @@
 // Concept of version useful e.g. for human-readable error messages, and stable once released.
 // Does not replace the need for a binary verification mechanism (e.g. checksum check).
 // TODO: populate using CMake
-#define VERSION "1.0.0-alpha12"
+#define VERSION "1.0.0-alpha13"
 
 namespace tracing_perfetto {
     void RegisterWithPerfetto() {
diff --git a/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt b/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
index 13e2f1d..7611798 100644
--- a/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
+++ b/tracing/tracing-perfetto/src/androidTest/java/androidx/tracing/perfetto/jni/test/PerfettoNativeTest.kt
@@ -30,7 +30,7 @@
         init {
             PerfettoNative.loadLib()
         }
-        const val libraryVersion = "1.0.0-alpha12" // TODO: get using reflection
+        const val libraryVersion = "1.0.0-alpha13" // TODO: get using reflection
     }
 
     @Test
diff --git a/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt b/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
index 9ce873b..3ab9718 100644
--- a/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
+++ b/tracing/tracing-perfetto/src/main/java/androidx/tracing/perfetto/jni/PerfettoNative.kt
@@ -25,12 +25,12 @@
 
     // TODO(224510255): load from a file produced at build time
     object Metadata {
-        const val version = "1.0.0-alpha12"
+        const val version = "1.0.0-alpha13"
         val checksums = mapOf(
-            "arm64-v8a" to "bff106aafe19364627e77bca7f7f658441e35fdd61f9a519f5f814742bd22803",
-            "armeabi-v7a" to "b128da6ed9b69b0db7fa65215c50709d0b1bb5a73c697b4b292cb7326f263c2f",
-            "x86" to "534325ba590cb4f5775c0e0f31fb41521c7a212096f8263b1a1015962799678b",
-            "x86_64" to "56efe76f73b7c4635a42df5037d6ff5f39ddec239893ba716b37e05f6fe3afa3",
+            "arm64-v8a" to "3513a43f87bb7b455a626fbbe3e0f2b65585ad929d81825ce7126fcfe250a6bb",
+            "armeabi-v7a" to "de02d5fcc0f2cfacb2376f18836326886f23cd3df7359d9e0edae93bd6e3e7c8",
+            "x86" to "4ae9b924dc06ac16b0cc591b7bd61197f51efcbfebc0909fdf78778fef1f715c",
+            "x86_64" to "793b66df2d387626f005e15a4ab564acb6e32cd33dc17ec58e46e4fef05326c2",
         )
     }
 
diff --git a/tracing/tracing/api/1.2.0-beta02.txt b/tracing/tracing/api/1.2.0-beta02.txt
new file mode 100644
index 0000000..c883da2
--- /dev/null
+++ b/tracing/tracing/api/1.2.0-beta02.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class Trace {
+    method public static void beginAsyncSection(String, int);
+    method public static void beginSection(String);
+    method public static void endAsyncSection(String, int);
+    method public static void endSection();
+    method public static void forceEnableAppTracing();
+    method public static boolean isEnabled();
+    method public static void setCounter(String, int);
+  }
+
+}
+
diff --git a/tracing/tracing/api/public_plus_experimental_1.2.0-beta02.txt b/tracing/tracing/api/public_plus_experimental_1.2.0-beta02.txt
new file mode 100644
index 0000000..c883da2
--- /dev/null
+++ b/tracing/tracing/api/public_plus_experimental_1.2.0-beta02.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class Trace {
+    method public static void beginAsyncSection(String, int);
+    method public static void beginSection(String);
+    method public static void endAsyncSection(String, int);
+    method public static void endSection();
+    method public static void forceEnableAppTracing();
+    method public static boolean isEnabled();
+    method public static void setCounter(String, int);
+  }
+
+}
+
diff --git a/tracing/tracing/api/res-1.2.0-beta02.txt b/tracing/tracing/api/res-1.2.0-beta02.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tracing/tracing/api/res-1.2.0-beta02.txt
diff --git a/tracing/tracing/api/restricted_1.2.0-beta02.txt b/tracing/tracing/api/restricted_1.2.0-beta02.txt
new file mode 100644
index 0000000..c883da2
--- /dev/null
+++ b/tracing/tracing/api/restricted_1.2.0-beta02.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.tracing {
+
+  public final class Trace {
+    method public static void beginAsyncSection(String, int);
+    method public static void beginSection(String);
+    method public static void endAsyncSection(String, int);
+    method public static void endSection();
+    method public static void forceEnableAppTracing();
+    method public static boolean isEnabled();
+    method public static void setCounter(String, int);
+  }
+
+}
+
diff --git a/tv/integration-tests/demos/build.gradle b/tv/integration-tests/demos/build.gradle
index 8d0133f..31f15c1 100644
--- a/tv/integration-tests/demos/build.gradle
+++ b/tv/integration-tests/demos/build.gradle
@@ -26,16 +26,15 @@
 dependencies {
     implementation(libs.kotlinStdlib)
 
-    implementation("androidx.activity:activity-compose:1.7.0-rc01")
+    implementation("androidx.appcompat:appcompat:1.6.1")
 
+    implementation(project(":activity:activity-compose"))
     implementation(project(":compose:material3:material3"))
     implementation(project(":navigation:navigation-runtime"))
+    implementation(project(":profileinstaller:profileinstaller"))
 
     implementation(project(":tv:tv-foundation"))
     implementation(project(":tv:tv-material"))
-    implementation "androidx.profileinstaller:profileinstaller:1.3.0-alpha03"
-
-    implementation("androidx.appcompat:appcompat:1.6.0-alpha05")
 }
 
 androidx {
diff --git a/tv/samples/src/main/java/androidx/tv/samples/NavigationDrawerSamples.kt b/tv/samples/src/main/java/androidx/tv/samples/NavigationDrawerSamples.kt
index a61b2f6..345adc6 100644
--- a/tv/samples/src/main/java/androidx/tv/samples/NavigationDrawerSamples.kt
+++ b/tv/samples/src/main/java/androidx/tv/samples/NavigationDrawerSamples.kt
@@ -16,6 +16,7 @@
 
 package androidx.tv.samples
 
+import androidx.annotation.Sampled
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.foundation.background
 import androidx.compose.foundation.focusable
@@ -41,53 +42,73 @@
 import androidx.tv.material3.Text
 
 @OptIn(ExperimentalTvMaterial3Api::class)
+@Sampled
 @Composable
 fun SampleNavigationDrawer() {
-    NavigationDrawer(drawerContent = drawerContent()) {
-        NonDrawerContent()
+    val navigationRow: @Composable (drawerValue: DrawerValue, color: Color, text: String) -> Unit =
+        { drawerValue, color, text ->
+            Row(Modifier.padding(10.dp).focusable()) {
+                Box(Modifier.size(50.dp).background(color).padding(end = 20.dp))
+                AnimatedVisibility(visible = drawerValue == DrawerValue.Open) {
+                    Text(
+                        text = text,
+                        softWrap = false,
+                        modifier = Modifier.padding(15.dp).width(50.dp),
+                        textAlign = TextAlign.Center
+                    )
+                }
+            }
+        }
+
+    NavigationDrawer(
+        drawerContent = {
+            Column(Modifier.background(Color.Gray).fillMaxHeight()) {
+                navigationRow(it, Color.Red, "Red")
+                navigationRow(it, Color.Blue, "Blue")
+                navigationRow(it, Color.Yellow, "Yellow")
+            }
+        }
+    ) {
+        Button(modifier = Modifier
+            .height(100.dp)
+            .fillMaxWidth(), onClick = {}) {
+            Text("BUTTON")
+        }
     }
 }
 
 @OptIn(ExperimentalTvMaterial3Api::class)
+@Sampled
 @Composable
 fun SampleModalNavigationDrawer() {
-    ModalNavigationDrawer(drawerContent = drawerContent()) {
-        NonDrawerContent()
-    }
-}
+    val navigationRow: @Composable (drawerValue: DrawerValue, color: Color, text: String) -> Unit =
+        { drawerValue, color, text ->
+            Row(Modifier.padding(10.dp).focusable()) {
+                Box(Modifier.size(50.dp).background(color).padding(end = 20.dp))
+                AnimatedVisibility(visible = drawerValue == DrawerValue.Open) {
+                    Text(
+                        text = text,
+                        softWrap = false,
+                        modifier = Modifier.padding(15.dp).width(50.dp),
+                        textAlign = TextAlign.Center
+                    )
+                }
+            }
+        }
 
-@Composable
-private fun NonDrawerContent() {
-    Button(modifier = Modifier
-        .height(100.dp)
-        .fillMaxWidth(), onClick = {}) {
-        Text("BUTTON")
-    }
-}
-
-@Composable
-@OptIn(ExperimentalTvMaterial3Api::class)
-private fun drawerContent(): @Composable (DrawerValue) -> Unit =
-    {
-        Column(Modifier.background(Color.Gray).fillMaxHeight()) {
-            NavigationRow(it, Color.Red, "Red")
-            NavigationRow(it, Color.Blue, "Blue")
-            NavigationRow(it, Color.Yellow, "Yellow")
+    ModalNavigationDrawer(
+        drawerContent = {
+            Column(Modifier.background(Color.Gray).fillMaxHeight()) {
+                navigationRow(it, Color.Red, "Red")
+                navigationRow(it, Color.Blue, "Blue")
+                navigationRow(it, Color.Yellow, "Yellow")
+            }
+        }
+    ) {
+        Button(modifier = Modifier
+            .height(100.dp)
+            .fillMaxWidth(), onClick = {}) {
+            Text("BUTTON")
         }
     }
-
-@OptIn(ExperimentalTvMaterial3Api::class)
-@Composable
-private fun NavigationRow(drawerValue: DrawerValue, color: Color, text: String) {
-    Row(Modifier.padding(10.dp).focusable()) {
-        Box(Modifier.size(50.dp).background(color).padding(end = 20.dp))
-        AnimatedVisibility(visible = drawerValue == DrawerValue.Open) {
-            Text(
-                text = text,
-                softWrap = false,
-                modifier = Modifier.padding(15.dp).width(50.dp),
-                textAlign = TextAlign.Center
-            )
-        }
-    }
-}
\ No newline at end of file
+}
diff --git a/tv/tv-foundation/build.gradle b/tv/tv-foundation/build.gradle
index 76fef0d..c193d0d 100644
--- a/tv/tv-foundation/build.gradle
+++ b/tv/tv-foundation/build.gradle
@@ -30,17 +30,17 @@
 dependencies {
     api(libs.kotlinStdlib)
 
-    def composeVersion = '1.4.0-alpha04'
+    def composeVersion = '1.4.0-rc01'
 
     implementation(libs.kotlinStdlibCommon)
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
-    api(project(":compose:ui:ui"))
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     api("androidx.annotation:annotation:1.5.0")
     api("androidx.compose.animation:animation:$composeVersion")
     api("androidx.compose.runtime:runtime:$composeVersion")
 
     api(project(":compose:foundation:foundation"))
+    api("androidx.compose.ui:ui:$composeVersion")
     api("androidx.compose.foundation:foundation-layout:$composeVersion")
     api("androidx.compose.ui:ui-graphics:$composeVersion")
     api("androidx.compose.ui:ui-text:$composeVersion")
diff --git a/tv/tv-material/build.gradle b/tv/tv-material/build.gradle
index 6b59668..7b7119b 100644
--- a/tv/tv-material/build.gradle
+++ b/tv/tv-material/build.gradle
@@ -27,13 +27,13 @@
 dependencies {
     api(libs.kotlinStdlib)
 
-    def composeVersion = '1.3.0-rc01'
+    def composeVersion = '1.4.0-rc01'
 
     api("androidx.annotation:annotation:1.5.0")
     api("androidx.compose.runtime:runtime:$composeVersion")
 
-    api(project(":compose:ui:ui"))
     api(project(":compose:animation:animation"))
+    api("androidx.compose.ui:ui:$composeVersion")
     api("androidx.compose.foundation:foundation:$composeVersion")
     api("androidx.compose.foundation:foundation-layout:$composeVersion")
     api("androidx.compose.material:material-icons-core:$composeVersion")
@@ -43,13 +43,14 @@
     api(project(":tv:tv-foundation"))
 
     implementation(libs.kotlinStdlibCommon)
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(libs.truth)
 
     androidTestImplementation(project(":compose:ui:ui-test"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
     androidTestImplementation(project(":compose:test-utils"))
+    androidTestImplementation(project(":test:screenshot:screenshot"))
     androidTestImplementation(libs.testRunner)
 
     samples(project(":tv:tv-samples"))
@@ -60,6 +61,8 @@
     defaultConfig {
         minSdkVersion 21
     }
+    sourceSets.androidTest.assets.srcDirs +=
+             project.rootDir.absolutePath + "/../../golden/tv/compose/material3"
 }
 
 androidx {
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/GoldenCommon.kt
similarity index 78%
copy from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
copy to tv/tv-material/src/androidTest/java/androidx/tv/material3/GoldenCommon.kt
index 8f2bd49..49b8130 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/GoldenCommon.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+package androidx.tv.material3
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+internal const val TV_GOLDEN_MATERIAL3 = "tv/compose/material3"
\ No newline at end of file
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/ModalNavigationDrawerTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/ModalNavigationDrawerTest.kt
index d0f0fda..f221066 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/ModalNavigationDrawerTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/ModalNavigationDrawerTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.tv.material3
 
+import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -25,11 +26,15 @@
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.text.BasicText
 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.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.key.Key
@@ -41,6 +46,7 @@
 import androidx.compose.ui.test.SemanticsNodeInteractionCollection
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsEqualTo
+import androidx.compose.ui.test.assertIsFocused
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.getUnclippedBoundsInRoot
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -125,7 +131,9 @@
             val navigationDrawerValue = remember { DrawerState(DrawerValue.Closed) }
             Row {
                 ModalNavigationDrawer(
-                    modifier = Modifier.focusRequester(drawerFocusRequester).focusable(false),
+                    modifier = Modifier
+                        .focusRequester(drawerFocusRequester)
+                        .focusable(false),
                     drawerState = navigationDrawerValue,
                     drawerContent = {
                         BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
@@ -155,7 +163,17 @@
                 ModalNavigationDrawer(
                     drawerState = navigationDrawerValue,
                     drawerContent = {
-                        BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
+                        var isFocused by remember { mutableStateOf(false) }
+                        BasicText(
+                            text = if (it == DrawerValue.Open) "Opened" else "Closed",
+                            modifier = Modifier
+                                .onFocusChanged { focusState ->
+                                    isFocused = focusState.isFocused
+                                }
+                                .background(if (isFocused) Color.Green else Color.Yellow)
+                                .focusable()
+                                .testTag("drawerItem")
+                        )
                     }) {
                     Box(
                         modifier = Modifier
@@ -172,7 +190,9 @@
         }
         rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()
         rule.onRoot().performKeyInput { pressKey(Key.DirectionLeft) }
+        rule.waitForIdle()
         rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
+        rule.onNodeWithTag("drawerItem").assertIsFocused()
     }
 
     @Test
@@ -191,7 +211,10 @@
                             Box(Modifier.width(closedDrawerContentWidth * 10))
                         }
                     }
-                ) { Box(Modifier.fillMaxWidth().testTag(contentWidthBoxTag)) }
+                ) { Box(
+                    Modifier
+                        .fillMaxWidth()
+                        .testTag(contentWidthBoxTag)) }
             }
         }
 
@@ -213,7 +236,10 @@
                             Box(Modifier.width(openDrawerContentWidth * 10))
                         }
                     }
-                ) { Box(Modifier.fillMaxWidth().testTag(contentWidthBoxTag)) }
+                ) { Box(
+                    Modifier
+                        .fillMaxWidth()
+                        .testTag(contentWidthBoxTag)) }
             }
         }
 
@@ -229,11 +255,17 @@
                 ModalNavigationDrawer(
                     drawerState = remember { DrawerState(DrawerValue.Closed) },
                     drawerContent = {
-                        Box(Modifier.testTag(drawerContentBoxTag).border(2.dp, Color.Red)) {
+                        Box(
+                            Modifier
+                                .testTag(drawerContentBoxTag)
+                                .border(2.dp, Color.Red)) {
                             BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                         }
                     }
-                ) { Box(Modifier.fillMaxWidth().testTag(contentWidthBoxTag)) }
+                ) { Box(
+                    Modifier
+                        .fillMaxWidth()
+                        .testTag(contentWidthBoxTag)) }
             }
         }
 
@@ -252,11 +284,17 @@
                 ModalNavigationDrawer(
                     drawerState = drawerState!!,
                     drawerContent = {
-                        Box(Modifier.testTag(drawerContentBoxTag).border(2.dp, Color.Red)) {
+                        Box(
+                            Modifier
+                                .testTag(drawerContentBoxTag)
+                                .border(2.dp, Color.Red)) {
                             BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
                         }
                     }
-                ) { Box(Modifier.fillMaxWidth().testTag(contentWidthBoxTag)) }
+                ) { Box(
+                    Modifier
+                        .fillMaxWidth()
+                        .testTag(contentWidthBoxTag)) }
             }
         }
 
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerTest.kt
index f414f64..e3c8177 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerTest.kt
@@ -41,6 +41,7 @@
 import androidx.compose.ui.test.SemanticsNodeInteractionCollection
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsEqualTo
+import androidx.compose.ui.test.assertIsFocused
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.getUnclippedBoundsInRoot
 import androidx.compose.ui.test.junit4.StateRestorationTester
@@ -156,7 +157,12 @@
                 NavigationDrawer(
                     drawerState = navigationDrawerValue,
                     drawerContent = {
-                        BasicText(text = if (it == DrawerValue.Open) "Opened" else "Closed")
+                        BasicText(
+                            text = if (it == DrawerValue.Open) "Opened" else "Closed",
+                            modifier = Modifier
+                                .focusable()
+                                .testTag("drawerItem")
+                        )
                     }) {
                     Box(
                         modifier = Modifier
@@ -174,6 +180,7 @@
         rule.onAllNodesWithText("Closed").assertAnyAreDisplayed()
         rule.onRoot().performKeyInput { pressKey(Key.DirectionLeft) }
         rule.onAllNodesWithText("Opened").assertAnyAreDisplayed()
+        rule.onNodeWithTag("drawerItem").assertIsFocused()
     }
 
     @Test
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/TabRowTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/TabRowTest.kt
index fd811f2..198e493 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/TabRowTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/TabRowTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.tv.material3
 
+import android.os.Build
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.focusable
@@ -34,6 +35,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -42,20 +44,52 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsFocused
+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.unit.DpRect
 import androidx.compose.ui.unit.dp
+import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.screenshot.AndroidXScreenshotTestRule
 import org.junit.Rule
 import org.junit.Test
 
 class TabRowTest {
-
     @get:Rule
     val rule = createComposeRule()
 
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(TV_GOLDEN_MATERIAL3)
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun tabRow_pillIndicatorScreenshot() {
+        val tabs = constructTabs(count = 3)
+        val testTag = "TabRowTestTag"
+
+        setContent(
+            tabs = tabs,
+            contentBuilder = {
+                Box {
+                    var selectedTabIndex by remember { mutableStateOf(0) }
+                    TabRowSample(
+                        tabs = tabs,
+                        modifier = Modifier.testTag(testTag),
+                        selectedTabIndex = selectedTabIndex,
+                        onFocus = { selectedTabIndex = it }
+                    )
+                }
+            }
+        )
+
+        rule
+            .onNodeWithTag(testTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, "tab_row_pill_indicator_default")
+    }
+
     @Test
     fun tabRow_shouldNotCrashWithOnly1Tab() {
         val tabs = constructTabs(count = 1)
@@ -233,6 +267,7 @@
 private fun TabRowSample(
     tabs: List<String>,
     selectedTabIndex: Int,
+    modifier: Modifier = Modifier,
     onFocus: (index: Int) -> Unit = {},
     onClick: (index: Int) -> Unit = onFocus,
     buildTab: @Composable ((index: Int, tab: String) -> Unit) = @Composable { index, tab ->
@@ -272,6 +307,7 @@
         if (indicator != null) {
             TabRow(
                 selectedTabIndex = selectedTabIndex,
+                modifier = modifier,
                 indicator = indicator,
                 separator = { Spacer(modifier = Modifier.width(12.dp)) },
             ) {
@@ -280,6 +316,7 @@
         } else {
             TabRow(
                 selectedTabIndex = selectedTabIndex,
+                modifier = modifier,
                 separator = { Spacer(modifier = Modifier.width(12.dp)) },
             ) {
                 tabs.forEachIndexed { index, tab -> buildTab(index, tab) }
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawer.kt b/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawer.kt
index 8cba520..293f84a 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawer.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawer.kt
@@ -39,11 +39,13 @@
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusManager
 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.graphics.Color
 import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.unit.Dp
@@ -70,7 +72,6 @@
  * Drawer-entries can be animated when the drawer moves from Closed to Open state and vice-versa.
  * For, e.g., the entry could show only an icon in the Closed state and slide in text to form
  * (icon + text) when in the Open state.
- * @sample androidx.tv.samples.NavigationRow
  *
  * To limit the width of the drawer in the open or closed state, wrap the content in a box with the
  * required width.
@@ -90,6 +91,7 @@
     content: @Composable () -> Unit
 ) {
     val layoutDirection = LocalLayoutDirection.current
+    val localDensity = LocalDensity.current
     val exitDirection =
         if (layoutDirection == Ltr) FocusDirection.Right else FocusDirection.Left
     val drawerFocusRequester = remember { FocusRequester() }
@@ -107,7 +109,9 @@
                 if (closedDrawerWidth.value == null &&
                     drawerState.currentValue == DrawerValue.Closed
                 ) {
-                    closedDrawerWidth.value = it.width.dp
+                    with(localDensity) {
+                        closedDrawerWidth.value = it.width.toDp()
+                    }
                 }
             }
 
@@ -153,7 +157,6 @@
  * Drawer-entries can be animated when the drawer moves from Closed to Open state and vice-versa.
  * For, e.g., the entry could show only an icon in the Closed state and slide in text to form
  * (icon + text) when in the Open state.
- * @sample androidx.tv.samples.NavigationRow
  *
  * To limit the width of the drawer in the open or closed state, wrap the content in a box with the
  * required width.
@@ -276,17 +279,21 @@
     // indicates that the drawer has been set to its initial state and has grabbed focus if
     // necessary. Controls whether focus is used to decide the state of the drawer going forward.
     var initializationComplete: Boolean = remember { false }
+    val focusManager = LocalFocusManager.current
+    var focusState by remember { mutableStateOf<FocusState?>(null) }
+
+    val isDrawerOpen = drawerState.currentValue == DrawerValue.Open
+    val isDrawerClosed = drawerState.currentValue == DrawerValue.Closed
 
     val focusRequester = remember { FocusRequester() }
     LaunchedEffect(key1 = drawerState.currentValue) {
-        if (drawerState.currentValue == DrawerValue.Open) {
+        if (drawerState.currentValue == DrawerValue.Open && focusState?.hasFocus == false) {
             // used to grab focus if the drawer state is set to Open on start.
             focusRequester.requestFocus()
         }
         initializationComplete = true
     }
 
-    val focusManager = LocalFocusManager.current
     val internalModifier =
         Modifier
             .focusRequester(focusRequester)
@@ -296,14 +303,14 @@
             // size based modifiers.
             .then(modifier)
             .onFocusChanged {
+                focusState = it
                 when {
-                    it.isFocused && drawerState.currentValue == DrawerValue.Closed -> {
+                    it.isFocused && isDrawerClosed -> {
                         drawerState.setValue(DrawerValue.Open)
                         focusManager.moveFocus(FocusDirection.Enter)
                     }
 
-                    !it.hasFocus && drawerState.currentValue == DrawerValue.Open &&
-                        initializationComplete -> {
+                    !it.hasFocus && isDrawerOpen && initializationComplete -> {
                         drawerState.setValue(DrawerValue.Closed)
                     }
                 }
diff --git a/wear/compose/compose-foundation/api/current.txt b/wear/compose/compose-foundation/api/current.txt
index 384b168..117b84c 100644
--- a/wear/compose/compose-foundation/api/current.txt
+++ b/wear/compose/compose-foundation/api/current.txt
@@ -171,6 +171,30 @@
     property public final androidx.compose.ui.text.font.FontWeight? fontWeight;
   }
 
+  public final class ExpandableItemsDefaults {
+    method @androidx.compose.runtime.Composable public void Chevron(float progress, long color, optional androidx.compose.ui.Modifier modifier, optional float strokeWidth);
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
+    field public static final androidx.wear.compose.foundation.ExpandableItemsDefaults INSTANCE;
+  }
+
+  public final class ExpandableItemsState {
+    method public float getExpandProgress();
+    method public boolean isExpanded();
+    method public void setExpanded(boolean);
+    method public void toggle();
+    property public final float expandProgress;
+    property public final boolean expanded;
+  }
+
+  public final class ExpandableKt {
+    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
+    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    method @androidx.compose.runtime.Composable public static androidx.wear.compose.foundation.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
+  }
+
 }
 
 package androidx.wear.compose.foundation.lazy {
diff --git a/wear/compose/compose-foundation/api/public_plus_experimental_current.txt b/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
index eda89f7..abaaf5d 100644
--- a/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-foundation/api/public_plus_experimental_current.txt
@@ -171,6 +171,30 @@
     property public final androidx.compose.ui.text.font.FontWeight? fontWeight;
   }
 
+  public final class ExpandableItemsDefaults {
+    method @androidx.compose.runtime.Composable public void Chevron(float progress, long color, optional androidx.compose.ui.Modifier modifier, optional float strokeWidth);
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
+    field public static final androidx.wear.compose.foundation.ExpandableItemsDefaults INSTANCE;
+  }
+
+  public final class ExpandableItemsState {
+    method public float getExpandProgress();
+    method public boolean isExpanded();
+    method public void setExpanded(boolean);
+    method public void toggle();
+    property public final float expandProgress;
+    property public final boolean expanded;
+  }
+
+  public final class ExpandableKt {
+    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
+    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    method @androidx.compose.runtime.Composable public static androidx.wear.compose.foundation.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
+  }
+
   @kotlin.RequiresOptIn(message="This Wear Foundation API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWearFoundationApi {
   }
 
diff --git a/wear/compose/compose-foundation/api/restricted_current.txt b/wear/compose/compose-foundation/api/restricted_current.txt
index 384b168..117b84c 100644
--- a/wear/compose/compose-foundation/api/restricted_current.txt
+++ b/wear/compose/compose-foundation/api/restricted_current.txt
@@ -171,6 +171,30 @@
     property public final androidx.compose.ui.text.font.FontWeight? fontWeight;
   }
 
+  public final class ExpandableItemsDefaults {
+    method @androidx.compose.runtime.Composable public void Chevron(float progress, long color, optional androidx.compose.ui.Modifier modifier, optional float strokeWidth);
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
+    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
+    field public static final androidx.wear.compose.foundation.ExpandableItemsDefaults INSTANCE;
+  }
+
+  public final class ExpandableItemsState {
+    method public float getExpandProgress();
+    method public boolean isExpanded();
+    method public void setExpanded(boolean);
+    method public void toggle();
+    property public final float expandProgress;
+    property public final boolean expanded;
+  }
+
+  public final class ExpandableKt {
+    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
+    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.foundation.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
+    method @androidx.compose.runtime.Composable public static androidx.wear.compose.foundation.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
+  }
+
 }
 
 package androidx.wear.compose.foundation.lazy {
diff --git a/wear/compose/compose-foundation/build.gradle b/wear/compose/compose-foundation/build.gradle
index 5a85f33..81bb66b5 100644
--- a/wear/compose/compose-foundation/build.gradle
+++ b/wear/compose/compose-foundation/build.gradle
@@ -35,7 +35,7 @@
     implementation(libs.kotlinStdlib)
     implementation(project(":compose:foundation:foundation-layout"))
     implementation(project(":compose:ui:ui-util"))
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     testImplementation(libs.testRules)
     testImplementation(libs.testRunner)
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ExpandableSample.kt b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
similarity index 92%
rename from wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ExpandableSample.kt
rename to wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
index afa936f..3769f31 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/ExpandableSample.kt
+++ b/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/ExpandableSample.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material.samples
+package androidx.wear.compose.foundation.samples
 
 import androidx.annotation.Sampled
 import androidx.compose.foundation.layout.Spacer
@@ -25,15 +25,15 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.ExpandableItemsDefaults
+import androidx.wear.compose.foundation.expandableItem
+import androidx.wear.compose.foundation.expandableItems
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.rememberExpandableItemsState
 import androidx.wear.compose.material.Chip
-import androidx.wear.compose.material.ExpandableItemsDefaults
 import androidx.wear.compose.material.MaterialTheme
 import androidx.wear.compose.material.OutlinedChip
 import androidx.wear.compose.material.Text
-import androidx.wear.compose.material.expandableItem
-import androidx.wear.compose.material.expandableItems
-import androidx.wear.compose.material.rememberExpandableItemsState
 
 @Sampled
 @Composable
diff --git a/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt b/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
index 7dcec87..170be37 100644
--- a/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
+++ b/wear/compose/compose-foundation/src/androidAndroidTest/kotlin/androidx/wear/compose/foundation/CurvedScreenshotTest.kt
@@ -34,6 +34,8 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.text.PlatformTextStyle
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
@@ -125,7 +127,13 @@
             curvedComposable {
                 Column {
                     Box(Modifier.size(15.dp).background(Color.Red))
-                    BasicText("Text")
+                    @Suppress("DEPRECATION")
+                    BasicText(
+                        text = "Text",
+                        style = TextStyle(
+                            platformStyle = PlatformTextStyle(includeFontPadding = true)
+                        )
+                    )
                     Box(Modifier.size(15.dp).background(Color.Red))
                 }
             }
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Expandable.kt b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/Expandable.kt
similarity index 95%
rename from wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Expandable.kt
rename to wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/Expandable.kt
index 47cffe6..1fafbf8 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Expandable.kt
+++ b/wear/compose/compose-foundation/src/commonMain/kotlin/androidx/wear/compose/foundation/Expandable.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material
+package androidx.wear.compose.foundation
 
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.AnimationSpec
@@ -45,10 +45,10 @@
  * Create and [remember] an [ExpandableItemsState]
  *
  * Example of an expandable list:
- * @sample androidx.wear.compose.material.samples.ExpandableWithItemsSample
+ * @sample androidx.wear.compose.foundation.samples.ExpandableWithItemsSample
  *
  * Example of an expandable text:
- * @sample androidx.wear.compose.material.samples.ExpandableTextSample
+ * @sample androidx.wear.compose.foundation.samples.ExpandableTextSample
  *
  * @param initiallyExpanded The initial value of the state.
  * @param expandAnimationSpec The [AnimationSpec] to use when showing the extra information.
@@ -70,7 +70,7 @@
  * Adds a series of items, that will be expanded/collapsed according to the [ExpandableItemsState]
  *
  * Example of an expandable list:
- * @sample androidx.wear.compose.material.samples.ExpandableWithItemsSample
+ * @sample androidx.wear.compose.foundation.samples.ExpandableWithItemsSample
  *
  * @param state The [ExpandableItemsState] connected to these items to.
  * @param count The number of items
@@ -115,7 +115,7 @@
  * Adds a single item, that will be expanded/collapsed according to the [ExpandableItemsState].
  *
  * Example of an expandable text:
- * @sample androidx.wear.compose.material.samples.ExpandableTextSample
+ * @sample androidx.wear.compose.foundation.samples.ExpandableTextSample
  *
  * The item should support two levels of information display (for example, a text showing a few
  * lines in the collapsed state, and more in the expanded state)
@@ -229,16 +229,16 @@
      *
      * @param progress The point in the animation we are displaying this chevron in. 0f means pointing
      * downward, 1f means pointing upward.
+     * @param color The color to draw this chevron on.
      * @param modifier Modifier to be applied to the AnimatableChevron. This can be used to provide a
      * content description for accessibility.
-     * @param color The color to draw this chevron on.
      * @param strokeWidth The stroke width used to draw this chevron.
      */
     @Composable
     public fun Chevron(
         progress: Float,
+        color: Color,
         modifier: Modifier = Modifier,
-        color: Color = MaterialTheme.colors.onBackground,
         strokeWidth: Dp = 3.dp
     ) {
         Box(
diff --git a/wear/compose/compose-material-core/build.gradle b/wear/compose/compose-material-core/build.gradle
index 84995a0..fe566204 100644
--- a/wear/compose/compose-material-core/build.gradle
+++ b/wear/compose/compose-material-core/build.gradle
@@ -39,7 +39,7 @@
     implementation(project(":compose:material:material-ripple"))
     implementation(project(":compose:ui:ui-util"))
     implementation(project(":wear:compose:compose-foundation"))
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(project(":compose:ui:ui-test"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
diff --git a/wear/compose/compose-material/api/current.txt b/wear/compose/compose-material/api/current.txt
index 1be733d..761dc1e8 100644
--- a/wear/compose/compose-material/api/current.txt
+++ b/wear/compose/compose-material/api/current.txt
@@ -184,30 +184,6 @@
     method @Deprecated public static void curvedText(androidx.wear.compose.foundation.CurvedScope, String text, optional androidx.wear.compose.foundation.CurvedModifier modifier, optional long background, optional long color, optional long fontSize, optional androidx.wear.compose.foundation.CurvedTextStyle? style, optional androidx.wear.compose.foundation.CurvedDirection.Angular? angularDirection, optional int overflow);
   }
 
-  public final class ExpandableItemsDefaults {
-    method @androidx.compose.runtime.Composable public void Chevron(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
-    field public static final androidx.wear.compose.material.ExpandableItemsDefaults INSTANCE;
-  }
-
-  public final class ExpandableItemsState {
-    method public float getExpandProgress();
-    method public boolean isExpanded();
-    method public void setExpanded(boolean);
-    method public void toggle();
-    property public final float expandProgress;
-    property public final boolean expanded;
-  }
-
-  public final class ExpandableKt {
-    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
-    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
-  }
-
   public final class HorizontalPageIndicatorKt {
     method @androidx.compose.runtime.Composable public static void HorizontalPageIndicator(androidx.wear.compose.material.PageIndicatorState pageIndicatorState, optional androidx.compose.ui.Modifier modifier, optional int indicatorStyle, optional long selectedColor, optional long unselectedColor, optional float indicatorSize, optional float spacing, optional androidx.compose.ui.graphics.Shape indicatorShape);
   }
diff --git a/wear/compose/compose-material/api/public_plus_experimental_current.txt b/wear/compose/compose-material/api/public_plus_experimental_current.txt
index c1255f3..3dd2192 100644
--- a/wear/compose/compose-material/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material/api/public_plus_experimental_current.txt
@@ -185,30 +185,6 @@
     method @Deprecated public static void curvedText(androidx.wear.compose.foundation.CurvedScope, String text, optional androidx.wear.compose.foundation.CurvedModifier modifier, optional long background, optional long color, optional long fontSize, optional androidx.wear.compose.foundation.CurvedTextStyle? style, optional androidx.wear.compose.foundation.CurvedDirection.Angular? angularDirection, optional int overflow);
   }
 
-  public final class ExpandableItemsDefaults {
-    method @androidx.compose.runtime.Composable public void Chevron(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
-    field public static final androidx.wear.compose.material.ExpandableItemsDefaults INSTANCE;
-  }
-
-  public final class ExpandableItemsState {
-    method public float getExpandProgress();
-    method public boolean isExpanded();
-    method public void setExpanded(boolean);
-    method public void toggle();
-    property public final float expandProgress;
-    property public final boolean expanded;
-  }
-
-  public final class ExpandableKt {
-    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
-    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
-  }
-
   @kotlin.RequiresOptIn(message="This Wear Material API is experimental and is likely to change or to be removed in" + " the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalWearMaterialApi {
   }
 
diff --git a/wear/compose/compose-material/api/restricted_current.txt b/wear/compose/compose-material/api/restricted_current.txt
index 1be733d..761dc1e8 100644
--- a/wear/compose/compose-material/api/restricted_current.txt
+++ b/wear/compose/compose-material/api/restricted_current.txt
@@ -184,30 +184,6 @@
     method @Deprecated public static void curvedText(androidx.wear.compose.foundation.CurvedScope, String text, optional androidx.wear.compose.foundation.CurvedModifier modifier, optional long background, optional long color, optional long fontSize, optional androidx.wear.compose.foundation.CurvedTextStyle? style, optional androidx.wear.compose.foundation.CurvedDirection.Angular? angularDirection, optional int overflow);
   }
 
-  public final class ExpandableItemsDefaults {
-    method @androidx.compose.runtime.Composable public void Chevron(float progress, optional androidx.compose.ui.Modifier modifier, optional long color, optional float strokeWidth);
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getCollapseAnimationSpec();
-    method public androidx.compose.animation.core.AnimationSpec<java.lang.Float> getExpandAnimationSpec();
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec;
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec;
-    field public static final androidx.wear.compose.material.ExpandableItemsDefaults INSTANCE;
-  }
-
-  public final class ExpandableItemsState {
-    method public float getExpandProgress();
-    method public boolean isExpanded();
-    method public void setExpanded(boolean);
-    method public void toggle();
-    property public final float expandProgress;
-    property public final boolean expanded;
-  }
-
-  public final class ExpandableKt {
-    method public static void expandableItem(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, optional Object? key, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> content);
-    method public static void expandableItems(androidx.wear.compose.foundation.lazy.ScalingLazyListScope, androidx.wear.compose.material.ExpandableItemsState state, int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.BoxScope,? super java.lang.Integer,kotlin.Unit> itemContent);
-    method @androidx.compose.runtime.Composable public static androidx.wear.compose.material.ExpandableItemsState rememberExpandableItemsState(optional boolean initiallyExpanded, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> expandAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> collapseAnimationSpec);
-  }
-
   public final class HorizontalPageIndicatorKt {
     method @androidx.compose.runtime.Composable public static void HorizontalPageIndicator(androidx.wear.compose.material.PageIndicatorState pageIndicatorState, optional androidx.compose.ui.Modifier modifier, optional int indicatorStyle, optional long selectedColor, optional long unselectedColor, optional float indicatorSize, optional float spacing, optional androidx.compose.ui.graphics.Shape indicatorShape);
   }
diff --git a/wear/compose/compose-material/build.gradle b/wear/compose/compose-material/build.gradle
index e1354a3..03e7a68 100644
--- a/wear/compose/compose-material/build.gradle
+++ b/wear/compose/compose-material/build.gradle
@@ -40,7 +40,7 @@
     implementation(project(":compose:ui:ui-util"))
     implementation(project(":wear:compose:compose-foundation"))
     implementation(project(":wear:compose:compose-material-core"))
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
     implementation("androidx.lifecycle:lifecycle-common:2.5.1")
 
     androidTestImplementation(project(":compose:ui:ui-test"))
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt b/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.android.kt
similarity index 62%
copy from compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
copy to wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.android.kt
index 6f365ff..5365a53 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material/TimeFormat.desktop.kt
+++ b/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.android.kt
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3
+package androidx.wear.compose.material
 
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual val is24HourFormat: Boolean
-    @Composable
-    @ReadOnlyComposable get() = false
\ No newline at end of file
+private const val DefaultIncludeFontPadding = true
+
+@Suppress("DEPRECATION")
+private val DefaultPlatformTextStyle = PlatformTextStyle(
+    includeFontPadding = DefaultIncludeFontPadding
+)
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = DefaultPlatformTextStyle
\ No newline at end of file
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
index a9be263..d31497f 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PickerGroup.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.gestures.awaitFirstDown
 import androidx.compose.foundation.gestures.scrollable
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
@@ -112,12 +113,16 @@
             ),
         propagateMinConstraints = propagateMinConstraints
     ) {
+        // When no Picker is selected, provide an empty composable as a placeholder
+        // and tell the HierarchicalFocusCoordinator to clear the focus.
+        HierarchicalFocusCoordinator(requiresFocus = {
+            !pickers.indices.contains(pickerGroupState.selectedIndex)
+        }) {}
         pickers.forEachIndexed { index, pickerData ->
             val pickerSelected = index == pickerGroupState.selectedIndex
             val flingBehavior = PickerDefaults.flingBehavior(state = pickerData.pickerState)
             HierarchicalFocusCoordinator(requiresFocus = { pickerSelected }) {
-                val focusRequester =
-                    pickerData.focusRequester ?: rememberActiveFocusRequester()
+                val focusRequester = pickerData.focusRequester ?: rememberActiveFocusRequester()
                 Picker(
                     state = pickerData.pickerState,
                     contentDescription = pickerData.contentDescription,
@@ -129,7 +134,8 @@
                             if (pickerSelected && autoCenter) Modifier.autoCenteringTarget()
                             else Modifier
                         )
-                        .focusRequester(focusRequester),
+                        .focusRequester(focusRequester)
+                        .focusable(),
                     readOnlyLabel = pickerData.readOnlyLabel,
                     flingBehavior = flingBehavior,
                     onSelected = pickerData.onSelected,
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Text.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Text.kt
index 297bc4a..7991332 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Text.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Text.kt
@@ -429,7 +429,7 @@
  * @see ProvideTextStyle
  */
 public val LocalTextStyle: ProvidableCompositionLocal<TextStyle> =
-    compositionLocalOf(structuralEqualityPolicy()) { TextStyle.Default }
+    compositionLocalOf(structuralEqualityPolicy()) { DefaultTextStyle }
 
 // TODO: b/156598010 remove this and replace with fold definition on the backing CompositionLocal
 /**
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Typography.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Typography.kt
index ca17826..1c7c2a3 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Typography.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Typography.kt
@@ -17,6 +17,7 @@
 
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.text.PlatformTextStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontWeight
@@ -87,79 +88,78 @@
 ) {
     public constructor (
         defaultFontFamily: FontFamily = FontFamily.Default,
-        display1: TextStyle = TextStyle(
+        display1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 40.sp,
             lineHeight = 46.sp,
             letterSpacing = 0.5.sp
         ),
-        display2: TextStyle = TextStyle(
+        display2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 34.sp,
             lineHeight = 40.sp,
             letterSpacing = 1.sp
         ),
-        display3: TextStyle = TextStyle(
+        display3: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 30.sp,
             lineHeight = 36.sp,
             letterSpacing = 0.8.sp,
         ),
-        title1: TextStyle = TextStyle(
+        title1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 24.sp,
             lineHeight = 28.sp,
             letterSpacing = 0.2.sp
         ),
-        title2: TextStyle = TextStyle(
+        title2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 20.sp,
             lineHeight = 24.sp,
             letterSpacing = 0.2.sp
         ),
-        title3: TextStyle = TextStyle(
+        title3: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 16.sp,
             lineHeight = 20.sp,
             letterSpacing = 0.2.sp
         ),
-        body1: TextStyle = TextStyle(
+        body1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 16.sp,
             lineHeight = 20.sp,
             letterSpacing = 0.18.sp
         ),
-        body2: TextStyle = TextStyle(
+        body2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Normal,
             fontSize = 14.sp,
             lineHeight = 18.sp,
             letterSpacing = 0.2.sp
         ),
-        button: TextStyle = TextStyle(
+        button: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Bold,
             fontSize = 15.sp,
             lineHeight = 19.sp,
             letterSpacing = 0.38.sp
         ),
-        caption1: TextStyle = TextStyle(
+        caption1: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 14.sp,
             lineHeight = 18.sp,
             letterSpacing = 0.1.sp
         ),
-        caption2: TextStyle = TextStyle(
+        caption2: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 12.sp,
             lineHeight = 16.sp,
             letterSpacing = 0.1.sp
         ),
-        caption3: TextStyle = TextStyle(
+        caption3: TextStyle = DefaultTextStyle.copy(
             fontWeight = FontWeight.Medium,
             fontSize = 10.sp,
             lineHeight = 14.sp,
             letterSpacing = 0.1.sp
         )
-
     ) : this(
         display1 = display1.withDefaultFontFamily(defaultFontFamily),
         display2 = display2.withDefaultFontFamily(defaultFontFamily),
@@ -257,6 +257,15 @@
     return if (fontFamily != null) this else copy(fontFamily = default)
 }
 
+internal val DefaultTextStyle = TextStyle.Default.copy(
+    platformStyle = defaultPlatformTextStyle()
+)
+
+/**
+ * Returns Default [PlatformTextStyle].
+ */
+internal expect fun defaultPlatformTextStyle(): PlatformTextStyle?
+
 /**
  * This Ambient holds on to the current definition of typography for this application as described
  * by the Wear Material spec. You can read the values in it when creating custom components that
diff --git a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt b/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.desktop.kt
similarity index 78%
rename from compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
rename to wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.desktop.kt
index 8f2bd49..fd5d994 100644
--- a/compose/foundation/foundation-newtext/src/jvmMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/AtomicLong.kt
+++ b/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/DefaultPlatformTextStyle.desktop.kt
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-// ktlint-disable filename
+package androidx.wear.compose.material
 
-package androidx.compose.foundation.newtext.text.copypasta
+import androidx.compose.ui.text.PlatformTextStyle
 
-internal actual typealias AtomicLong = java.util.concurrent.atomic.AtomicLong
\ No newline at end of file
+internal actual fun defaultPlatformTextStyle(): PlatformTextStyle? = null
\ No newline at end of file
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index e6f50d0..2dbfac5 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -1 +1,186 @@
 // Signature format: 4.0
+package androidx.wear.compose.material3 {
+
+  @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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    method public long getBackground();
+    method public long getError();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getPrimaryDim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSecondaryDim();
+    method public long getSurface();
+    method public long getSurfaceBright();
+    method public long getSurfaceDim();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    method public long getTertiaryDim();
+    method public void setSecondaryDim(long);
+    property public final long background;
+    property public final long error;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long primaryDim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long secondaryDim;
+    property public final long surface;
+    property public final long surfaceBright;
+    property public final long surfaceDim;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+    property public final long tertiaryDim;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.wear.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+  }
+
+  public final class ContentAlpha {
+    method @androidx.compose.runtime.Composable public float getDisabled();
+    method @androidx.compose.runtime.Composable public float getHigh();
+    method @androidx.compose.runtime.Composable public float getMedium();
+    property @androidx.compose.runtime.Composable public final float disabled;
+    property @androidx.compose.runtime.Composable public final float high;
+    property @androidx.compose.runtime.Composable public final float medium;
+    field public static final androidx.wear.compose.material3.ContentAlpha INSTANCE;
+  }
+
+  public final class ContentAlphaKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> getLocalContentAlpha();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> LocalContentAlpha;
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  public final class MaterialTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Typography typography;
+    field public static final androidx.wear.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    method @androidx.compose.runtime.Composable public static void MaterialTheme(optional androidx.wear.compose.material3.ColorScheme colorScheme, optional androidx.wear.compose.material3.Typography typography, optional androidx.wear.compose.material3.Shapes shapes, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraSmall();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getFull();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getSmall();
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Full;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Large;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Medium;
+    property public final androidx.compose.ui.graphics.Shape None;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Small;
+    field public static final androidx.wear.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.wear.compose.material3.Shapes copy(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.compose.ui.graphics.Shape getExtraLarge();
+    method public androidx.compose.ui.graphics.Shape getExtraSmall();
+    method public androidx.compose.ui.graphics.Shape getFull();
+    method public androidx.compose.ui.graphics.Shape getLarge();
+    method public androidx.compose.ui.graphics.Shape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.ui.graphics.Shape getSmall();
+    property public final androidx.compose.ui.graphics.Shape extraLarge;
+    property public final androidx.compose.ui.graphics.Shape extraSmall;
+    property public final androidx.compose.ui.graphics.Shape full;
+    property public final androidx.compose.ui.graphics.Shape large;
+    property public final androidx.compose.ui.graphics.Shape medium;
+    property public final androidx.compose.ui.graphics.Shape none;
+    property public final androidx.compose.ui.graphics.Shape small;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @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 displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getButtonMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionLarge();
+    method public androidx.compose.ui.text.TextStyle getCaptionMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionSmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayExtraLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle buttonMedium;
+    property public final androidx.compose.ui.text.TextStyle captionLarge;
+    property public final androidx.compose.ui.text.TextStyle captionMedium;
+    property public final androidx.compose.ui.text.TextStyle captionSmall;
+    property public final androidx.compose.ui.text.TextStyle displayExtraLarge;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    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/public_plus_experimental_current.txt b/wear/compose/compose-material3/api/public_plus_experimental_current.txt
index e6f50d0..2dbfac5 100644
--- a/wear/compose/compose-material3/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material3/api/public_plus_experimental_current.txt
@@ -1 +1,186 @@
 // Signature format: 4.0
+package androidx.wear.compose.material3 {
+
+  @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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    method public long getBackground();
+    method public long getError();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getPrimaryDim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSecondaryDim();
+    method public long getSurface();
+    method public long getSurfaceBright();
+    method public long getSurfaceDim();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    method public long getTertiaryDim();
+    method public void setSecondaryDim(long);
+    property public final long background;
+    property public final long error;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long primaryDim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long secondaryDim;
+    property public final long surface;
+    property public final long surfaceBright;
+    property public final long surfaceDim;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+    property public final long tertiaryDim;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.wear.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+  }
+
+  public final class ContentAlpha {
+    method @androidx.compose.runtime.Composable public float getDisabled();
+    method @androidx.compose.runtime.Composable public float getHigh();
+    method @androidx.compose.runtime.Composable public float getMedium();
+    property @androidx.compose.runtime.Composable public final float disabled;
+    property @androidx.compose.runtime.Composable public final float high;
+    property @androidx.compose.runtime.Composable public final float medium;
+    field public static final androidx.wear.compose.material3.ContentAlpha INSTANCE;
+  }
+
+  public final class ContentAlphaKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> getLocalContentAlpha();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> LocalContentAlpha;
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  public final class MaterialTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Typography typography;
+    field public static final androidx.wear.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    method @androidx.compose.runtime.Composable public static void MaterialTheme(optional androidx.wear.compose.material3.ColorScheme colorScheme, optional androidx.wear.compose.material3.Typography typography, optional androidx.wear.compose.material3.Shapes shapes, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraSmall();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getFull();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getSmall();
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Full;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Large;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Medium;
+    property public final androidx.compose.ui.graphics.Shape None;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Small;
+    field public static final androidx.wear.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.wear.compose.material3.Shapes copy(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.compose.ui.graphics.Shape getExtraLarge();
+    method public androidx.compose.ui.graphics.Shape getExtraSmall();
+    method public androidx.compose.ui.graphics.Shape getFull();
+    method public androidx.compose.ui.graphics.Shape getLarge();
+    method public androidx.compose.ui.graphics.Shape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.ui.graphics.Shape getSmall();
+    property public final androidx.compose.ui.graphics.Shape extraLarge;
+    property public final androidx.compose.ui.graphics.Shape extraSmall;
+    property public final androidx.compose.ui.graphics.Shape full;
+    property public final androidx.compose.ui.graphics.Shape large;
+    property public final androidx.compose.ui.graphics.Shape medium;
+    property public final androidx.compose.ui.graphics.Shape none;
+    property public final androidx.compose.ui.graphics.Shape small;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @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 displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getButtonMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionLarge();
+    method public androidx.compose.ui.text.TextStyle getCaptionMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionSmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayExtraLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle buttonMedium;
+    property public final androidx.compose.ui.text.TextStyle captionLarge;
+    property public final androidx.compose.ui.text.TextStyle captionMedium;
+    property public final androidx.compose.ui.text.TextStyle captionSmall;
+    property public final androidx.compose.ui.text.TextStyle displayExtraLarge;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    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 e6f50d0..2dbfac5 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -1 +1,186 @@
 // Signature format: 4.0
+package androidx.wear.compose.material3 {
+
+  @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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    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 surfaceDim, optional long surface, optional long surfaceBright, optional long onSurface, optional long onSurfaceVariant, optional long outline, optional long outlineVariant, optional long background, optional long onBackground, optional long error, optional long onError);
+    method public long getBackground();
+    method public long getError();
+    method public long getOnBackground();
+    method public long getOnError();
+    method public long getOnPrimary();
+    method public long getOnPrimaryContainer();
+    method public long getOnSecondary();
+    method public long getOnSecondaryContainer();
+    method public long getOnSurface();
+    method public long getOnSurfaceVariant();
+    method public long getOnTertiary();
+    method public long getOnTertiaryContainer();
+    method public long getOutline();
+    method public long getOutlineVariant();
+    method public long getPrimary();
+    method public long getPrimaryContainer();
+    method public long getPrimaryDim();
+    method public long getSecondary();
+    method public long getSecondaryContainer();
+    method public long getSecondaryDim();
+    method public long getSurface();
+    method public long getSurfaceBright();
+    method public long getSurfaceDim();
+    method public long getTertiary();
+    method public long getTertiaryContainer();
+    method public long getTertiaryDim();
+    method public void setSecondaryDim(long);
+    property public final long background;
+    property public final long error;
+    property public final long onBackground;
+    property public final long onError;
+    property public final long onPrimary;
+    property public final long onPrimaryContainer;
+    property public final long onSecondary;
+    property public final long onSecondaryContainer;
+    property public final long onSurface;
+    property public final long onSurfaceVariant;
+    property public final long onTertiary;
+    property public final long onTertiaryContainer;
+    property public final long outline;
+    property public final long outlineVariant;
+    property public final long primary;
+    property public final long primaryContainer;
+    property public final long primaryDim;
+    property public final long secondary;
+    property public final long secondaryContainer;
+    property public final long secondaryDim;
+    property public final long surface;
+    property public final long surfaceBright;
+    property public final long surfaceDim;
+    property public final long tertiary;
+    property public final long tertiaryContainer;
+    property public final long tertiaryDim;
+  }
+
+  public final class ColorSchemeKt {
+    method public static long contentColorFor(androidx.wear.compose.material3.ColorScheme, long backgroundColor);
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public static long contentColorFor(long backgroundColor);
+  }
+
+  public final class ContentAlpha {
+    method @androidx.compose.runtime.Composable public float getDisabled();
+    method @androidx.compose.runtime.Composable public float getHigh();
+    method @androidx.compose.runtime.Composable public float getMedium();
+    property @androidx.compose.runtime.Composable public final float disabled;
+    property @androidx.compose.runtime.Composable public final float high;
+    property @androidx.compose.runtime.Composable public final float medium;
+    field public static final androidx.wear.compose.material3.ContentAlpha INSTANCE;
+  }
+
+  public final class ContentAlphaKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> getLocalContentAlpha();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.Float> LocalContentAlpha;
+  }
+
+  public final class ContentColorKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> getLocalContentColor();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.graphics.Color> LocalContentColor;
+  }
+
+  public final class IconKt {
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.vector.ImageVector imageVector, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.ImageBitmap bitmap, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+    method @androidx.compose.runtime.Composable public static void Icon(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional long tint);
+  }
+
+  public final class MaterialTheme {
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.ColorScheme getColorScheme();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Shapes getShapes();
+    method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.wear.compose.material3.Typography getTypography();
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.ColorScheme colorScheme;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Shapes shapes;
+    property @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public final androidx.wear.compose.material3.Typography typography;
+    field public static final androidx.wear.compose.material3.MaterialTheme INSTANCE;
+  }
+
+  public final class MaterialThemeKt {
+    method @androidx.compose.runtime.Composable public static void MaterialTheme(optional androidx.wear.compose.material3.ColorScheme colorScheme, optional androidx.wear.compose.material3.Typography typography, optional androidx.wear.compose.material3.Shapes shapes, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
+  public final class ShapeDefaults {
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getExtraSmall();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getFull();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getLarge();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.foundation.shape.RoundedCornerShape getSmall();
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraLarge;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape ExtraSmall;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Full;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Large;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Medium;
+    property public final androidx.compose.ui.graphics.Shape None;
+    property public final androidx.compose.foundation.shape.RoundedCornerShape Small;
+    field public static final androidx.wear.compose.material3.ShapeDefaults INSTANCE;
+  }
+
+  @androidx.compose.runtime.Immutable public final class Shapes {
+    ctor public Shapes(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.wear.compose.material3.Shapes copy(optional androidx.compose.ui.graphics.Shape none, optional androidx.compose.ui.graphics.Shape extraSmall, optional androidx.compose.ui.graphics.Shape small, optional androidx.compose.ui.graphics.Shape medium, optional androidx.compose.ui.graphics.Shape large, optional androidx.compose.ui.graphics.Shape extraLarge, optional androidx.compose.ui.graphics.Shape full);
+    method public androidx.compose.ui.graphics.Shape getExtraLarge();
+    method public androidx.compose.ui.graphics.Shape getExtraSmall();
+    method public androidx.compose.ui.graphics.Shape getFull();
+    method public androidx.compose.ui.graphics.Shape getLarge();
+    method public androidx.compose.ui.graphics.Shape getMedium();
+    method public androidx.compose.ui.graphics.Shape getNone();
+    method public androidx.compose.ui.graphics.Shape getSmall();
+    property public final androidx.compose.ui.graphics.Shape extraLarge;
+    property public final androidx.compose.ui.graphics.Shape extraSmall;
+    property public final androidx.compose.ui.graphics.Shape full;
+    property public final androidx.compose.ui.graphics.Shape large;
+    property public final androidx.compose.ui.graphics.Shape medium;
+    property public final androidx.compose.ui.graphics.Shape none;
+    property public final androidx.compose.ui.graphics.Shape small;
+  }
+
+  public final class TextKt {
+    method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> getLocalTextStyle();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
+  }
+
+  @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 displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.wear.compose.material3.Typography copy(optional androidx.compose.ui.text.TextStyle displayExtraLarge, 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 bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle buttonMedium, optional androidx.compose.ui.text.TextStyle captionLarge, optional androidx.compose.ui.text.TextStyle captionMedium, optional androidx.compose.ui.text.TextStyle captionSmall);
+    method public androidx.compose.ui.text.TextStyle getBodyLarge();
+    method public androidx.compose.ui.text.TextStyle getBodyMedium();
+    method public androidx.compose.ui.text.TextStyle getBodySmall();
+    method public androidx.compose.ui.text.TextStyle getButtonMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionLarge();
+    method public androidx.compose.ui.text.TextStyle getCaptionMedium();
+    method public androidx.compose.ui.text.TextStyle getCaptionSmall();
+    method public androidx.compose.ui.text.TextStyle getDisplayExtraLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayLarge();
+    method public androidx.compose.ui.text.TextStyle getDisplayMedium();
+    method public androidx.compose.ui.text.TextStyle getDisplaySmall();
+    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 bodyLarge;
+    property public final androidx.compose.ui.text.TextStyle bodyMedium;
+    property public final androidx.compose.ui.text.TextStyle bodySmall;
+    property public final androidx.compose.ui.text.TextStyle buttonMedium;
+    property public final androidx.compose.ui.text.TextStyle captionLarge;
+    property public final androidx.compose.ui.text.TextStyle captionMedium;
+    property public final androidx.compose.ui.text.TextStyle captionSmall;
+    property public final androidx.compose.ui.text.TextStyle displayExtraLarge;
+    property public final androidx.compose.ui.text.TextStyle displayLarge;
+    property public final androidx.compose.ui.text.TextStyle displayMedium;
+    property public final androidx.compose.ui.text.TextStyle displaySmall;
+    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/build.gradle b/wear/compose/compose-material3/build.gradle
index fd5a497..8e0a522 100644
--- a/wear/compose/compose-material3/build.gradle
+++ b/wear/compose/compose-material3/build.gradle
@@ -40,7 +40,7 @@
     implementation(project(":compose:ui:ui-util"))
     implementation(project(":wear:compose:compose-foundation"))
     implementation(project(":wear:compose:compose-material-core"))
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(project(":compose:ui:ui-test"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconTest.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconTest.kt
new file mode 100644
index 0000000..729aace
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/IconTest.kt
@@ -0,0 +1,285 @@
+/*
+ * 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.layout.requiredSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Menu
+import androidx.compose.testutils.assertPixels
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Canvas
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
+import androidx.compose.ui.graphics.painter.BitmapPainter
+import androidx.compose.ui.graphics.painter.ColorPainter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalDensity
+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.assertContentDescriptionEquals
+import androidx.compose.ui.test.assertHeightIsEqualTo
+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.Density
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.test.filters.SdkSuppress
+import org.junit.Rule
+import org.junit.Test
+
+class IconTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val testTag = "TestText"
+
+    @Test
+    fun vector_materialIconSize_dimensions() {
+        val width = 24.dp
+        val height = 24.dp
+        val vector = Icons.Filled.Menu
+        rule
+            .setContentWithThemeForSizeAssertions {
+                Icon(vector, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @Test
+    fun vector_customIconSize_dimensions() {
+        val width = 35.dp
+        val height = 83.dp
+        val vector = ImageVector.Builder(
+            defaultWidth = width, defaultHeight = height,
+            viewportWidth = width.value, viewportHeight = height.value
+        ).build()
+        rule
+            .setContentWithThemeForSizeAssertions {
+                Icon(vector, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @Test
+    fun image_noIntrinsicSize_dimensions() {
+        val width = 24.dp
+        val height = 24.dp
+        rule
+            .setContentWithThemeForSizeAssertions {
+                val image = with(LocalDensity.current) {
+                    ImageBitmap(width.roundToPx(), height.roundToPx())
+                }
+
+                Icon(image, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @Test
+    fun image_withIntrinsicSize_dimensions() {
+        val width = 35.dp
+        val height = 83.dp
+
+        rule
+            .setContentWithThemeForSizeAssertions {
+                val image = with(LocalDensity.current) {
+                    ImageBitmap(width.roundToPx(), height.roundToPx())
+                }
+
+                Icon(image, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @Test
+    fun painter_noIntrinsicSize_dimensions() {
+        val width = 24.dp
+        val height = 24.dp
+        val painter = ColorPainter(Color.Red)
+
+        rule
+            .setContentWithThemeForSizeAssertions {
+                Icon(painter, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @Test
+    fun painter_withIntrinsicSize_dimensions() {
+        val width = 35.dp
+        val height = 83.dp
+
+        rule
+            .setContentWithThemeForSizeAssertions {
+                val image = with(LocalDensity.current) {
+                    ImageBitmap(width.roundToPx(), height.roundToPx())
+                }
+
+                val bitmapPainter = BitmapPainter(image)
+                Icon(bitmapPainter, null)
+            }
+            .assertWidthIsEqualTo(width)
+            .assertHeightIsEqualTo(height)
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun iconScalesToFitSize() {
+        // Image with intrinsic size of 24dp
+        val width = 24.dp
+        val height = 24.dp
+        var expectedIntSize: IntSize? = null
+
+        rule
+            .setContentWithTheme {
+                val image: ImageBitmap
+                with(LocalDensity.current) {
+                    image = createBitmapWithColor(
+                        this,
+                        width.roundToPx(),
+                        height.roundToPx(),
+                        Color.Red
+                    )
+                }
+                Icon(
+                    image,
+                    null,
+                    // Force Icon to be 50dp
+                    modifier = Modifier.requiredSize(50.dp).testTag(testTag),
+                    tint = Color.Unspecified
+                )
+                with(LocalDensity.current) {
+                    val dimension = 50.dp.roundToPx()
+                    expectedIntSize = IntSize(dimension, dimension)
+                }
+            }
+
+        rule.onNodeWithTag(testTag)
+            .captureToImage()
+            // The icon should be 50x50 and fill the whole size with red pixels
+            .assertPixels(expectedSize = expectedIntSize!!) {
+                Color.Red
+            }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun iconUnspecifiedTintColorIgnored() {
+        val width = 35.dp
+        val height = 83.dp
+
+        rule
+            .setContentWithTheme {
+                val image: ImageBitmap
+                with(LocalDensity.current) {
+                    image = createBitmapWithColor(
+                        this,
+                        width.roundToPx(),
+                        height.roundToPx(),
+                        Color.Red
+                    )
+                }
+                Icon(
+                    image,
+                    null,
+                    modifier = Modifier.testTag(testTag),
+                    tint = Color.Unspecified
+                )
+            }
+
+        // With no color provided for a tint, the icon should render the original pixels
+        rule.onNodeWithTag(testTag).captureToImage().assertPixels { Color.Red }
+    }
+
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun iconSpecifiedTintColorApplied() {
+        val width = 35.dp
+        val height = 83.dp
+
+        rule
+            .setContentWithTheme {
+                val image: ImageBitmap
+                with(LocalDensity.current) {
+                    image = createBitmapWithColor(
+                        this,
+                        width.roundToPx(),
+                        height.roundToPx(),
+                        Color.Red
+                    )
+                }
+                Icon(
+                    image,
+                    null,
+                    modifier = Modifier.testTag(testTag),
+                    tint = Color.Blue
+                )
+            }
+
+        // With a tint color provided, all pixels should be blue
+        rule.onNodeWithTag(testTag).captureToImage().assertPixels { Color.Blue }
+    }
+
+    @Test
+    fun defaultSemanticsWhenContentDescriptionProvided() {
+        rule
+            .setContent {
+                Icon(
+                    bitmap = ImageBitmap(100, 100),
+                    contentDescription = "qwerty",
+                    modifier = Modifier.testTag(testTag)
+                )
+            }
+
+        rule.onNodeWithTag(testTag)
+            .assertContentDescriptionEquals("qwerty")
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Image))
+    }
+
+    private fun createBitmapWithColor(
+        density: Density,
+        width: Int,
+        height: Int,
+        color: Color
+    ): ImageBitmap {
+        val size = Size(width.toFloat(), height.toFloat())
+        val image = ImageBitmap(width, height)
+        CanvasDrawScope().draw(
+            density,
+            LayoutDirection.Ltr,
+            Canvas(image),
+            size
+        ) {
+            drawRect(color)
+        }
+        return image
+    }
+}
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
new file mode 100644
index 0000000..f427c75
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+val BigTestMaxWidth = 5000.dp
+val BigTestMaxHeight = 5000.dp
+
+fun ComposeContentTestRule.setContentWithThemeForSizeAssertions(
+    parentMaxWidth: Dp = BigTestMaxWidth,
+    parentMaxHeight: Dp = BigTestMaxHeight,
+    useUnmergedTree: Boolean = false,
+    content: @Composable () -> Unit
+): SemanticsNodeInteraction {
+    setContent {
+        MaterialTheme {
+            Box {
+                Box(
+                    Modifier
+                        .sizeIn(
+                            maxWidth = parentMaxWidth,
+                            maxHeight = parentMaxHeight
+                        )
+                        .testTag("containerForSizeAssertion")
+                ) {
+                    content()
+                }
+            }
+        }
+    }
+
+    return onNodeWithTag("containerForSizeAssertion", useUnmergedTree)
+}
+
+fun ComposeContentTestRule.setContentWithTheme(
+    modifier: Modifier = Modifier,
+    composable: @Composable BoxScope.() -> Unit
+) {
+    setContent {
+        MaterialTheme {
+            Box(modifier = modifier, content = composable)
+        }
+    }
+}
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/TextTest.kt b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/TextTest.kt
new file mode 100644
index 0000000..a61944f
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidAndroidTest/kotlin/androidx/wear/compose/material3/TextTest.kt
@@ -0,0 +1,271 @@
+/*
+ * 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.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.test.junit4.createComposeRule
+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.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.unit.em
+import androidx.compose.ui.unit.sp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.lang.IllegalArgumentException
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TextTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    private val ExpectedTextStyle = TextStyle(
+        color = Color.Red,
+        fontSize = 32.sp,
+        fontStyle = FontStyle.Italic,
+        fontWeight = FontWeight.Normal,
+        fontFamily = FontFamily.Default,
+        letterSpacing = 1.sp,
+        textDecoration = TextDecoration.Underline,
+        textAlign = TextAlign.End,
+        lineHeight = 10.sp,
+    )
+
+    private val TestText = "TestText"
+
+    @Test
+    fun validateGreaterMinLinesResultsGreaterSize() {
+        var size1 = 0
+        var size2 = 0
+
+        rule.setContent {
+            CompositionLocalProvider(LocalContentColor provides Color.Blue) {
+                Column(Modifier.background(Color.White)) {
+                    Text(
+                        "Lorem ipsum",
+                        minLines = 1,
+                        maxLines = 3,
+                        onTextLayout = {
+                            size1 = it.size.height
+                        }
+                    )
+
+                    Text(
+                        "Lorem ipsum",
+                        minLines = 2,
+                        maxLines = 3,
+                        onTextLayout = {
+                            size2 = it.size.height
+                        }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(size2).isGreaterThan(size1)
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun validateMinLinesGreaterThanZero() {
+        rule.setContent {
+            Text(
+                TestText,
+                minLines = 0
+            )
+        }
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun validateMaxLinesGreaterThanMinLines() {
+        rule.setContent {
+            Text(
+                TestText,
+                minLines = 2,
+                maxLines = 1
+            )
+        }
+    }
+
+    @Test
+    fun colorParameterOverridesStyleColor() {
+        var textColor: Color? = null
+        val expectedColor = Color.Red
+
+        rule.setContent {
+            CompositionLocalProvider(LocalContentColor provides Color.Blue) {
+                ProvideTextStyle(ExpectedTextStyle) {
+                    Box(Modifier.background(Color.White)) {
+                        Text(
+                            TestText,
+                            color = expectedColor,
+                            onTextLayout = {
+                                textColor = it.layoutInput.style.color
+                            }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(textColor).isEqualTo(expectedColor)
+        }
+    }
+
+    @Test
+    fun styleColorOverridesLocalContentColor() {
+        var textColor: Color? = null
+
+        rule.setContent {
+            CompositionLocalProvider(LocalContentColor provides Color.Blue) {
+                ProvideTextStyle(ExpectedTextStyle) {
+                    Box(Modifier.background(Color.White)) {
+                        Text(
+                            TestText,
+                            onTextLayout = {
+                                textColor = it.layoutInput.style.color
+                            }
+                        )
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(textColor).isEqualTo(ExpectedTextStyle.color)
+        }
+    }
+
+    @Test
+    fun usesLocalContentColorAsFallback() {
+        var textColor: Color? = null
+
+        rule.setContent {
+            CompositionLocalProvider(LocalContentColor provides Color.Blue) {
+                Box(Modifier.background(Color.White)) {
+                    Text(
+                        TestText,
+                        onTextLayout = {
+                            textColor = it.layoutInput.style.color
+                        }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(textColor).isEqualTo(Color.Blue)
+        }
+    }
+
+    @Test
+    fun inheritsTextStyle() {
+        var fontSize: TextUnit? = null
+        var fontStyle: FontStyle? = null
+        var fontWeight: FontWeight? = null
+        var fontFamily: FontFamily? = null
+        var letterSpacing: TextUnit? = null
+        var textDecoration: TextDecoration? = null
+        var textAlign: TextAlign? = null
+
+        rule.setContent {
+            ProvideTextStyle(ExpectedTextStyle) {
+                Box(Modifier.background(Color.White)) {
+                    Text(
+                        TestText,
+                        onTextLayout = {
+                            fontSize = it.layoutInput.style.fontSize
+                            fontStyle = it.layoutInput.style.fontStyle
+                            fontWeight = it.layoutInput.style.fontWeight
+                            fontFamily = it.layoutInput.style.fontFamily
+                            letterSpacing = it.layoutInput.style.letterSpacing
+                            textDecoration = it.layoutInput.style.textDecoration
+                            textAlign = it.layoutInput.style.textAlign
+                        }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(fontSize).isEqualTo(ExpectedTextStyle.fontSize)
+            Truth.assertThat(fontStyle).isEqualTo(ExpectedTextStyle.fontStyle)
+            Truth.assertThat(fontWeight).isEqualTo(ExpectedTextStyle.fontWeight)
+            Truth.assertThat(fontFamily).isEqualTo(ExpectedTextStyle.fontFamily)
+            Truth.assertThat(letterSpacing).isEqualTo(ExpectedTextStyle.letterSpacing)
+            Truth.assertThat(textDecoration).isEqualTo(ExpectedTextStyle.textDecoration)
+            Truth.assertThat(textAlign).isEqualTo(ExpectedTextStyle.textAlign)
+        }
+    }
+
+    @Test
+    fun setsParametersExplicitly() {
+        // Test to ensure that when parameter is set explicitly, then this parameter will be used
+        var textAlign: TextAlign? = null
+        var fontSize: TextUnit? = null
+        var fontStyle: FontStyle? = null
+        var letterSpacing: TextUnit? = null
+        val expectedColor = Color.Red
+        val expectedTextAlign = TextAlign.End
+        val expectedFontSize = 32.sp
+        val expectedFontStyle = FontStyle.Italic
+        val expectedLetterSpacing = 1.em
+
+        rule.setContent {
+            ProvideTextStyle(ExpectedTextStyle) {
+                Box(Modifier.background(Color.White)) {
+                    Text(
+                        TestText,
+                        color = expectedColor,
+                        textAlign = expectedTextAlign,
+                        fontSize = expectedFontSize,
+                        fontStyle = expectedFontStyle,
+                        letterSpacing = expectedLetterSpacing,
+                        onTextLayout = {
+                            textAlign = it.layoutInput.style.textAlign
+                            fontSize = it.layoutInput.style.fontSize
+                            fontStyle = it.layoutInput.style.fontStyle
+                            letterSpacing = it.layoutInput.style.letterSpacing
+                        }
+                    )
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(textAlign).isEqualTo(expectedTextAlign)
+            Truth.assertThat(fontSize).isEqualTo(expectedFontSize)
+            Truth.assertThat(fontStyle).isEqualTo(expectedFontStyle)
+            Truth.assertThat(letterSpacing).isEqualTo(expectedLetterSpacing)
+        }
+    }
+}
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt
new file mode 100644
index 0000000..1216db9
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt
@@ -0,0 +1,456 @@
+/*
+ * 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.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.takeOrElse
+
+/**
+ * A [ColorScheme] holds all the named color parameters for a [MaterialTheme].
+ *
+ * Color schemes are designed to be harmonious, ensure accessible text, and distinguish UI
+ * elements and surfaces from one another.
+ *
+ * The Material color system and custom schemes provide default values for color as a starting point
+ * for customization.
+ *
+ * To learn more about color schemes,
+ * see [Material Design Color System](https://m3.material.io/styles/color/the-color-system/color-roles).
+ *
+ * @property primary The primary color is the color displayed most frequently across your app’s
+ * screens and components.
+ * @property primaryDim is less prominent than [primary] for component backgrounds
+ * @property primaryContainer is a standout container color for key components.
+ * @property onPrimary Color used for text and icons displayed on top of the primary color.
+ * @property onPrimaryContainer The color (and state variants) that should be used for content on
+ * top of [primaryContainer].
+ * @property secondary The secondary color provides more ways to accent and distinguish your
+ * product.
+ * @property secondaryDim is less prominent than [secondary] for component backgrounds.
+ * @property secondaryContainer A tonal color to be used in containers.
+ * @property onSecondary Color used for text and icons displayed on top of the secondary color.
+ * @property onSecondaryContainer The color (and state variants) that should be used for content on
+ * top of [secondaryContainer].
+ * @property tertiary The tertiary color that can be used to balance primary and secondary
+ * colors, or bring heightened attention to an element.
+ * @property tertiaryDim A less prominent tertiary color that can be used to balance
+ * primary and secondary colors, or bring heightened attention to an element.
+ * @property tertiaryContainer A tonal color to be used in containers.
+ * @property onTertiary Color used for text and icons displayed on top of the tertiary color.
+ * @property onTertiaryContainer The color (and state variants) that should be used for content on
+ * top of [tertiaryContainer].
+ * @property surfaceDim A surface color used for large containment components
+ * such as Card and Button with low prominence.
+ * @property surface The main surface color that affect surfaces of components with large
+ * containment areas, such as Card and Button.
+ * @property surfaceBright A surface color used for large containment components
+ * such Card and Button with high prominence.
+ * @property onSurface Color used for text and icons displayed on top of the surface color.
+ * @property onSurfaceVariant The color for secondary text and icons on top of
+ * [surface].
+ * @property outline The main color for primary outline components.
+ * The outline color role adds contrast for accessibility purposes.
+ * @property outlineVariant The secondary color for secondary outline components.
+ * @property background The background color that appears behind other content.
+ * @property onBackground Color used for text and icons displayed on top of the background color.
+ * @property error The error color is used to indicate errors.
+ * @property onError Color used for text and icons displayed on top of the error color.
+ */@Stable
+public class ColorScheme(
+    primary: Color = Color(0xFFD3E3FD),
+    primaryDim: Color = Color(0xFFA8C7FA),
+    primaryContainer: Color = Color(0xFF04409F),
+    onPrimary: Color = Color(0xFF001944),
+    onPrimaryContainer: Color = Color(0xFFD3E3FD),
+    secondary: Color = Color(0xFFC2E7FF),
+    secondaryDim: Color = Color(0xFF7FCFFF),
+    secondaryContainer: Color = Color(0xFF004A77),
+    onSecondary: Color = Color(0xFF001D35),
+    onSecondaryContainer: Color = Color(0xFFC2E7FF),
+    tertiary: Color = Color(0xFFC3EDCF),
+    tertiaryDim: Color = Color(0xFF73DC92),
+    tertiaryContainer: Color = Color(0xFF0F5223),
+    onTertiary: Color = Color(0xFF02210C),
+    onTertiaryContainer: Color = Color(0xFFC3EDCF),
+    surfaceDim: Color = Color(0xFF252626),
+    surface: Color = Color(0xFF303030),
+    surfaceBright: Color = Color(0xFF474747),
+    onSurface: Color = Color(0xFFF2F2F2),
+    onSurfaceVariant: Color = Color(0xFFC4C7C5),
+    outline: Color = Color(0xFF8E918F),
+    outlineVariant: Color = Color(0xFF5C5F5E),
+    background: Color = Color.Black,
+    onBackground: Color = Color(0xFFFFFFFF),
+    error: Color = Color(0xFFFD7267),
+    onError: Color = Color(0xFF410002),
+) {
+    /**
+     * [primary] is the main color used across screens and components
+     */
+    public var primary: Color by mutableStateOf(primary)
+        internal set
+
+    /**
+     * [primaryDim] is less prominent than [primary] for component backgrounds
+     */
+    public var primaryDim: Color by mutableStateOf(primaryDim)
+        internal set
+
+    /**
+     * [primaryContainer] is a standout container color for key components
+     */
+    public var primaryContainer: Color by mutableStateOf(primaryContainer)
+        internal set
+
+    /**
+     * [onPrimary] is for text and icons shown against the Primary and primaryDim colors
+     */
+    public var onPrimary: Color by mutableStateOf(onPrimary)
+        internal set
+
+    /**
+     * [onPrimaryContainer] is a contrast-passing color shown against the primaryContainer
+     */
+    public var onPrimaryContainer: Color by mutableStateOf(onPrimaryContainer)
+        internal set
+
+    /**
+     * [secondary] is an accent color used across screens and components
+     */
+    public var secondary: Color by mutableStateOf(secondary)
+        internal set
+
+    /**
+     * [secondaryDim] is less prominent than [secondary] for component backgrounds
+     */
+    public var secondaryDim: Color by mutableStateOf(secondaryDim)
+
+    /**
+     * [secondaryContainer] is a less prominent container color than [primaryContainer],
+     * for components like tonal buttons
+     */
+    public var secondaryContainer: Color by mutableStateOf(secondaryContainer)
+        internal set
+
+    /**
+     * [onSecondary] is for text and icons shown against the Secondary and SecondaryDim colors
+     */
+    public var onSecondary: Color by mutableStateOf(onSecondary)
+        internal set
+
+    /**
+     * [onSecondaryContainer] is a contrast-passing color shown against the secondaryContainer
+     */
+    public var onSecondaryContainer: Color by mutableStateOf(onSecondaryContainer)
+        internal set
+
+    /**
+     * [tertiary] is a complementary color to create contrast and draw attention to elements
+     */
+    public var tertiary: Color by mutableStateOf(tertiary)
+        internal set
+
+    /**
+     * [tertiaryDim] is less prominent than [tertiary] for component backgrounds
+     */
+    public var tertiaryDim: Color by mutableStateOf(tertiaryDim)
+        internal set
+
+    /**
+     * [tertiaryContainer] is a contrasting container color for components
+     */
+    public var tertiaryContainer: Color by mutableStateOf(tertiaryContainer)
+        internal set
+
+    /**
+     * [onTertiary] is for text and icons shown against the Tertiary and tertiaryDim colors
+     */
+    public var onTertiary: Color by mutableStateOf(onTertiary)
+        internal set
+
+    /**
+     * [onTertiaryContainer] is a contrast-passing color shown against the tertiaryContainer
+     */
+    public var onTertiaryContainer: Color by mutableStateOf(onTertiaryContainer)
+        internal set
+
+    /**
+     * [surfaceDim] is a surface color used for large containment components, with the
+     * lowest prominence behind Surface and surfaceBright
+     */
+    public var surfaceDim: Color by mutableStateOf(surfaceDim)
+        internal set
+
+    /**
+     * [surface] is the main color for large containment components like card and button backgrounds
+     */
+    public var surface: Color by mutableStateOf(surface)
+        internal set
+
+    /**
+     * [surfaceBright] is a surface color used for large containment components, with
+     * the highest prominence, ahead of Surface and surfaceDim
+     */
+    public var surfaceBright: Color by mutableStateOf(surfaceBright)
+        internal set
+
+    /**
+     * [onSurface] for primary text and icons shown against the
+     * [surface], [surfaceDim] and [surfaceBright]
+     */
+    public var onSurface: Color by mutableStateOf(onSurface)
+        internal set
+
+    /**
+     * [onSurfaceVariant] for secondary text and icons on
+     * [surface], [surfaceDim] and [surfaceBright]
+     */
+    public var onSurfaceVariant: Color by mutableStateOf(onSurfaceVariant)
+        internal set
+
+    /**
+     * [outline] is the main color for primary outline components
+     */
+    public var outline: Color by mutableStateOf(outline)
+        internal set
+
+    /**
+     * [outlineVariant] is the secondary color for secondary outline components
+     */
+    public var outlineVariant: Color by mutableStateOf(outlineVariant)
+        internal set
+
+    /**
+     * [background] is the static color used behind all texts and components
+     */
+    public var background: Color by mutableStateOf(background)
+        internal set
+
+    /**
+     * [onBackground] is used for text and icons shown against the background color
+     */
+    public var onBackground: Color by mutableStateOf(onBackground)
+        internal set
+
+    /**
+     * [error] indicates errors and emergency states
+     */
+    public var error: Color by mutableStateOf(error)
+        internal set
+
+    /**
+     * [onError] is used for text and icons on the error color
+     */
+    public var onError: Color by mutableStateOf(onError)
+        internal set
+
+    /**
+     * Returns a copy of this Colors, optionally overriding some of the values.
+     */
+    public fun copy(
+        primary: Color = this.primary,
+        primaryDim: Color = this.primaryDim,
+        primaryContainer: Color = this.primaryContainer,
+        onPrimary: Color = this.onPrimary,
+        onPrimaryContainer: Color = this.onPrimaryContainer,
+        secondary: Color = this.secondary,
+        secondaryDim: Color = this.secondaryDim,
+        secondaryContainer: Color = this.secondaryContainer,
+        onSecondary: Color = this.onSecondary,
+        onSecondaryContainer: Color = this.onSecondaryContainer,
+        tertiary: Color = this.tertiary,
+        tertiaryDim: Color = this.tertiaryDim,
+        tertiaryContainer: Color = this.tertiaryContainer,
+        onTertiary: Color = this.onTertiary,
+        onTertiaryContainer: Color = this.onTertiaryContainer,
+        surfaceDim: Color = this.surfaceDim,
+        surface: Color = this.surface,
+        surfaceBright: Color = this.surfaceBright,
+        onSurface: Color = this.onSurface,
+        onSurfaceVariant: Color = this.onSurfaceVariant,
+        outline: Color = this.outline,
+        outlineVariant: Color = this.outlineVariant,
+        background: Color = this.background,
+        onBackground: Color = this.onBackground,
+        error: Color = this.error,
+        onError: Color = this.onError
+    ): ColorScheme = ColorScheme(
+        primary = primary,
+        primaryDim = primaryDim,
+        primaryContainer = primaryContainer,
+        onPrimary = onPrimary,
+        onPrimaryContainer = onPrimaryContainer,
+        secondary = secondary,
+        secondaryDim = secondaryDim,
+        secondaryContainer = secondaryContainer,
+        onSecondary = onSecondary,
+        onSecondaryContainer = onSecondaryContainer,
+        tertiary = tertiary,
+        tertiaryDim = tertiaryDim,
+        tertiaryContainer = tertiaryContainer,
+        onTertiary = onTertiary,
+        onTertiaryContainer = onTertiaryContainer,
+        surfaceDim = surfaceDim,
+        surface = surface,
+        surfaceBright = surfaceBright,
+        onSurface = onSurface,
+        onSurfaceVariant = onSurfaceVariant,
+        outline = outline,
+        outlineVariant = outlineVariant,
+        background = background,
+        onBackground = onBackground,
+        error = error,
+        onError = onError
+    )
+
+    override fun toString(): String {
+        return "Colors(" +
+            "primary=$primary, " +
+            "primaryDim=$primaryDim, " +
+            "primaryContainer=$primaryContainer, " +
+            "onPrimary=$onPrimary, " +
+            "onPrimaryContainer=$onPrimaryContainer, " +
+            "secondary=$secondary, " +
+            "secondaryDim=$secondaryDim, " +
+            "secondaryContainer=$secondaryContainer, " +
+            "onSecondary=$onSecondary, " +
+            "onSecondaryContainer=$onSecondaryContainer, " +
+            "tertiary=$tertiary, " +
+            "tertiaryDim=$tertiaryDim, " +
+            "tertiaryContainer=$tertiaryContainer, " +
+            "onTertiary=$onTertiary, " +
+            "onTertiaryContainer=$onTertiaryContainer, " +
+            "surfaceDim=$surfaceDim, " +
+            "surface=$surface, " +
+            "surfaceBright=$surfaceBright, " +
+            "onSurface=$onSurface, " +
+            "onSurfaceVariant=$onSurfaceVariant, " +
+            "outline=$outline, " +
+            "outlineVariant=$outlineVariant, " +
+            "background=$background, " +
+            "onBackground=$onBackground, " +
+            "error=$error, " +
+            "onError=$onError" +
+            ")"
+    }
+}
+
+/**
+ * The Material color system contains pairs of colors that are typically used for the background
+ * and content color inside a component. For example, a Button typically uses `primary` for its
+ * background, and `onPrimary` for the color of its content (usually text or iconography).
+ *
+ * This function tries to match the provided [backgroundColor] to a 'background' color in this
+ * [ColorScheme], and then will return the corresponding color used for content. For example, when
+ * [backgroundColor] is [ColorScheme.primary], this will return [ColorScheme.onPrimary].
+ *
+ * If [backgroundColor] does not match a background color in the theme, this will return
+ * [Color.Unspecified].
+ *
+ * @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
+ * the theme's [ColorScheme], then returns [Color.Unspecified].
+ *
+ * @see contentColorFor
+ */
+public fun ColorScheme.contentColorFor(backgroundColor: Color): Color {
+    return when (backgroundColor) {
+        primary, primaryDim -> onPrimary
+        primaryContainer -> onPrimaryContainer
+        secondary, secondaryDim -> onSecondary
+        secondaryContainer -> onSecondaryContainer
+        tertiary, tertiaryDim -> onTertiary
+        tertiaryContainer -> onTertiaryContainer
+        surface, surfaceDim, surfaceBright -> onSurface
+        background -> onBackground
+        error -> onError
+        else -> Color.Unspecified
+    }
+}
+
+/**
+ * The Material color system contains pairs of colors that are typically used for the background
+ * and content color inside a component. For example, a Button typically uses `primary` for its
+ * background, and `onPrimary` for the color of its content (usually text or iconography).
+ *
+ * This function tries to match the provided [backgroundColor] to a 'background' color in this
+ * [ColorScheme], and then will return the corresponding color used for content. For example, when
+ * [backgroundColor] is [ColorScheme.primary], this will return [ColorScheme.onPrimary].
+ *
+ * If [backgroundColor] does not match a background color in the theme, this will return
+ * the current value of [LocalContentColor] as a best-effort color.
+ *
+ * @return the matching content color for [backgroundColor]. If [backgroundColor] is not present in
+ * the theme's [ColorScheme], then returns the current value of [LocalContentColor].
+ *
+ * @see ColorScheme.contentColorFor
+ */
+@Composable
+@ReadOnlyComposable
+public fun contentColorFor(backgroundColor: Color): Color =
+    MaterialTheme.colorScheme
+        .contentColorFor(backgroundColor)
+        .takeOrElse { LocalContentColor.current }
+
+/**
+ * Updates the internal values of the given [ColorScheme] with values from the [other] [ColorScheme]. This
+ * allows efficiently updating a subset of [ColorScheme], without recomposing every composable that
+ * consumes values from [LocalColors].
+ *
+ * Because [ColorScheme] is very wide-reaching, and used by many expensive composables in the
+ * hierarchy, providing a new value to [LocalColors] causes every composable consuming
+ * [LocalColors] to recompose, which is prohibitively expensive in cases such as animating one
+ * color in the theme. Instead, [ColorScheme] is internally backed by [mutableStateOf], and this
+ * function mutates the internal state of [this] to match values in [other]. This means that any
+ * changes will mutate the internal state of [this], and only cause composables that are reading
+ * the specific changed value to recompose.
+ */
+internal fun ColorScheme.updateColorSchemeFrom(other: ColorScheme) {
+    primary = other.primary
+    primaryDim = other.primaryDim
+    primaryContainer = other.primaryContainer
+    onPrimary = other.onPrimary
+    onPrimaryContainer = other.onPrimaryContainer
+    secondary = other.secondary
+    secondaryDim = other.secondaryDim
+    secondaryContainer = other.secondaryContainer
+    onSecondary = other.onSecondary
+    onSecondaryContainer = other.onSecondaryContainer
+    tertiary = other.tertiary
+    tertiaryDim = other.tertiaryDim
+    tertiaryContainer = other.tertiaryContainer
+    onTertiary = other.onTertiary
+    onTertiaryContainer = other.onTertiaryContainer
+    surfaceDim = other.surfaceDim
+    surface = other.surface
+    surfaceBright = other.surfaceBright
+    onSurface = other.onSurface
+    onSurfaceVariant = other.onSurfaceVariant
+    outline = other.outline
+    outlineVariant = other.outlineVariant
+    background = other.background
+    onBackground = other.onBackground
+    error = other.error
+    onError = other.onError
+}
+
+internal val LocalColors = staticCompositionLocalOf<ColorScheme> { ColorScheme() }
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt
new file mode 100644
index 0000000..91e559b
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentAlpha.kt
@@ -0,0 +1,124 @@
+/*
+ * 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.runtime.Composable
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.ui.graphics.luminance
+
+/**
+ * CompositionLocal containing the preferred content alpha for a given position in the hierarchy.
+ * This alpha is used for text and iconography ([Text] and Icon) to emphasize / de-emphasize
+ * different parts of a component. See the Material guide on
+ * [Text Legibility](https://material.io/design/color/text-legibility.html) for more information on
+ * alpha levels used by text and iconography.
+ *
+ * See [ContentAlpha] for the default levels used by most Material components.
+ *
+ * [MaterialTheme] sets this to [ContentAlpha.high] by default, as this is the default alpha for
+ * body text.
+ *
+ */
+public val LocalContentAlpha: ProvidableCompositionLocal<Float> = compositionLocalOf { 1f }
+
+/**
+ * Default alpha levels used by Material components.
+ *
+ * See [LocalContentAlpha].
+ */
+public object ContentAlpha {
+    /**
+     * A high level of content alpha, used to represent high emphasis text.
+     */
+    public val high: Float
+        @Composable
+        get() = contentAlpha(
+            highContrastAlpha = HighContrastContentAlpha.high,
+            lowContrastAlpha = LowContrastContentAlpha.high
+        )
+
+    /**
+     * A medium level of content alpha, used to represent medium emphasis text such as
+     * placeholder text.
+     */
+    public val medium: Float
+        @Composable
+        get() = contentAlpha(
+            highContrastAlpha = HighContrastContentAlpha.medium,
+            lowContrastAlpha = LowContrastContentAlpha.medium
+        )
+
+    /**
+     * A low level of content alpha used to represent disabled components, such as text in a
+     * disabled Button.
+     */
+    public val disabled: Float
+        @Composable
+        get() = contentAlpha(
+            highContrastAlpha = HighContrastContentAlpha.disabled,
+            lowContrastAlpha = LowContrastContentAlpha.disabled
+        )
+
+    /**
+     * This default implementation uses separate alpha levels depending on the luminance of the
+     * incoming color, and whether the theme is light or dark. This is to ensure correct contrast
+     * and accessibility on all surfaces.
+     *
+     * See [HighContrastContentAlpha] and [LowContrastContentAlpha] for what the levels are
+     * used for, and under what circumstances.
+     */
+    @Composable
+    private fun contentAlpha(
+        /*@FloatRange(from = 0.0, to = 1.0)*/
+        highContrastAlpha: Float,
+        /*@FloatRange(from = 0.0, to = 1.0)*/
+        lowContrastAlpha: Float
+    ): Float {
+        val contentColor = LocalContentColor.current
+        return if (contentColor.luminance() < 0.5) highContrastAlpha else lowContrastAlpha
+    }
+}
+
+/**
+ * Alpha levels for high luminance content in light theme, or low luminance content in dark theme.
+ *
+ * This content will typically be placed on colored surfaces, so it is important that the
+ * contrast here is higher to meet accessibility standards, and increase legibility.
+ *
+ * These levels are typically used for text / iconography in primary colored tabs /
+ * bottom navigation / etc.
+ */
+private object HighContrastContentAlpha {
+    const val high: Float = 1.00f
+    const val medium: Float = 0.74f
+    const val disabled: Float = 0.38f
+}
+
+/**
+ * Alpha levels for low luminance content in light theme, or high luminance content in dark theme.
+ *
+ * This content will typically be placed on grayscale surfaces, so the contrast here can be lower
+ * without sacrificing accessibility and legibility.
+ *
+ * These levels are typically used for body text on the main surface (white in light theme, grey
+ * in dark theme) and text / iconography in surface colored tabs / bottom navigation / etc.
+ */
+private object LowContrastContentAlpha {
+    const val high: Float = 0.87f
+    const val medium: Float = 0.60f
+    const val disabled: Float = 0.38f
+}
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentColor.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentColor.kt
new file mode 100644
index 0000000..f05bed6
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ContentColor.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.ui.graphics.Color
+
+/**
+ * CompositionLocal containing the preferred content color for a given position in the hierarchy.
+ * This typically represents the `on` color for a color in [ColorScheme]. For example, if the background
+ * color is [ColorScheme.surface], this color is typically set to [ColorScheme.onSurface].
+ *
+ * This color should be used for any typography / iconography, to ensure that the color of these
+ * adjusts when the background color changes. For example, on a dark background, text should be
+ * light, and on a light background, text should be dark.
+ *
+ * Defaults to [Color.White] if no color has been explicitly set.
+ */
+public val LocalContentColor: ProvidableCompositionLocal<Color> = compositionLocalOf { Color.White }
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Icon.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Icon.kt
new file mode 100644
index 0000000..2113a27
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Icon.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.BitmapPainter
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+
+/**
+ * Icon component that draws [imageVector] using [tint], defaulting to [LocalContentColor]. For a
+ * clickable icon, see Button.
+ *
+ * @param imageVector [ImageVector] to draw inside this Icon
+ * @param contentDescription Text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * @param modifier Optional [Modifier] for this Icon
+ * @param tint Tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no
+ *  tint is applied
+ */
+@Composable
+fun Icon(
+    imageVector: ImageVector,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+) {
+    Icon(
+        painter = rememberVectorPainter(imageVector),
+        contentDescription = contentDescription,
+        modifier = modifier,
+        tint = tint
+    )
+}
+
+/**
+ * Icon component that draws [bitmap] using [tint], defaulting to [LocalContentColor]. For a
+ * clickable icon, see Button.
+ *
+ * @param bitmap [ImageBitmap] to draw inside this Icon
+ * @param contentDescription Text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * @param modifier Optional [Modifier] for this Icon
+ * @param tint Tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no
+ *  tint is applied
+ */
+@Composable
+fun Icon(
+    bitmap: ImageBitmap,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+) {
+    val painter = remember(bitmap) { BitmapPainter(bitmap) }
+    Icon(
+        painter = painter,
+        contentDescription = contentDescription,
+        modifier = modifier,
+        tint = tint
+    )
+}
+
+/**
+ * Icon component that draws a [painter] using [tint], defaulting to [LocalContentColor]. For a
+ * clickable icon, see Button.
+ *
+ * @param painter [Painter] to draw inside this Icon
+ * @param contentDescription Text used by accessibility services to describe what this icon
+ * represents. This should always be provided unless this icon is used for decorative purposes,
+ * and does not represent a meaningful action that a user can take. This text should be
+ * localized, such as by using [androidx.compose.ui.res.stringResource] or similar
+ * @param modifier Optional [Modifier] for this Icon
+ * @param tint Tint to be applied to [painter]. If [Color.Unspecified] is provided, then no
+ *  tint is applied
+ */
+@Composable
+fun Icon(
+    painter: Painter,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+) {
+    androidx.wear.compose.materialcore.Icon(
+        painter = painter,
+        contentDescription = contentDescription,
+        tint = tint,
+        modifier = modifier
+    )
+}
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTextSelectionColors.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTextSelectionColors.kt
new file mode 100644
index 0000000..8939ee4
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTextSelectionColors.kt
@@ -0,0 +1,239 @@
+/*
+ * 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.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.graphics.luminance
+import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.foundation.text.selection.TextSelectionColors
+import kotlin.math.max
+import kotlin.math.min
+
+/**
+ * Remembers a [TextSelectionColors] based on [colorScheme]. The handle color will be
+ * [ColorScheme.primary] and the background color will be [ColorScheme.primary] with alpha applied.
+ *
+ * See [calculateSelectionBackgroundColor].
+ */
+@Composable
+internal fun rememberTextSelectionColors(colorScheme: ColorScheme): TextSelectionColors {
+    val primaryColor = colorScheme.primary
+    val backgroundColor = colorScheme.background
+    // Test with ContentAlpha.medium to ensure that the selection background is accessible in the
+    // 'worst case' scenario. We explicitly don't test with ContentAlpha.disabled, as disabled
+    // text shouldn't be selectable / is noted as disabled for accessibility purposes.
+    val textColorWithLowestAlpha = colorScheme.contentColorFor(backgroundColor)
+        .takeOrElse {
+            LocalContentColor.current
+        }.copy(
+            alpha = ContentAlpha.medium
+        )
+    return remember(primaryColor, backgroundColor, textColorWithLowestAlpha) {
+        TextSelectionColors(
+            handleColor = colorScheme.primary,
+            backgroundColor = calculateSelectionBackgroundColor(
+                selectionColor = primaryColor,
+                textColor = textColorWithLowestAlpha,
+                backgroundColor = backgroundColor
+            )
+        )
+    }
+}
+
+/**
+ * Best-effort calculates a color (with alpha) for the selection background that (if possible)
+ * will have at least [DesiredContrastRatio] with [textColor], when the selection background
+ * is on top of [backgroundColor].
+ *
+ * Since this is a minimum contrast ratio, [textColor] should have the lowest alpha that
+ * may be applied to content so we can ensure that the selection background color is accessible
+ * in that worst-case scenario for contrast.
+ *
+ * @param selectionColor the 'raw' (without alpha) selection color that we should search alpha for
+ * @param textColor the color of text with minimal alpha applied to test for contrast with
+ * @param backgroundColor the color of the background that the selection color will typically be
+ * placed against
+ *
+ * @return a resulting [selectionColor] with alpha applied that results in acceptable contrast
+ * (if possible with the values for [selectionColor], [textColor] and [backgroundColor]).
+ */
+/*@VisibleForTesting*/
+internal fun calculateSelectionBackgroundColor(
+    selectionColor: Color,
+    textColor: Color,
+    backgroundColor: Color
+): Color {
+    val maximumContrastRatio = calculateContrastRatio(
+        selectionColor = selectionColor,
+        selectionColorAlpha = DefaultSelectionBackgroundAlpha,
+        textColor = textColor,
+        backgroundColor = backgroundColor
+    )
+
+    val minimumContrastRatio = calculateContrastRatio(
+        selectionColor = selectionColor,
+        selectionColorAlpha = MinimumSelectionBackgroundAlpha,
+        textColor = textColor,
+        backgroundColor = backgroundColor
+    )
+
+    val alpha = when {
+        // If the default alpha has enough contrast, use that
+        maximumContrastRatio >= DesiredContrastRatio -> DefaultSelectionBackgroundAlpha
+        // If the minimum alpha still does not have enough contrast, just use the minimum and return
+        minimumContrastRatio < DesiredContrastRatio -> MinimumSelectionBackgroundAlpha
+        else -> binarySearchForAccessibleSelectionColorAlpha(
+            selectionColor = selectionColor,
+            textColor = textColor,
+            backgroundColor = backgroundColor
+        )
+    }
+
+    return selectionColor.copy(alpha = alpha)
+}
+
+/**
+ * Binary searches for the highest alpha for selection color that results in a contrast ratio at
+ * least equal to and within 1% of [DesiredContrastRatio].
+ *
+ * The resulting alpha will be within the range of [MinimumSelectionBackgroundAlpha] and
+ * [DefaultSelectionBackgroundAlpha] - since not all values for [selectionColor], [textColor] and
+ * [backgroundColor] can be guaranteed to produce an accessible contrast ratio, this is a
+ * best-effort attempt and [MinimumSelectionBackgroundAlpha] might still not produce an
+ * accessible contrast ratio. In this case developers are encouraged to manually choose a
+ * different color for selection that _is_ accessible with their chosen content and background
+ * colors.
+ *
+ * Caps the number of attempts at 7 for performance and to avoid infinite searching when there is
+ * no value that results in an accessible contrast ratio. Because alpha is limited to [0,1], 7
+ * steps results in a precision of ~0.01, since log2(1/0.01) ≈ 7.
+ *
+ * Note: binary searching here is chosen since it is not possible to 'solve' for alpha, since the
+ * transformation from color -> contrast ratio is not linear (the gamma exponent for sRGB colors
+ * is 2.4). We can approximate this to 2, but this results in not that accurate solutions, and we
+ * need to guarantee that they are at least above [DesiredContrastRatio] - falling just below is
+ * not an acceptable result.
+ *
+ * @param selectionColor the 'raw' (without alpha) selection color that we should search alpha for
+ * @param textColor the color of text with minimal alpha applied to test for contrast with
+ * @param backgroundColor the color of the background that the selection color will typically be
+ * placed against
+ */
+private fun binarySearchForAccessibleSelectionColorAlpha(
+    selectionColor: Color,
+    textColor: Color,
+    backgroundColor: Color
+): Float {
+    var attempts = 0
+    val maxAttempts = 7
+
+    var lowAlpha = MinimumSelectionBackgroundAlpha
+    var alpha = DefaultSelectionBackgroundAlpha
+    var highAlpha = DefaultSelectionBackgroundAlpha
+
+    while (attempts < maxAttempts) {
+        val contrastRatio = calculateContrastRatio(
+            selectionColor = selectionColor,
+            selectionColorAlpha = alpha,
+            textColor = textColor,
+            backgroundColor = backgroundColor
+        )
+
+        // Percentage error of the calculated contrast compared to the actual contrast. Positive
+        // numbers here mean we have higher contrast than needed.
+        val percentageError = (contrastRatio / DesiredContrastRatio) - 1f
+        when {
+            // Contrast is at most 1% above the guideline, return
+            percentageError in 0f..0.01f -> break
+            // Contrast too low, decrease alpha
+            percentageError < 0f -> highAlpha = alpha
+            // Contrast higher than required, increase alpha
+            else -> lowAlpha = alpha
+        }
+        alpha = (highAlpha + lowAlpha) / 2f
+        attempts++
+    }
+
+    return alpha
+}
+
+/**
+ * Calculates the contrast ratio of [textColor] against [selectionColor] with
+ * [selectionColorAlpha], all on top of [backgroundColor].
+ *
+ * Both the [selectionColor] and [textColor] will be composited to handle transparency.
+ *
+ * @param selectionColor the 'raw' (without alpha) selection color that we should search alpha for
+ * @param selectionColorAlpha the alpha for [selectionColor] to test contrast with
+ * @param textColor the color of text with minimal alpha applied to test for contrast with
+ * @param backgroundColor the color of the background that the selection color will typically be
+ * placed against
+ *
+ * @return the contrast ratio as a value between 1 and 21. See [calculateContrastRatio]
+ */
+private fun calculateContrastRatio(
+    selectionColor: Color,
+    selectionColorAlpha: Float,
+    textColor: Color,
+    backgroundColor: Color
+): Float {
+    val compositeBackground = selectionColor.copy(alpha = selectionColorAlpha)
+        .compositeOver(backgroundColor)
+    val compositeTextColor = textColor.compositeOver(compositeBackground)
+    return calculateContrastRatio(compositeTextColor, compositeBackground)
+}
+
+/**
+ * Calculates the contrast ratio of [foreground] against [background], returning a value between
+ * 1 and 21. (1:1 and 21:1 ratios).
+ *
+ * Formula taken from [WCAG 2.0](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html#contrast-ratiodef)
+ *
+ * Note: [foreground] and [background] *must* be opaque. See [Color.compositeOver] to pre-composite
+ * a translucent foreground over the background.
+ *
+ * @return the contrast ratio as a value between 1 and 21. See [calculateContrastRatio]
+ */
+/*@VisibleForTesting*/
+internal fun calculateContrastRatio(foreground: Color, background: Color): Float {
+    val foregroundLuminance = foreground.luminance() + 0.05f
+    val backgroundLuminance = background.luminance() + 0.05f
+
+    return max(foregroundLuminance, backgroundLuminance) /
+        min(foregroundLuminance, backgroundLuminance)
+}
+
+/**
+ * Default selection background alpha - we will try and use this if it is accessible and produces
+ * the correct contrast ratio.
+ */
+private const val DefaultSelectionBackgroundAlpha = 0.4f
+
+/**
+ * Not all combinations of text color and selection color will have a reasonable alpha that
+ * produces a contrast ratio of at least [DesiredContrastRatio] - in this case just pick a low
+ * but still visible alpha so at least the contrast ratio is as good as it can be - this is
+ * preferable to crashing at runtime.
+ */
+private const val MinimumSelectionBackgroundAlpha = DefaultSelectionBackgroundAlpha / 2f
+
+/**
+ * Material and WCAG 2.0 sc 1.4.3 minimum contrast for AA text
+ */
+private const val DesiredContrastRatio = 4.5f
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTheme.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTheme.kt
new file mode 100644
index 0000000..9c15d6f2
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/MaterialTheme.kt
@@ -0,0 +1,113 @@
+/*
+ * 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.foundation.LocalIndication
+import androidx.compose.foundation.text.selection.LocalTextSelectionColors
+import androidx.compose.material.ripple.LocalRippleTheme
+import androidx.compose.material.ripple.RippleTheme
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.remember
+
+/**
+ * MaterialTheme defines the styling principles from the Wear Material3 design specification
+ * which extends the Material design specification.
+ *
+ * Wear Material components from package/sub-packages in [androidx.wear.compose.material3]
+ * use values provided here when retrieving default values.
+ *
+ * TODO(b/273543423) Update references to Material3 design specs
+ *
+ * All values may be set by providing this component with the [colors][ColorScheme],
+ * [typography][Typography], and [shapes][Shapes] attributes. Use this to configure the
+ * overall theme of elements within this MaterialTheme.
+ *
+ * Any values that are not set will inherit the current value from the theme, falling back to the
+ * defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the
+ * top of your application, and then separate MaterialTheme(s) for different screens / parts of
+ * your UI, overriding only the parts of the theme definition that need to change.
+ *
+ * For more information, see the
+ * [Theming](https://developer.android.com/training/wearables/components/theme)
+ * guide.
+ *
+ * @param colorScheme A complete definition of the Wear Material Color theme for this hierarchy
+ * @param typography A set of text styles to be used as this hierarchy's typography system
+ * @param shapes A set of shapes to be used by the components in this hierarchy
+ */
+@Composable
+public fun MaterialTheme(
+    colorScheme: ColorScheme = MaterialTheme.colorScheme,
+    typography: Typography = MaterialTheme.typography,
+    shapes: Shapes = MaterialTheme.shapes,
+    content: @Composable () -> Unit
+) {
+    val rememberedColors = remember {
+        // Explicitly creating a new object here so we don't mutate the initial [colors]
+        // provided, and overwrite the values set in it.
+        colorScheme.copy()
+    }.apply { updateColorSchemeFrom(colorScheme) }
+    val rippleIndication = rememberRipple()
+    val selectionColors = rememberTextSelectionColors(rememberedColors)
+    CompositionLocalProvider(
+        LocalColors provides rememberedColors,
+        LocalShapes provides shapes,
+        LocalTypography provides typography,
+        LocalContentAlpha provides ContentAlpha.high,
+        LocalIndication provides rippleIndication,
+        LocalRippleTheme provides MaterialRippleTheme,
+        LocalTextSelectionColors provides selectionColors,
+
+        ) {
+        ProvideTextStyle(value = typography.bodyLarge, content = content)
+    }
+}
+
+public object MaterialTheme {
+    public val colorScheme: ColorScheme
+        @ReadOnlyComposable
+        @Composable
+        get() = LocalColors.current
+
+    public val typography: Typography
+        @ReadOnlyComposable
+        @Composable
+        get() = LocalTypography.current
+
+    public val shapes: Shapes
+        @ReadOnlyComposable
+        @Composable
+        get() = LocalShapes.current
+}
+
+@Immutable
+private object MaterialRippleTheme : RippleTheme {
+    @Composable
+    override fun defaultColor() = RippleTheme.defaultRippleColor(
+        contentColor = LocalContentColor.current,
+        lightTheme = false
+    )
+
+    @Composable
+    override fun rippleAlpha() = RippleTheme.defaultRippleAlpha(
+        contentColor = LocalContentColor.current,
+        lightTheme = false
+    )
+}
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Shapes.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Shapes.kt
new file mode 100644
index 0000000..aa54053
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Shapes.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.foundation.shape.CornerSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.graphics.RectangleShape
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.unit.dp
+
+/**
+ * Material surfaces can be displayed in different shapes. Shapes direct attention, identify
+ * components, communicate state, and express brand.
+ *
+ * The shape scale defines the style of container, offering a range of
+ * curved shapes (mostly polygonal). The default [Shapes] theme for Material3 is rounded rectangles,
+ * with various degrees of corner roundness:
+ *
+ * - None
+ * - Extra Small
+ * - Small
+ * - Medium
+ * - Large
+ * - Full
+ *
+ * You can customize the shape system for all components in the [MaterialTheme] or you can do it
+ * on a per component basis by overriding the shape parameter for that
+ * component. For example, by default, buttons use the shape style “full.” If your product requires
+ * a smaller amount of roundness, you can override the shape parameter with a different shape
+ * value like [Shapes.small].
+ *
+ * TODO(b/273226734) Review documentation with references to components that use the shape themes.
+ *
+ * @param none By default, provides [ShapeDefaults.None], which is [RectangleShape]
+ * @param extraSmall By default, provides [ShapeDefaults.ExtraSmall], a [RoundedCornerShape]
+ * with 4dp [CornerSize] (used by bundled Cards).
+ * @param small By default, provides [ShapeDefaults.Small], a [RoundedCornerShape]
+ * with 8dp [CornerSize].
+ * @param medium By default, provides [ShapeDefaults.Medium], a [RoundedCornerShape] with
+ * 16dp [CornerSize] (used by shape-shifting Buttons and rounded rectangle buttons).
+ * @param large By default, provides [ShapeDefaults.Large], a [RoundedCornerShape]
+ * with 24dp [CornerSize] (used by Cards).
+ * @param extraLarge By default, provides [ShapeDefaults.ExtraLarge], a
+ * [RoundedCornerShape] with 32dp [CornerSize].
+ * @param full By default, provides [ShapeDefaults.Full], a Stadium shape with
+ * 50% rounded [CornerSize] (used by Button).
+ */
+@Immutable
+class Shapes(
+    val none: Shape = ShapeDefaults.None,
+    val extraSmall: Shape = ShapeDefaults.ExtraSmall,
+    val small: Shape = ShapeDefaults.Small,
+    val medium: Shape = ShapeDefaults.Medium,
+    val large: Shape = ShapeDefaults.Large,
+    val extraLarge: Shape = ShapeDefaults.ExtraLarge,
+    val full: Shape = ShapeDefaults.Full,
+) {
+    /** Returns a copy of this Shapes, optionally overriding some of the values. */
+    fun copy(
+        none: Shape = this.none,
+        extraSmall: Shape = this.extraSmall,
+        small: Shape = this.small,
+        medium: Shape = this.medium,
+        large: Shape = this.large,
+        extraLarge: Shape = this.extraLarge,
+        full: Shape = this.full
+    ): Shapes = Shapes(
+        none = none,
+        extraSmall = extraSmall,
+        small = small,
+        medium = medium,
+        large = large,
+        extraLarge = extraLarge,
+        full = full,
+    )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is Shapes) return false
+        if (none != other.none) return false
+        if (extraSmall != other.extraSmall) return false
+        if (small != other.small) return false
+        if (medium != other.medium) return false
+        if (large != other.large) return false
+        if (extraLarge != other.extraLarge) return false
+        if (full != other.full) return false
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = none.hashCode()
+        result = 31 * result + extraSmall.hashCode()
+        result = 31 * result + small.hashCode()
+        result = 31 * result + medium.hashCode()
+        result = 31 * result + large.hashCode()
+        result = 31 * result + extraLarge.hashCode()
+        result = 31 * result + full.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "Shapes(" +
+            "none=$none, " +
+            "extraSmall=$extraSmall, " +
+            "small=$small, " +
+            "medium=$medium, " +
+            "large=$large, " +
+            "extraLarge=$extraLarge, " +
+            "full=$full)"
+    }
+}
+
+/**
+ * Contains the default values used by [Shapes]
+ */
+object ShapeDefaults {
+    /** None provides a RectangleShape */
+    val None = RectangleShape
+
+    /** Extra small sized corner shape */
+    val ExtraSmall = RoundedCornerShape(corner = CornerSize(4.dp))
+
+    /** Small sized corner shape */
+    val Small = RoundedCornerShape(corner = CornerSize(8.dp))
+
+    /** Medium sized corner shape */
+    val Medium = RoundedCornerShape(corner = CornerSize(16.dp))
+
+    /** Large sized corner shape */
+    val Large = RoundedCornerShape(corner = CornerSize(24.dp))
+
+    /** Extra large sized corner shape */
+    val ExtraLarge = RoundedCornerShape(corner = CornerSize(32.dp))
+
+    /** Full provides a stadium-shape with 50% rounded corners */
+    val Full = RoundedCornerShape(corner = CornerSize(50))
+}
+
+/** CompositionLocal used to specify the default shapes for the surfaces. */
+internal val LocalShapes = staticCompositionLocalOf { Shapes() }
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Text.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Text.kt
new file mode 100644
index 0000000..9efaa5e
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Text.kt
@@ -0,0 +1,258 @@
+/*
+ * 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.foundation.text.InlineTextContent
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.runtime.structuralEqualityPolicy
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.Paragraph
+import androidx.compose.ui.text.TextLayoutResult
+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.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.TextUnit
+
+/**
+ * High level element that displays text and provides semantics / accessibility information.
+ *
+ * The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
+ * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * attributes you want to override.
+ *
+ * For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
+ * precedence is as follows:
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
+ * then this parameter will always be used.
+ * - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
+ * from [style] will be used instead.
+ *
+ * Additionally, for [color], if [color] is not set, and [style] does not have a color, then
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
+ * [Text] or element containing this [Text] to adapt to different background colors and still
+ * maintain contrast and accessibility.
+ *
+ * @param text The text to be displayed.
+ * @param modifier [Modifier] to apply to this layout node.
+ * @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
+ * this will be [LocalContentColor].
+ * @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
+ * See [TextStyle.fontStyle].
+ * @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
+ * @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
+ * @param letterSpacing The amount of space to add between each letter.
+ * See [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline).
+ * See [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph.
+ * See [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
+ * See [TextStyle.lineHeight].
+ * @param overflow How visual overflow should be handled.
+ * @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if
+ * necessary. If the text exceeds the given number of lines, it will be truncated according to
+ * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * @param minLines The minimum height in terms of minimum number of visible lines. It is required
+ * that 1 <= [minLines] <= [maxLines].
+ * @param onTextLayout Callback that is executed when a new text layout is calculated. A
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
+ * @param style Style configuration for the text such as color, font, line height etc.
+ */
+@Composable
+public fun Text(
+    text: String,
+    modifier: Modifier = Modifier,
+    color: Color = Color.Unspecified,
+    fontSize: TextUnit = TextUnit.Unspecified,
+    fontStyle: FontStyle? = null,
+    fontWeight: FontWeight? = null,
+    fontFamily: FontFamily? = null,
+    letterSpacing: TextUnit = TextUnit.Unspecified,
+    textDecoration: TextDecoration? = null,
+    textAlign: TextAlign? = null,
+    lineHeight: TextUnit = TextUnit.Unspecified,
+    overflow: TextOverflow = TextOverflow.Clip,
+    softWrap: Boolean = true,
+    maxLines: Int = Int.MAX_VALUE,
+    minLines: Int = 1,
+    onTextLayout: (TextLayoutResult) -> Unit = {},
+    style: TextStyle = LocalTextStyle.current
+) {
+    Text(
+        AnnotatedString(text),
+        modifier,
+        color,
+        fontSize,
+        fontStyle,
+        fontWeight,
+        fontFamily,
+        letterSpacing,
+        textDecoration,
+        textAlign,
+        lineHeight,
+        overflow,
+        softWrap,
+        maxLines,
+        minLines,
+        emptyMap(),
+        onTextLayout,
+        style
+    )
+}
+
+/**
+ * High level element that displays text and provides semantics / accessibility information.
+ *
+ * The default [style] uses the [LocalTextStyle] provided by the [MaterialTheme] / components. If
+ * you are setting your own style, you may want to consider first retrieving [LocalTextStyle],
+ * and using [TextStyle.copy] to keep any theme defined attributes, only modifying the specific
+ * attributes you want to override.
+ *
+ * For ease of use, commonly used parameters from [TextStyle] are also present here. The order of
+ * precedence is as follows:
+ * - If a parameter is explicitly set here (i.e, it is _not_ `null` or [TextUnit.Unspecified]),
+ * then this parameter will always be used.
+ * - If a parameter is _not_ set, (`null` or [TextUnit.Unspecified]), then the corresponding value
+ * from [style] will be used instead.
+ *
+ * Additionally, for [color], if [color] is not set, and [style] does not have a color, then
+ * [LocalContentColor] will be used with an alpha of [LocalContentAlpha]- this allows this
+ * [Text] or element containing this [Text] to adapt to different background colors and still
+ * maintain contrast and accessibility.
+ *
+ * @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
+ * @param modifier [Modifier] to apply to this layout node.
+ * @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
+ * this will be [LocalContentColor].
+ * @param fontSize The size of glyphs to use when painting the text. See [TextStyle.fontSize].
+ * @param fontStyle The typeface variant to use when drawing the letters (e.g., italic).
+ * See [TextStyle.fontStyle].
+ * @param fontWeight The typeface thickness to use when painting the text (e.g., [FontWeight.Bold]).
+ * @param fontFamily The font family to be used when rendering the text. See [TextStyle.fontFamily].
+ * @param letterSpacing The amount of space to add between each letter.
+ * See [TextStyle.letterSpacing].
+ * @param textDecoration The decorations to paint on the text (e.g., an underline).
+ * See [TextStyle.textDecoration].
+ * @param textAlign The alignment of the text within the lines of the paragraph.
+ * See [TextStyle.textAlign].
+ * @param lineHeight Line height for the [Paragraph] in [TextUnit] unit, e.g. SP or EM.
+ * See [TextStyle.lineHeight].
+ * @param overflow How visual overflow should be handled.
+ * @param softWrap Whether the text should break at soft line breaks. If false, the glyphs in the
+ * text will be positioned as if there was unlimited horizontal space. If [softWrap] is false,
+ * [overflow] and TextAlign may have unexpected effects.
+ * @param maxLines An optional maximum number of lines for the text to span, wrapping if
+ * necessary. If the text exceeds the given number of lines, it will be truncated according to
+ * [overflow] and [softWrap]. If it is not null, then it must be greater than zero.
+ * @param minLines The minimum height in terms of minimum number of visible lines. It is required
+ * that 1 <= [minLines] <= [maxLines].
+ * @param inlineContent A map store composables that replaces certain ranges of the text. It's
+ * used to insert composables into text layout. Check [InlineTextContent] for more information.
+ * @param onTextLayout Callback that is executed when a new text layout is calculated. A
+ * [TextLayoutResult] object that callback provides contains paragraph information, size of the
+ * text, baselines and other details. The callback can be used to add additional decoration or
+ * functionality to the text. For example, to draw selection around the text.
+ * @param style Style configuration for the text such as color, font, line height etc.
+ */
+@Composable
+public fun Text(
+    text: AnnotatedString,
+    modifier: Modifier = Modifier,
+    color: Color = Color.Unspecified,
+    fontSize: TextUnit = TextUnit.Unspecified,
+    fontStyle: FontStyle? = null,
+    fontWeight: FontWeight? = null,
+    fontFamily: FontFamily? = null,
+    letterSpacing: TextUnit = TextUnit.Unspecified,
+    textDecoration: TextDecoration? = null,
+    textAlign: TextAlign? = null,
+    lineHeight: TextUnit = TextUnit.Unspecified,
+    overflow: TextOverflow = TextOverflow.Clip,
+    softWrap: Boolean = true,
+    maxLines: Int = Int.MAX_VALUE,
+    minLines: Int = 1,
+    inlineContent: Map<String, InlineTextContent> = mapOf(),
+    onTextLayout: (TextLayoutResult) -> Unit = {},
+    style: TextStyle = LocalTextStyle.current
+) {
+    val textColor = color.takeOrElse {
+        style.color.takeOrElse {
+            LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
+        }
+    }
+
+    androidx.wear.compose.materialcore.Text(
+        text = text,
+        modifier = modifier,
+        color = textColor,
+        fontSize = fontSize,
+        fontStyle = fontStyle,
+        fontWeight = fontWeight,
+        fontFamily = fontFamily,
+        letterSpacing = letterSpacing,
+        textDecoration = textDecoration,
+        textAlign = textAlign,
+        lineHeight = lineHeight,
+        overflow = overflow,
+        softWrap = softWrap,
+        maxLines = maxLines,
+        minLines = minLines,
+        inlineContent = inlineContent,
+        onTextLayout = onTextLayout,
+        style = style
+    )
+}
+
+/**
+ * CompositionLocal containing the preferred [TextStyle] that will be used by [Text] components by
+ * default. To set the value for this CompositionLocal, see [ProvideTextStyle] which will merge any
+ * missing [TextStyle] properties with the existing [TextStyle] set in this CompositionLocal.
+ *
+ * @see ProvideTextStyle
+ */
+public val LocalTextStyle: ProvidableCompositionLocal<TextStyle> =
+    compositionLocalOf(structuralEqualityPolicy()) { TextStyle.Default }
+
+/**
+ * This function is used to set the current value of [LocalTextStyle], merging the given style
+ * with the current style values for any missing attributes. Any [Text] components included in
+ * this component's [content] will be styled with this style unless styled explicitly.
+ *
+ * @see LocalTextStyle
+ */
+@Composable
+public fun ProvideTextStyle(value: TextStyle, content: @Composable () -> Unit) {
+    val mergedStyle = LocalTextStyle.current.merge(value)
+    CompositionLocalProvider(LocalTextStyle provides mergedStyle, content = content)
+}
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Typography.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Typography.kt
new file mode 100644
index 0000000..34d16b6
--- /dev/null
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Typography.kt
@@ -0,0 +1,304 @@
+/*
+ * 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.runtime.Immutable
+import androidx.compose.runtime.staticCompositionLocalOf
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+/**
+ * Class holding typography definitions as defined by the Wear Material typography specification.
+ *
+ * The text styles in this typography are scaled according to the user's preferred font size in
+ * the system settings. Larger font sizes can be fixed if necessary in order to avoid pressure on
+ * screen space, because they are already sufficiently accessible.
+ * Here is an example of fixing the font size for Display1:
+ * @sample androidx.wear.compose.material.samples.FixedFontSize
+ *
+ * TODO(b/273526150) Review documentation for typography, add examples for each size.
+ * @property displayExtraLarge DisplayExtraLarge is the largest headline. Displays are the
+ * largest text on the screen, reserved for short, important text or numerals.
+ *
+ * @property displayLarge DisplayLarge is the second largest headline. Displays are the largest text
+ * on the screen, reserved for short, important text or numerals.
+ *
+ * @property displayMedium DisplayMedium is the third largest headline. Displays are the
+ * largest text on the screen, reserved for short, important text or numerals.
+ *
+ * @property displaySmall DisplaySmall is the fourth largest headline. Displays are the largest
+ * text on the screen, reserved for short, important text or numerals.
+ *
+ * @property titleLarge TitleLarge is the largest title. Titles are smaller than Displays. They are
+ * typically reserved for medium-emphasis text that is shorter in length.
+ *
+ * @property titleMedium TitleMedium is the medium title. Titles are smaller than Displays. They are
+ * typically reserved for medium-emphasis text that is shorter in length.
+ *
+ * @property titleSmall TitleSmall is the smallest title. Titles are smaller than Displays. They are
+ * typically reserved for medium-emphasis text that is shorter in length.
+ *
+ * @property bodyLarge 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.
+ *
+ * @property bodyMedium BodyMedium is the medium 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 bodySmall BodySmall 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 buttonMedium ButtonMedium text is a call to action used in different types of buttons
+ * (such as text, outlined and contained buttons) and in tabs, dialogs, and cards. Button text is
+ * typically sans serif, using all caps text.
+ *
+ * @property captionLarge CaptionLarge is the largest caption. Caption texts are the smallest
+ * font sizes. They are used on secondary content.
+ *
+ * @property captionMedium CaptionMedium is the second largest caption. Caption texts are the
+ * smallest font sizes. They are used on secondary content.
+ *
+ * @property captionSmall CaptionSmall is an exceptional small font size which is used for the extra
+ * long-form writing like legal texts.
+ */
+@Immutable
+public class Typography internal constructor(
+    public val displayExtraLarge: TextStyle,
+    public val displayLarge: TextStyle,
+    public val displayMedium: TextStyle,
+    public val displaySmall: TextStyle,
+    public val titleLarge: TextStyle,
+    public val titleMedium: TextStyle,
+    public val titleSmall: TextStyle,
+    public val bodyLarge: TextStyle,
+    public val bodyMedium: TextStyle,
+    public val bodySmall: TextStyle,
+    public val buttonMedium: TextStyle,
+    public val captionLarge: TextStyle,
+    public val captionMedium: TextStyle,
+    public val captionSmall: TextStyle,
+) {
+    public constructor (
+        defaultFontFamily: FontFamily = FontFamily.Default,
+        displayExtraLarge: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 50.sp,
+            lineHeight = 56.sp,
+            letterSpacing = 0.5.sp
+        ),
+        displayLarge: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 40.sp,
+            lineHeight = 46.sp,
+            letterSpacing = 0.5.sp
+        ),
+        displayMedium: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 34.sp,
+            lineHeight = 40.sp,
+            letterSpacing = 1.sp
+        ),
+        displaySmall: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 30.sp,
+            lineHeight = 36.sp,
+            letterSpacing = 0.8.sp,
+        ),
+        titleLarge: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 24.sp,
+            lineHeight = 28.sp,
+            letterSpacing = 0.2.sp
+        ),
+        titleMedium: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 20.sp,
+            lineHeight = 24.sp,
+            letterSpacing = 0.2.sp
+        ),
+        titleSmall: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 16.sp,
+            lineHeight = 20.sp,
+            letterSpacing = 0.2.sp
+        ),
+        bodyLarge: TextStyle = TextStyle(
+            fontWeight = FontWeight.Normal,
+            fontSize = 16.sp,
+            lineHeight = 20.sp,
+            letterSpacing = 0.18.sp
+        ),
+        bodyMedium: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 16.sp,
+            lineHeight = 20.sp,
+            letterSpacing = 0.2.sp
+        ),
+        bodySmall: TextStyle = TextStyle(
+            fontWeight = FontWeight.Normal,
+            fontSize = 14.sp,
+            lineHeight = 18.sp,
+            letterSpacing = 0.2.sp
+        ),
+        buttonMedium: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 15.sp,
+            lineHeight = 19.sp,
+            letterSpacing = 0.2.sp
+        ),
+        captionLarge: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 14.sp,
+            lineHeight = 18.sp,
+            letterSpacing = 0.3.sp
+        ),
+        captionMedium: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 12.sp,
+            lineHeight = 16.sp,
+            letterSpacing = 0.4.sp
+        ),
+        captionSmall: TextStyle = TextStyle(
+            fontWeight = FontWeight.Medium,
+            fontSize = 10.sp,
+            lineHeight = 14.sp,
+            letterSpacing = 0.4.sp
+        )
+
+    ) : this(
+        displayExtraLarge = displayExtraLarge.withDefaultFontFamily(defaultFontFamily),
+        displayLarge = displayLarge.withDefaultFontFamily(defaultFontFamily),
+        displayMedium = displayMedium.withDefaultFontFamily(defaultFontFamily),
+        displaySmall = displaySmall.withDefaultFontFamily(defaultFontFamily),
+        titleLarge = titleLarge.withDefaultFontFamily(defaultFontFamily),
+        titleMedium = titleMedium.withDefaultFontFamily(defaultFontFamily),
+        titleSmall = titleSmall.withDefaultFontFamily(defaultFontFamily),
+        bodyLarge = bodyLarge.withDefaultFontFamily(defaultFontFamily),
+        bodyMedium = bodyMedium.withDefaultFontFamily(defaultFontFamily),
+        bodySmall = bodySmall.withDefaultFontFamily(defaultFontFamily),
+        buttonMedium = buttonMedium.withDefaultFontFamily(defaultFontFamily),
+        captionLarge = captionLarge.withDefaultFontFamily(defaultFontFamily),
+        captionMedium = captionMedium.withDefaultFontFamily(defaultFontFamily),
+        captionSmall = captionSmall.withDefaultFontFamily(defaultFontFamily),
+    )
+
+    /**
+     * Returns a copy of this Typography, optionally overriding some of the values.
+     */
+    public fun copy(
+        displayExtraLarge: TextStyle = this.displayExtraLarge,
+        displayLarge: TextStyle = this.displayLarge,
+        displayMedium: TextStyle = this.displayMedium,
+        displaySmall: TextStyle = this.displaySmall,
+        titleLarge: TextStyle = this.titleLarge,
+        titleMedium: TextStyle = this.titleMedium,
+        titleSmall: TextStyle = this.titleSmall,
+        bodyLarge: TextStyle = this.bodyLarge,
+        bodyMedium: TextStyle = this.bodyMedium,
+        bodySmall: TextStyle = this.bodySmall,
+        buttonMedium: TextStyle = this.buttonMedium,
+        captionLarge: TextStyle = this.captionLarge,
+        captionMedium: TextStyle = this.captionMedium,
+        captionSmall: TextStyle = this.captionSmall,
+    ): Typography = Typography(
+        displayExtraLarge,
+        displayLarge,
+        displayMedium,
+        displaySmall,
+        titleLarge,
+        titleMedium,
+        titleSmall,
+        bodyLarge,
+        bodyMedium,
+        bodySmall,
+        buttonMedium,
+        captionLarge,
+        captionMedium,
+        captionSmall,
+    )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is Typography) return false
+
+        if (displayExtraLarge != other.displayExtraLarge) return false
+        if (displayLarge != other.displayLarge) return false
+        if (displayMedium != other.displayMedium) return false
+        if (displaySmall != other.displaySmall) return false
+        if (titleLarge != other.titleLarge) return false
+        if (titleMedium != other.titleMedium) return false
+        if (titleSmall != other.titleSmall) return false
+        if (bodyLarge != other.bodyLarge) return false
+        if (bodyMedium != other.bodyMedium) return false
+        if (bodySmall != other.bodySmall) return false
+        if (buttonMedium != other.buttonMedium) return false
+        if (captionLarge != other.captionLarge) return false
+        if (captionMedium != other.captionMedium) return false
+        if (captionSmall != other.captionSmall) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = displayExtraLarge.hashCode()
+        result = 31 * result + displayLarge.hashCode()
+        result = 31 * result + displayMedium.hashCode()
+        result = 31 * result + displaySmall.hashCode()
+        result = 31 * result + titleLarge.hashCode()
+        result = 31 * result + titleMedium.hashCode()
+        result = 31 * result + titleSmall.hashCode()
+        result = 31 * result + bodyLarge.hashCode()
+        result = 31 * result + bodyMedium.hashCode()
+        result = 31 * result + bodySmall.hashCode()
+        result = 31 * result + buttonMedium.hashCode()
+        result = 31 * result + captionLarge.hashCode()
+        result = 31 * result + captionMedium.hashCode()
+        result = 31 * result + captionSmall.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "Typography(displayExtraLarge=$displayExtraLarge, displayLarge=$displayLarge, " +
+            "displayMedium=$displayMedium, displaySmall=$displaySmall, " +
+            "titleLarge=$titleLarge, titleMedium=$titleMedium, titleSmall=$titleSmall, " +
+            "bodyLarge=$bodyLarge, bodyMedium=$bodyMedium, bodySmall=$bodySmall, " +
+            "buttonMedium=$buttonMedium, captionLarge=$captionLarge, " +
+            "captionMedium=$captionMedium, captionSmall=$captionSmall)"
+    }
+}
+
+/**
+ * @return [this] if there is a [FontFamily] defined, otherwise copies [this] with [default] as
+ * the [FontFamily].
+ */
+private fun TextStyle.withDefaultFontFamily(default: FontFamily): TextStyle {
+    return if (fontFamily != null) this else copy(fontFamily = default)
+}
+
+/**
+ * This Ambient holds on to the current definition of typography for this application as described
+ * by the Wear Material spec. You can read the values in it when creating custom components that
+ * want to use Wear Material types, as well as override the values when you want to re-style a part
+ * of your hierarchy. Material components related to text such as Button will use this Ambient
+ * to set values with which to style children text components.
+ *
+ * To access values within this ambient, use [MaterialTheme.typography].
+ */
+internal val LocalTypography = staticCompositionLocalOf { Typography() }
diff --git a/wear/compose/compose-navigation/build.gradle b/wear/compose/compose-navigation/build.gradle
index cee0747..7bfe4ee 100644
--- a/wear/compose/compose-navigation/build.gradle
+++ b/wear/compose/compose-navigation/build.gradle
@@ -29,13 +29,13 @@
     api(project(":compose:runtime:runtime"))
     api("androidx.navigation:navigation-runtime:2.5.3")
     api(project(":wear:compose:compose-material"))
-    api(project(":activity:activity-compose"))
+    api("androidx.activity:activity-compose:1.7.0")
     api("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0")
 
     implementation(libs.kotlinStdlib)
     implementation(project(":navigation:navigation-common"))
     implementation("androidx.navigation:navigation-compose:2.5.3")
-    implementation("androidx.profileinstaller:profileinstaller:1.2.0")
+    implementation("androidx.profileinstaller:profileinstaller:1.3.0")
 
     androidTestImplementation(project(":compose:test-utils"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
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 e0b1320..108b9ad 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
@@ -106,12 +106,15 @@
         is ActivityDemo<*> -> {
             /* should never get here as activity demos are not added to the backstack*/
         }
+
         is ComposableDemo -> {
             demo.content(DemoParameters(onNavigateBack, state))
         }
+
         is DemoCategory -> {
             DisplayDemoList(demo, onNavigateTo)
         }
+
         else -> {
         }
     }
@@ -190,7 +193,7 @@
 fun Modifier.rsbScroll(
     scrollableState: ScrollableState,
     flingBehavior: FlingBehavior,
-    focusRequester: FocusRequester
+    focusRequester: FocusRequester? = null
 ): Modifier {
     val channel = remember {
         Channel<TimestampedDelta>(
@@ -247,9 +250,12 @@
             channel.trySend(TimestampedDelta(it.uptimeMillis, it.verticalScrollPixels))
             rsbScrollInProgress = true
             true
+        }.let {
+            if (focusRequester != null) {
+                it.focusRequester(focusRequester)
+                    .focusable()
+            } else it
         }
-            .focusRequester(focusRequester)
-            .focusable()
     }
 }
 
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
index 39f1e3c..e40b68a 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ExpandableDemo.kt
@@ -29,18 +29,18 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.ExpandableItemsDefaults
+import androidx.wear.compose.foundation.ExpandableItemsState
+import androidx.wear.compose.foundation.expandableItem
+import androidx.wear.compose.foundation.expandableItems
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
 import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
+import androidx.wear.compose.foundation.rememberExpandableItemsState
 import androidx.wear.compose.material.Chip
 import androidx.wear.compose.material.ChipDefaults
-import androidx.wear.compose.material.ExpandableItemsDefaults
 import androidx.wear.compose.material.MaterialTheme
 import androidx.wear.compose.material.OutlinedChip
-import androidx.wear.compose.material.ExpandableItemsState
 import androidx.wear.compose.material.Text
-import androidx.wear.compose.material.rememberExpandableItemsState
-import androidx.wear.compose.material.expandableItem
-import androidx.wear.compose.material.expandableItems
 
 @Composable
 fun ExpandableListItems() {
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 49fb373..c0f9761 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
@@ -24,6 +24,8 @@
 import androidx.wear.compose.foundation.samples.CurvedFonts
 import androidx.wear.compose.foundation.samples.CurvedRowAndColumn
 import androidx.wear.compose.foundation.samples.CurvedWeight
+import androidx.wear.compose.foundation.samples.ExpandableTextSample
+import androidx.wear.compose.foundation.samples.ExpandableWithItemsSample
 import androidx.wear.compose.foundation.samples.HierarchicalFocusCoordinatorSample
 import androidx.wear.compose.foundation.samples.OversizeComposable
 import androidx.wear.compose.foundation.samples.ScalingLazyColumnEdgeAnchoredAndAnimatedScrollTo
@@ -35,6 +37,15 @@
 val WearFoundationDemos = DemoCategory(
     "Foundation",
     listOf(
+        DemoCategory(
+            "Expandables",
+            listOf(
+                ComposableDemo("Items in SLC") { ExpandableListItems() },
+                ComposableDemo("Expandable Text") { ExpandableText() },
+                ComposableDemo("Items Sample") { ExpandableWithItemsSample() },
+                ComposableDemo("Text Sample") { ExpandableTextSample() },
+            )
+        ),
         DemoCategory("CurvedLayout", listOf(
             ComposableDemo("Curved Row") { CurvedWorldDemo() },
             ComposableDemo("Curved Row and Column") { CurvedRowAndColumn() },
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index baf4417..45ecbf2 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -50,8 +50,6 @@
 import androidx.wear.compose.material.samples.CurvedTextDemo
 import androidx.wear.compose.material.samples.CurvedTextProviderDemo
 import androidx.wear.compose.material.samples.EdgeSwipeForSwipeToDismiss
-import androidx.wear.compose.material.samples.ExpandableTextSample
-import androidx.wear.compose.material.samples.ExpandableWithItemsSample
 import androidx.wear.compose.material.samples.FixedFontSize
 import androidx.wear.compose.material.samples.HorizontalPageIndicatorSample
 import androidx.wear.compose.material.samples.IndeterminateCircularProgressIndicator
@@ -130,15 +128,6 @@
     "Material",
     listOf(
         DemoCategory(
-            "Expandables",
-            listOf(
-                ComposableDemo("Items in SLC") { ExpandableListItems() },
-                ComposableDemo("Expandable Text") { ExpandableText() },
-                ComposableDemo("Items Sample") { ExpandableWithItemsSample() },
-                ComposableDemo("Text Sample") { ExpandableTextSample() },
-            )
-        ),
-        DemoCategory(
             "ScrollAway",
             listOf(
                 ComposableDemo("Column") { ScrollAwayColumnDemo() },
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
index def1922..510f4b4 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
@@ -61,6 +61,7 @@
 import androidx.compose.ui.input.pointer.pointerInteropFilter
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalLifecycleOwner
 import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.focused
@@ -165,6 +166,7 @@
                 pickerGroupState.selectedIndex = curr.index
             } else if (next == FocusableElementsTimePicker.CONFIRM_BUTTON) {
                 focusRequesterConfirmButton.requestFocus()
+                pickerGroupState.selectedIndex = next.index
             } else {
                 pickerGroupState.selectedIndex = next.index
             }
@@ -201,8 +203,11 @@
                     PickerGroup(
                         PickerGroupItem(
                             pickerState = hourState,
-                            modifier = Modifier.size(40.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier
+                                .size(40.dp, 100.dp).rsbScroll(
+                                    scrollableState = hourState,
+                                    flingBehavior = PickerDefaults.flingBehavior(hourState),
+                                ),
                             onSelected = {
                                 onPickerSelected(
                                     FocusableElementsTimePicker.HOURS,
@@ -214,8 +219,11 @@
                         ),
                         PickerGroupItem(
                             pickerState = minuteState,
-                            modifier = Modifier.size(40.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier
+                                .size(40.dp, 100.dp).rsbScroll(
+                                    scrollableState = minuteState,
+                                    flingBehavior = PickerDefaults.flingBehavior(minuteState),
+                                ),
                             onSelected = {
                                 onPickerSelected(
                                     FocusableElementsTimePicker.MINUTES,
@@ -227,8 +235,11 @@
                         ),
                         PickerGroupItem(
                             pickerState = secondState,
-                            modifier = Modifier.size(40.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier
+                                .size(40.dp, 100.dp).rsbScroll(
+                                    scrollableState = secondState,
+                                    flingBehavior = PickerDefaults.flingBehavior(secondState),
+                                ),
                             onSelected = {
                                 onPickerSelected(
                                     FocusableElementsTimePicker.SECONDS,
@@ -376,24 +387,27 @@
                 Row(
                     modifier = Modifier.fillMaxWidth(),
                     verticalAlignment = Alignment.CenterVertically,
-                    horizontalArrangement = Arrangement.Center,
-
+                    horizontalArrangement = Arrangement.End,
                     ) {
                     val doubleTapToNext =
                         { current: FocusableElement12Hour, next: FocusableElement12Hour ->
                             if (pickerGroupState.selectedIndex != current.index) {
-                                focusRequesterConfirmButton.requestFocus()
-                            } else if (next == FocusableElement12Hour.CONFIRM_BUTTON) {
                                 pickerGroupState.selectedIndex = current.index
+                            } else if (next == FocusableElement12Hour.CONFIRM_BUTTON) {
+                                focusRequesterConfirmButton.requestFocus()
+                                pickerGroupState.selectedIndex = next.index
                             } else {
                                 pickerGroupState.selectedIndex = next.index
                             }
                         }
+                    Spacer(Modifier.width(16.dp))
                     PickerGroup(
                         PickerGroupItem(
                             pickerState = hourState,
-                            modifier = Modifier.size(40.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier.size(50.dp, 100.dp).rsbScroll(
+                                scrollableState = hourState,
+                                flingBehavior = PickerDefaults.flingBehavior(hourState),
+                            ),
                             onSelected = {
                                 doubleTapToNext(
                                     FocusableElement12Hour.HOURS,
@@ -401,12 +415,14 @@
                                 )
                             },
                             contentDescription = hoursContentDescription,
-                            option = pickerOption
+                            option = pickerTextOption(textStyle) { "%02d".format(it + 1) }
                         ),
                         PickerGroupItem(
                             pickerState = minuteState,
-                            modifier = Modifier.size(48.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier.size(50.dp, 100.dp).rsbScroll(
+                                scrollableState = minuteState,
+                                flingBehavior = PickerDefaults.flingBehavior(minuteState),
+                            ),
 
                             onSelected = {
                                 doubleTapToNext(
@@ -419,8 +435,10 @@
                         ),
                         PickerGroupItem(
                             pickerState = periodState,
-                            modifier = Modifier.size(64.dp, 100.dp),
-                            focusRequester = remember { FocusRequester() },
+                            modifier = Modifier.size(64.dp, 100.dp).rsbScroll(
+                                scrollableState = periodState,
+                                flingBehavior = PickerDefaults.flingBehavior(periodState),
+                            ),
                             contentDescription = periodContentDescription,
                             onSelected = {
                                 doubleTapToNext(
@@ -446,7 +464,11 @@
                         ),
                         autoCenter = false,
                         pickerGroupState = pickerGroupState,
-                        separator = { Separator(6.dp, textStyle) },
+                        separator = {
+                            if (it == 0) {
+                                Separator(0.dp, textStyle)
+                            }
+                        },
                     )
                 }
                 Spacer(
@@ -583,6 +605,17 @@
                 )
             } }
 
+        val focusManager = LocalFocusManager.current
+
+        LaunchedEffect(focusedElement) {
+            when (focusedElement) {
+                FocusableElementDatePicker.DAY -> focusRequesterDay.requestFocus()
+                FocusableElementDatePicker.MONTH -> focusRequesterMonth.requestFocus()
+                FocusableElementDatePicker.YEAR -> focusRequesterYear.requestFocus()
+                else -> focusManager.clearFocus()
+            }
+        }
+
         BoxWithConstraints(
             modifier = modifier
                 .fillMaxSize()
diff --git a/wear/protolayout/protolayout-material/api/current.txt b/wear/protolayout/protolayout-material/api/current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/current.txt
+++ b/wear/protolayout/protolayout-material/api/current.txt
@@ -1 +1,298 @@
 // 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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    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(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    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 String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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);
+  }
+
+  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 String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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 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 int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setHorizontalAlignment(int);
+    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 public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    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_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 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 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 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/public_plus_experimental_current.txt b/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-material/api/public_plus_experimental_current.txt
@@ -1 +1,298 @@
 // 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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    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(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    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 String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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);
+  }
+
+  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 String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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 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 int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setHorizontalAlignment(int);
+    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 public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    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_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 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 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 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/restricted_current.txt b/wear/protolayout/protolayout-material/api/restricted_current.txt
index e6f50d0..862495c3 100644
--- a/wear/protolayout/protolayout-material/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-material/api/restricted_current.txt
@@ -1 +1,298 @@
 // 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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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, androidx.wear.protolayout.DimensionBuilders.DpProp);
+    method public androidx.wear.protolayout.material.Button.Builder setIconContent(String);
+    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(@ColorInt int, @ColorInt int);
+    ctor public ButtonColors(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(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(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.protolayout.ColorBuilders.ColorProp, androidx.wear.protolayout.ColorBuilders.ColorProp);
+    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 CharSequence? 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();
+  }
+
+  public static final class CircularProgressIndicator.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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(CharSequence);
+    method public androidx.wear.protolayout.material.CircularProgressIndicator.Builder setEndAngle(float);
+    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 String getText();
+  }
+
+  public static final class CompactChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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);
+  }
+
+  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 String getText();
+    method public int getWeight();
+    method public boolean isItalic();
+    method public boolean isUnderline();
+  }
+
+  public static final class Text.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.Builder {
+    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 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 int getHorizontalAlignment();
+    method public String getText();
+    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension getWidth();
+  }
+
+  public static final class TitleChip.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setHorizontalAlignment(int);
+    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 public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getEdgeContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
+    method public androidx.wear.protolayout.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  }
+
+  public static final class EdgeContentLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 setEdgeContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    method public androidx.wear.protolayout.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.protolayout.LayoutElementBuilders.LayoutElement);
+    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_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 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 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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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();
+  }
+
+  public static final class PrimaryLayout.Builder implements androidx.wear.protolayout.LayoutElementBuilders.LayoutElement.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 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/build.gradle b/wear/protolayout/protolayout-material/build.gradle
index 7241009..fdd52a9 100644
--- a/wear/protolayout/protolayout-material/build.gradle
+++ b/wear/protolayout/protolayout-material/build.gradle
@@ -23,10 +23,46 @@
 
 dependencies {
     annotationProcessor(libs.nullaway)
-    // Add dependencies here
+    api("androidx.annotation:annotation:1.2.0")
+    implementation(project(":wear:protolayout:protolayout"))
+    implementation(project(":wear:protolayout:protolayout-proto"))
+    implementation(project(":wear:protolayout:protolayout-expression"))
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation("androidx.core:core:1.7.0")
+    androidTestImplementation(project(":test:screenshot:screenshot"))
+    androidTestImplementation(project(":wear:tiles:tiles-renderer"))
+    androidTestRuntimeOnly(project(path: ":wear:protolayout:protolayout-proto", configuration: "shadow"))
+    androidTestImplementation(libs.protobuf)
+
+    testImplementation(libs.junit)
+    testImplementation(libs.mockitoCore4)
+    testImplementation(libs.robolectric)
+    testImplementation(libs.testExtJunit)
+    testImplementation(libs.testExtTruth)
+    testImplementation(libs.testCore)
+    testImplementation(libs.testRunner)
+    testImplementation(libs.testRules)
+    testImplementation(libs.truth)
 }
 
 android {
+    defaultConfig {
+        minSdkVersion 26
+    }
+
+    sourceSets {
+        // TODO(b/268312818): Update to protolayout location and copy images.
+        androidTest.assets.srcDirs += project.rootDir.absolutePath + "/../../golden/wear/wear-tiles-material"
+    }
+
+    defaultConfig {
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
     namespace "androidx.wear.protolayout.material"
 }
 
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java
new file mode 100644
index 0000000..996cae8
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Button.java
@@ -0,0 +1,565 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.CONTENT_SCALE_MODE_FILL_BOUNDS;
+import static androidx.wear.protolayout.material.ButtonDefaults.DEFAULT_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.EXTRA_LARGE_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.LARGE_SIZE;
+import static androidx.wear.protolayout.material.ButtonDefaults.PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.radiusOf;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.ColorFilter;
+import androidx.wear.protolayout.LayoutElementBuilders.Image;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders;
+import androidx.wear.protolayout.ModifiersBuilders.Background;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.Corner;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tiles component {@link Button} that represents clickable button with the given content.
+ *
+ * <p>The Button is circular in shape. The recommended sizes are defined in {@link ButtonDefaults}.
+ *
+ * <p>The recommended set of {@link ButtonColors} styles can be obtained from {@link
+ * ButtonDefaults}., e.g. {@link ButtonDefaults#PRIMARY_COLORS} to get a color scheme for a primary
+ * {@link Button}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Button button = new Button...
+ * Box box = new Box.Builder().addContent(button).build();
+ *
+ * Button myButton = (Button) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Button} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Button myButton = Button.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class Button implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with text. */
+    static final String METADATA_TAG_TEXT = "TXTBTN";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with icon. */
+    static final String METADATA_TAG_ICON = "ICNBTN";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with image. */
+    static final String METADATA_TAG_IMAGE = "IMGBTN";
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with custom
+     * content.
+     */
+    static final String METADATA_TAG_CUSTOM_CONTENT = "CSTBTN";
+
+    @NonNull private final Box mElement;
+
+    Button(@NonNull Box element) {
+        mElement = element;
+    }
+
+    /** Builder class for {@link Button}. */
+    public static final class Builder implements LayoutElement.Builder {
+        private static final int NOT_SET = -1;
+        private static final int ICON = 0;
+        private static final int TEXT = 1;
+        private static final int IMAGE = 2;
+        private static final int CUSTOM_CONTENT = 3;
+
+        @NonNull static final Map<Integer, String> TYPE_TO_TAG = new HashMap<>();
+
+        @RestrictTo(Scope.LIBRARY)
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({NOT_SET, ICON, TEXT, IMAGE, CUSTOM_CONTENT})
+        @interface ButtonType {}
+
+        @NonNull private final Context mContext;
+        @Nullable private LayoutElement mCustomContent;
+        @NonNull private final Clickable mClickable;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private DpProp mSize = DEFAULT_SIZE;
+        @Nullable private String mText = null;
+        @Nullable private Integer mTypographyName = null;
+        @Nullable private String mIcon = null;
+        @Nullable private DpProp mIconSize = null;
+        @Nullable private String mImage = null;
+        @NonNull private ButtonColors mButtonColors = PRIMARY_COLORS;
+        @ButtonType private int mType = NOT_SET;
+
+        static {
+            TYPE_TO_TAG.put(ICON, METADATA_TAG_ICON);
+            TYPE_TO_TAG.put(TEXT, METADATA_TAG_TEXT);
+            TYPE_TO_TAG.put(IMAGE, METADATA_TAG_IMAGE);
+            TYPE_TO_TAG.put(CUSTOM_CONTENT, METADATA_TAG_CUSTOM_CONTENT);
+        }
+
+        /**
+         * Creates a builder for the {@link Button} from the given content. Custom content should be
+         * later set with one of the following ({@link #setIconContent}, {@link #setTextContent},
+         * {@link #setImageContent}.
+         *
+         * @param context The application's context.
+         * @param clickable Associated {@link Clickable} for click events. When the Button is
+         *     clicked it will fire the associated action.
+         */
+        public Builder(@NonNull Context context, @NonNull Clickable clickable) {
+            mClickable = clickable;
+            mContext = context;
+        }
+
+        /**
+         * Sets the content description for the {@link Button}. It is highly recommended to provide
+         * this for button containing icon or image.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the size for the {@link Button}. Strongly recommended values are {@link
+         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
+         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
+         * used.
+         */
+        @NonNull
+        public Builder setSize(@NonNull DpProp size) {
+            mSize = size;
+            return this;
+        }
+
+        /**
+         * Sets the size for the {@link Button}. Strongly recommended values are {@link
+         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
+         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
+         * used.
+         */
+        @NonNull
+        public Builder setSize(@Dimension(unit = DP) float size) {
+            mSize = dp(size);
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link Button}. If not set, {@link ButtonDefaults#PRIMARY_COLORS}
+         * will be used.
+         */
+        @NonNull
+        public Builder setButtonColors(@NonNull ButtonColors buttonColors) {
+            mButtonColors = buttonColors;
+            return this;
+        }
+
+        /**
+         * Sets the custom content for this Button. Any previously added content will be overridden.
+         */
+        @NonNull
+        public Builder setCustomContent(@NonNull LayoutElement content) {
+            resetContent();
+            this.mCustomContent = content;
+            this.mType = CUSTOM_CONTENT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given icon with the given size. Any previously
+         * added content will be overridden. Provided icon will be tinted to the given content color
+         * from {@link ButtonColors} and with the given size. This icon should be image with chosen
+         * alpha channel and not an actual image.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId, @NonNull DpProp size) {
+            resetContent();
+            this.mIcon = imageResourceId;
+            this.mType = ICON;
+            this.mIconSize = size;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given icon with the default size that is half
+         * of the set size of the button. Any previously added content will be overridden. Provided
+         * icon will be tinted to the given content color from {@link ButtonColors}. This icon
+         * should be image with chosen alpha channel and not an actual image.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId) {
+            resetContent();
+            this.mIcon = imageResourceId;
+            this.mType = ICON;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given text with the default font for the set
+         * size (for the {@link ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and
+         * {@link ButtonDefaults#EXTRA_LARGE_SIZE} is {@link Typography#TYPOGRAPHY_TITLE2}, {@link
+         * Typography#TYPOGRAPHY_TITLE1} and {@link Typography#TYPOGRAPHY_DISPLAY3} respectively).
+         * Any previously added content will be overridden. Text should contain no more than 3
+         * characters, otherwise it will overflow from the edges.
+         */
+        @NonNull
+        public Builder setTextContent(@NonNull String text) {
+            resetContent();
+            this.mText = text;
+            this.mType = TEXT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given text with the given font. If you need
+         * more font related customization, consider using {@link #setCustomContent} with {@link
+         * Text} component. Any previously added content will be overridden. Text should contain no
+         * more than 3 characters, otherwise it will overflow from the edges.
+         */
+        @NonNull
+        public Builder setTextContent(@NonNull String text, @TypographyName int typographyName) {
+            resetContent();
+            this.mText = text;
+            this.mTypographyName = typographyName;
+            this.mType = TEXT;
+            return this;
+        }
+
+        /**
+         * Sets the content of this Button to be the given image, i.e. contacts photo. Any
+         * previously added content will be overridden.
+         */
+        @NonNull
+        public Builder setImageContent(@NonNull String imageResourceId) {
+            resetContent();
+            this.mImage = imageResourceId;
+            this.mType = IMAGE;
+            return this;
+        }
+
+        private void resetContent() {
+            this.mText = null;
+            this.mTypographyName = null;
+            this.mIcon = null;
+            this.mImage = null;
+            this.mCustomContent = null;
+            this.mIconSize = null;
+        }
+
+        /** Constructs and returns {@link Button} with the provided field and look. */
+        @NonNull
+        @Override
+        public Button build() {
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setClickable(mClickable)
+                            .setBackground(
+                                    new Background.Builder()
+                                            .setColor(mButtonColors.getBackgroundColor())
+                                            .setCorner(
+                                                    new Corner.Builder()
+                                                            .setRadius(radiusOf(mSize))
+                                                            .build())
+                                            .build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(
+                                                    getTagBytes(
+                                                            checkNotNull(TYPE_TO_TAG.get(mType))))
+                                            .build());
+            if (mContentDescription.length() > 0) {
+                modifiers.setSemantics(
+                        new ModifiersBuilders.Semantics.Builder()
+                                .setContentDescription(mContentDescription.toString())
+                                .build());
+            }
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setHeight(mSize)
+                            .setWidth(mSize)
+                            .setModifiers(modifiers.build());
+
+            element.addContent(getCorrectContent());
+
+            return new Button(element.build());
+        }
+
+        @NonNull
+        private LayoutElement getCorrectContent() {
+            LayoutElement.Builder content;
+            switch (mType) {
+                case ICON:
+                {
+                    DpProp iconSize =
+                            mIconSize != null
+                                    ? mIconSize
+                                    : ButtonDefaults.recommendedIconSize(mSize);
+                    content =
+                            new Image.Builder()
+                                    .setResourceId(checkNotNull(mIcon))
+                                    .setHeight(checkNotNull(iconSize))
+                                    .setWidth(iconSize)
+                                    .setContentScaleMode(CONTENT_SCALE_MODE_FILL_BOUNDS)
+                                    .setColorFilter(
+                                            new ColorFilter.Builder()
+                                                    .setTint(mButtonColors.getContentColor())
+                                                    .build());
+
+                    return content.build();
+                }
+                case TEXT:
+                {
+                    @TypographyName
+                    int typographyName =
+                            mTypographyName != null
+                                    ? mTypographyName
+                                    : getDefaultTypographyForSize(mSize);
+                    content =
+                            new Text.Builder(mContext, checkNotNull(mText))
+                                    .setMaxLines(1)
+                                    .setTypography(typographyName)
+                                    .setColor(mButtonColors.getContentColor());
+
+                    return content.build();
+                }
+                case IMAGE:
+                {
+                    content =
+                            new Image.Builder()
+                                    .setResourceId(checkNotNull(mImage))
+                                    .setHeight(mSize)
+                                    .setWidth(mSize)
+                                    .setContentScaleMode(CONTENT_SCALE_MODE_FILL_BOUNDS);
+                    return content.build();
+                }
+                case CUSTOM_CONTENT:
+                    return checkNotNull(mCustomContent);
+                case NOT_SET:
+                    // Shouldn't happen.
+                default:
+                    // Shouldn't happen.
+                    throw new IllegalArgumentException("Wrong Button type");
+            }
+        }
+
+        private static @TypographyName int getDefaultTypographyForSize(@NonNull DpProp size) {
+            if (size.getValue() == LARGE_SIZE.getValue()) {
+                return Typography.TYPOGRAPHY_TITLE1;
+            } else if (size.getValue() == EXTRA_LARGE_SIZE.getValue()) {
+                return Typography.TYPOGRAPHY_DISPLAY3;
+            } else {
+                return Typography.TYPOGRAPHY_TITLE2;
+            }
+        }
+    }
+
+    /**
+     * Returns the custom content of this Button if it has been added. Otherwise, it returns null.
+     */
+    @Nullable
+    public LayoutElement getCustomContent() {
+        if (!getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return null;
+        }
+        return getAnyContent();
+    }
+
+    /** Returns the icon content of this Button if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getIconContent() {
+        Image icon = getIconContentObject();
+        return icon != null ? checkNotNull(icon.getResourceId()).getValue() : null;
+    }
+
+    /**
+     * Returns the image content of this Button if it has been added. Otherwise, it returns null.
+     */
+    @Nullable
+    public String getImageContent() {
+        Image image = getImageContentObject();
+        return image != null ? checkNotNull(image.getResourceId()).getValue() : null;
+    }
+
+    /** Returns the text content of this Button if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getTextContent() {
+        Text text = getTextContentObject();
+        return text != null ? text.getText() : null;
+    }
+
+    @NonNull
+    private LayoutElement getAnyContent() {
+        return checkNotNull(mElement.getContents().get(0));
+    }
+
+    @Nullable
+    private Image getIconContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_ICON)) {
+            return null;
+        }
+        return (Image) getAnyContent();
+    }
+
+    @Nullable
+    private Text getTextContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_TEXT)) {
+            return null;
+        }
+        return Text.fromLayoutElement(getAnyContent());
+    }
+
+    @Nullable
+    private Image getImageContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_IMAGE)) {
+            return null;
+        }
+        return (Image) getAnyContent();
+    }
+
+    /** Returns click event action associated with this Button. */
+    @NonNull
+    public Clickable getClickable() {
+        return checkNotNull(checkNotNull(mElement.getModifiers()).getClickable());
+    }
+
+    /** Returns content description for this Button. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /** Returns size for this Button. */
+    @NonNull
+    public ContainerDimension getSize() {
+        return checkNotNull(mElement.getWidth());
+    }
+
+    private ColorProp getBackgroundColor() {
+        return checkNotNull(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getBackground()).getColor());
+    }
+
+    /** Returns button color of this Button. */
+    @NonNull
+    public ButtonColors getButtonColors() {
+        ColorProp backgroundColor = getBackgroundColor();
+        ColorProp contentColor = null;
+
+        switch (getMetadataTag()) {
+            case METADATA_TAG_TEXT:
+                contentColor = checkNotNull(getTextContentObject()).getColor();
+                break;
+            case METADATA_TAG_ICON:
+                contentColor =
+                        checkNotNull(checkNotNull(getIconContentObject()).getColorFilter())
+                                .getTint();
+                break;
+            case METADATA_TAG_IMAGE:
+                contentColor =
+                        checkNotNull(checkNotNull(getImageContentObject()).getColorFilter())
+                                .getTint();
+                break;
+            case METADATA_TAG_CUSTOM_CONTENT:
+                break;
+        }
+
+        if (contentColor == null) {
+            contentColor = new ColorProp.Builder(0).build();
+        }
+
+        return new ButtonColors(backgroundColor, contentColor);
+    }
+
+    /** Returns metadata tag set to this Button. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns Button object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * Button. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Button fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Button) {
+            return (Button) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), Builder.TYPE_TO_TAG.values())) {
+            return null;
+        }
+        // Now we are sure that this element is a Button.
+        return new Button(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return checkNotNull(mElement.toLayoutElementProto());
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java
new file mode 100644
index 0000000..3ebfc62
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonColors.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the background and content colors used in a button Tiles component.
+ *
+ * <p>See {@link ButtonDefaults#PRIMARY_COLORS} for the default colors used in a primary styled
+ * {@link Button}. See {@link ButtonDefaults#SECONDARY_COLORS} for the default colors used in a
+ * secondary styled {@link Button}.
+ */
+public class ButtonColors {
+    @NonNull private final ColorProp mBackgroundColor;
+    @NonNull private final ColorProp mContentColor;
+
+    /**
+     * Constructor for {@link ButtonColors} object.
+     *
+     * @param backgroundColor The background color to be used for a button Tiles component. Should
+     *     be in ARGB format.
+     * @param contentColor The content color or tint color to be used for a button Tiles component.
+     *     Should be in ARGB format.
+     */
+    public ButtonColors(@ColorInt int backgroundColor, @ColorInt int contentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mContentColor = argb(contentColor);
+    }
+
+    /**
+     * Constructor for {@link ButtonColors} object.
+     *
+     * @param backgroundColor The background color to be used for a button.
+     * @param contentColor The content color or tint color to be used for a button.
+     */
+    public ButtonColors(@NonNull ColorProp backgroundColor, @NonNull ColorProp contentColor) {
+        mBackgroundColor = backgroundColor;
+        mContentColor = contentColor;
+    }
+
+    /**
+     * Returns a {@link ButtonColors} object, using the current Primary colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ButtonColors primaryButtonColors(@NonNull Colors colors) {
+        return new ButtonColors(colors.getPrimary(), colors.getOnPrimary());
+    }
+
+    /**
+     * Returns a {@link ButtonColors} object, using the current Surface colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ButtonColors secondaryButtonColors(@NonNull Colors colors) {
+        return new ButtonColors(colors.getSurface(), colors.getOnSurface());
+    }
+
+    /** The background color to be used on a button Tiles components. */
+    @NonNull
+    public ColorProp getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    /** The content or tint color to be used on a button Tiles components. */
+    @NonNull
+    public ColorProp getContentColor() {
+        return mContentColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java
new file mode 100644
index 0000000..e98e212
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ButtonDefaults.java
@@ -0,0 +1,60 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by button Tiles components. */
+public class ButtonDefaults {
+    private ButtonDefaults() {}
+
+    /** The default size for standard {@link Button}. */
+    @NonNull public static final DpProp DEFAULT_SIZE = dp(52);
+
+    /** The recommended size for large {@link Button}. */
+    @NonNull public static final DpProp LARGE_SIZE = dp(60);
+
+    /** The recommended size for extra large {@link Button}. */
+    @NonNull public static final DpProp EXTRA_LARGE_SIZE = dp(88);
+
+    /** Returns the recommended icon size for the given size of a {@link Button}. */
+    @NonNull
+    public static DpProp recommendedIconSize(@NonNull DpProp buttonSize) {
+        return recommendedIconSize(buttonSize.getValue());
+    }
+
+    /** Returns the recommended icon size for the given size of a {@link Button}. */
+    @NonNull
+    public static DpProp recommendedIconSize(@Dimension(unit = DP) float buttonSize) {
+        return dp(buttonSize / 2);
+    }
+
+    /** The recommended colors for a primary {@link Button}. */
+    @NonNull
+    public static final ButtonColors PRIMARY_COLORS =
+            ButtonColors.primaryButtonColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link Button}. */
+    @NonNull
+    public static final ButtonColors SECONDARY_COLORS =
+            ButtonColors.secondaryButtonColors(Colors.DEFAULT);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java
new file mode 100644
index 0000000..74732d5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Chip.java
@@ -0,0 +1,682 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_START;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_UNDEFINED;
+import static androidx.wear.protolayout.material.ChipDefaults.DEFAULT_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.DEFAULT_MARGIN_PERCENT;
+import static androidx.wear.protolayout.material.ChipDefaults.HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.ICON_SIZE;
+import static androidx.wear.protolayout.material.ChipDefaults.ICON_SPACER_WIDTH;
+import static androidx.wear.protolayout.material.ChipDefaults.PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.radiusOf;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.ColorFilter;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.Image;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.Background;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.Corner;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tiles component {@link Chip} that represents clickable object with the text, optional label and
+ * optional icon or with custom content.
+ *
+ * <p>The Chip is Stadium shape and has a max height designed to take no more than two lines of text
+ * of {@link Typography#TYPOGRAPHY_BUTTON} style. The {@link Chip} can have an icon horizontally
+ * parallel to the two lines of text. Width of chip can very, and the recommended size is screen
+ * dependent with the recommended margin being applied.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults}.,
+ * e.g. {@link ChipDefaults#PRIMARY_COLORS} to get a color scheme for a primary {@link Chip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Chip chip = new Chip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * Chip myChip = (Chip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Chip} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Chip myChip = Chip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ *
+ * @see  androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder#setContent if this Chip is
+ * used inside of {@link androidx.wear.protolayout.material.layouts.PrimaryLayout}.
+ */
+public class Chip implements LayoutElement {
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with only text.
+     */
+    static final String METADATA_TAG_TEXT = "TXTCHP";
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with icon. */
+    static final String METADATA_TAG_ICON = "ICNCHP";
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with custom
+     * content.
+     */
+    static final String METADATA_TAG_CUSTOM_CONTENT = "CSTCHP";
+
+    @NonNull private final Box mElement;
+
+    Chip(@NonNull Box element) {
+        mElement = element;
+    }
+    /** Builder class for {@link androidx.wear.protolayout.material.Chip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        private static final int NOT_SET = 0;
+        private static final int TEXT = 1;
+        private static final int ICON = 2;
+        private static final int CUSTOM_CONTENT = 3;
+
+        @RestrictTo(Scope.LIBRARY)
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({NOT_SET, TEXT, ICON, CUSTOM_CONTENT})
+        @interface ChipType {}
+
+        @NonNull private final Context mContext;
+        @Nullable private LayoutElement mCustomContent;
+        @Nullable private String mImageResourceId = null;
+        @Nullable private String mPrimaryLabel = null;
+        @Nullable private String mSecondaryLabel = null;
+        @NonNull private final Clickable mClickable;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private ContainerDimension mWidth;
+        @NonNull private DpProp mHeight = DEFAULT_HEIGHT;
+        @NonNull private ChipColors mChipColors = PRIMARY_COLORS;
+        @HorizontalAlignment private int mHorizontalAlign = HORIZONTAL_ALIGN_UNDEFINED;
+        @TypographyName private int mPrimaryLabelTypography;
+        @NonNull private DpProp mHorizontalPadding = HORIZONTAL_PADDING;
+        private boolean mIsScalable = true;
+        private int mMaxLines = 0; // 0 indicates that is not set.
+        @NonNull private String mMetadataTag = "";
+
+        @NonNull static final Map<Integer, String> TYPE_TO_TAG = new HashMap<>();
+
+        static {
+            TYPE_TO_TAG.put(ICON, METADATA_TAG_ICON);
+            TYPE_TO_TAG.put(TEXT, METADATA_TAG_TEXT);
+            TYPE_TO_TAG.put(CUSTOM_CONTENT, METADATA_TAG_CUSTOM_CONTENT);
+        }
+
+        /**
+         * Creates a builder for the {@link Chip} with associated action. It is required to add
+         * content later with setters.
+         *
+         * @param context The application's context.
+         * @param clickable Associated {@link Clickable} for click events. When the Chip is clicked
+         *     it will fire the associated action.
+         * @param deviceParameters The device parameters used to derive defaults for this Chip.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            mContext = context;
+            mClickable = clickable;
+            mWidth =
+                    dp(
+                            (100 - 2 * DEFAULT_MARGIN_PERCENT)
+                                    * deviceParameters.getScreenWidthDp()
+                                    / 100);
+            mPrimaryLabelTypography = Typography.TYPOGRAPHY_BUTTON;
+        }
+
+        /**
+         * Sets the width of {@link Chip}. If not set, default value will be set to fill the screen.
+         */
+        @NonNull
+        public Builder setWidth(@NonNull ContainerDimension width) {
+            mWidth = width;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@Dimension(unit = DP) float width) {
+            mWidth = dp(width);
+            return this;
+        }
+
+        /**
+         * Sets the custom content for the {@link Chip}. Any previously added content will be
+         * overridden.
+         */
+        @NonNull
+        public Builder setCustomContent(@NonNull LayoutElement content) {
+            this.mCustomContent = content;
+            this.mPrimaryLabel = "";
+            this.mSecondaryLabel = "";
+            this.mImageResourceId = "";
+            return this;
+        }
+
+        /**
+         * Sets the content description for the {@link Chip}. It is highly recommended to provide
+         * this for chip containing icon.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the primary label for the {@link Chip}. Any previously added custom content will be
+         * overridden. Primary label can be on 1 or 2 lines, depending on the length and existence
+         * of secondary label.
+         */
+        @NonNull
+        public Builder setPrimaryLabelContent(@NonNull String primaryLabel) {
+            this.mPrimaryLabel = primaryLabel;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Used for creating CompactChip and TitleChip.
+         *
+         * <p>Sets the font for the primary label and should only be used internally.
+         */
+        @NonNull
+        Builder setPrimaryLabelTypography(@TypographyName int typography) {
+            this.mPrimaryLabelTypography = typography;
+            return this;
+        }
+
+        /**
+         * Used for creating CompactChip and TitleChip.
+         *
+         * <p>Sets whether the font for the primary label is scalable.
+         */
+        @NonNull
+        Builder setIsPrimaryLabelScalable(boolean isScalable) {
+            this.mIsScalable = isScalable;
+            return this;
+        }
+
+        /**
+         * Sets the secondary label for the {@link Chip}. Any previously added custom content will
+         * be overridden. If secondary label is set, primary label must be set too with {@link
+         * #setPrimaryLabelContent}.
+         */
+        @NonNull
+        public Builder setSecondaryLabelContent(@NonNull String secondaryLabel) {
+            this.mSecondaryLabel = secondaryLabel;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Sets the icon for the {@link Chip}. Any previously added custom content will be
+         * overridden. Provided icon will be tinted to the given content color from {@link
+         * ChipColors}. This icon should be image with chosen alpha channel and not an actual image.
+         * If icon is set, primary label must be set too with {@link #setPrimaryLabelContent}.
+         */
+        @NonNull
+        public Builder setIconContent(@NonNull String imageResourceId) {
+            this.mImageResourceId = imageResourceId;
+            this.mCustomContent = null;
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link Chip}. If set, {@link ChipColors#getBackgroundColor()}
+         * will be used for the background of the button, {@link ChipColors#getContentColor()} for
+         * main text, {@link ChipColors#getSecondaryContentColor()} for label text and {@link
+         * ChipColors#getIconColor()} will be used as color for the icon itself. If not set, {@link
+         * ChipDefaults#PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /**
+         * Sets the horizontal alignment in the chip. It is strongly recommended that the content of
+         * the chip is start-aligned if there is more than primary text in it. By default, {@link
+         * HorizontalAlignment#HORIZONTAL_ALIGN_CENTER} will be used when only a primary label is
+         * present. Otherwise {@link HorizontalAlignment#HORIZONTAL_ALIGN_START} will be used.
+         */
+        @NonNull
+        public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+            mHorizontalAlign = horizontalAlignment;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setHorizontalPadding(@NonNull DpProp horizontalPadding) {
+            this.mHorizontalPadding = horizontalPadding;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setHeight(@NonNull DpProp height) {
+            this.mHeight = height;
+            return this;
+        }
+
+        /** Used for creating CompactChip and TitleChip. */
+        @NonNull
+        Builder setMaxLines(int maxLines) {
+            this.mMaxLines = maxLines;
+            return this;
+        }
+
+        /** Used for setting the correct tag in CompactChip and TitleChip. */
+        @NonNull
+        Builder setMetadataTag(@NonNull String metadataTag) {
+            this.mMetadataTag = metadataTag;
+            return this;
+        }
+
+        /** Constructs and returns {@link Chip} with the provided content and look. */
+        @NonNull
+        @Override
+        public Chip build() {
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setClickable(mClickable)
+                            .setPadding(
+                                    new Padding.Builder()
+                                            .setStart(mHorizontalPadding)
+                                            .setEnd(mHorizontalPadding)
+                                            .build())
+                            .setBackground(
+                                    new Background.Builder()
+                                            .setColor(mChipColors.getBackgroundColor())
+                                            .setCorner(
+                                                    new Corner.Builder()
+                                                            .setRadius(radiusOf(mHeight))
+                                                            .build())
+                                            .build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(getTagBytes(getCorrectMetadataTag()))
+                                            .build())
+                            .setSemantics(
+                                    new Semantics.Builder()
+                                            .setContentDescription(getCorrectContentDescription())
+                                            .build());
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setWidth(mWidth)
+                            .setHeight(mHeight)
+                            .setHorizontalAlignment(getCorrectHorizontalAlignment())
+                            .addContent(getCorrectContent())
+                            .setModifiers(modifiers.build());
+
+            return new Chip(element.build());
+        }
+
+        @NonNull
+        private String getCorrectContentDescription() {
+            if (mContentDescription.length() == 0) {
+                mContentDescription = "";
+                if (mPrimaryLabel != null) {
+                    mContentDescription += mPrimaryLabel;
+                }
+                if (mSecondaryLabel != null) {
+                    mContentDescription += "\n" + mSecondaryLabel;
+                }
+            }
+            return mContentDescription.toString();
+        }
+
+        @HorizontalAlignment
+        private int getCorrectHorizontalAlignment() {
+            if (mHorizontalAlign != HORIZONTAL_ALIGN_UNDEFINED) {
+                return mHorizontalAlign;
+            }
+            if (mPrimaryLabel != null && mSecondaryLabel == null && mImageResourceId == null) {
+                return HORIZONTAL_ALIGN_CENTER;
+            } else {
+                return HORIZONTAL_ALIGN_START;
+            }
+        }
+
+        private String getCorrectMetadataTag() {
+            if (!mMetadataTag.isEmpty()) {
+                return mMetadataTag;
+            }
+            if (mCustomContent != null) {
+                return METADATA_TAG_CUSTOM_CONTENT;
+            }
+            if (mImageResourceId != null) {
+                return METADATA_TAG_ICON;
+            }
+            return METADATA_TAG_TEXT;
+        }
+
+        @NonNull
+        private LayoutElement getCorrectContent() {
+            if (mCustomContent != null) {
+                return mCustomContent;
+            }
+
+            Text mainTextElement =
+                    new Text.Builder(mContext, checkNotNull(mPrimaryLabel))
+                            .setTypography(mPrimaryLabelTypography)
+                            .setColor(mChipColors.getContentColor())
+                            .setMaxLines(getCorrectMaxLines())
+                            .setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END)
+                            .setMultilineAlignment(LayoutElementBuilders.TEXT_ALIGN_START)
+                            .setIsScalable(mIsScalable)
+                            .build();
+
+            // Placeholder for text.
+            Column.Builder column =
+                    new Column.Builder()
+                            .setHorizontalAlignment(HORIZONTAL_ALIGN_START)
+                            .addContent(putLayoutInBox(mainTextElement).build());
+
+            if (mSecondaryLabel != null) {
+                Text labelTextElement =
+                        new Text.Builder(mContext, mSecondaryLabel)
+                                .setTypography(Typography.TYPOGRAPHY_CAPTION2)
+                                .setColor(mChipColors.getSecondaryContentColor())
+                                .setMaxLines(1)
+                                .setOverflow(LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END)
+                                .setMultilineAlignment(LayoutElementBuilders.TEXT_ALIGN_START)
+                                .build();
+                column.addContent(putLayoutInBox(labelTextElement).build());
+            }
+
+            Box texts = putLayoutInBox(column.build()).build();
+            if (mImageResourceId == null) {
+                return texts;
+            } else {
+                return new Row.Builder()
+                        .addContent(
+                                new Image.Builder()
+                                        .setResourceId(mImageResourceId)
+                                        .setWidth(ICON_SIZE)
+                                        .setHeight(ICON_SIZE)
+                                        .setColorFilter(
+                                                new ColorFilter.Builder()
+                                                        .setTint(mChipColors.getIconColor())
+                                                        .build())
+                                        .build())
+                        .addContent(
+                                new Spacer.Builder()
+                                        .setHeight(mHeight)
+                                        .setWidth(ICON_SPACER_WIDTH)
+                                        .build())
+                        .addContent(texts)
+                        .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                        .build();
+            }
+        }
+
+        private int getCorrectMaxLines() {
+            if (mMaxLines > 0) {
+                return mMaxLines;
+            }
+            return mSecondaryLabel != null ? 1 : 2;
+        }
+
+        private Box.Builder putLayoutInBox(@NonNull LayoutElement element) {
+            // Wrapped and centered content are default.
+            return new Box.Builder().addContent(element);
+        }
+    }
+
+    /** Returns height of this Chip. */
+    @NonNull
+    public ContainerDimension getHeight() {
+        return checkNotNull(mElement.getHeight());
+    }
+
+    /** Returns width of this Chip. */
+    @NonNull
+    public ContainerDimension getWidth() {
+        return checkNotNull(mElement.getWidth());
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return checkNotNull(checkNotNull(mElement.getModifiers()).getClickable());
+    }
+
+    /** Returns background color of this Chip. */
+    @NonNull
+    private ColorProp getBackgroundColor() {
+        return checkNotNull(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getBackground()).getColor());
+    }
+
+    /** Returns chip colors of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        ColorProp backgroundColor = getBackgroundColor();
+        ColorProp contentColor = null;
+        ColorProp secondaryContentColor = null;
+        ColorProp iconTintColor = null;
+
+        if (!getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            if (getMetadataTag().equals(METADATA_TAG_ICON)) {
+                Image icon = checkNotNull(getIconContentObject());
+                iconTintColor = checkNotNull(checkNotNull(icon.getColorFilter()).getTint());
+            }
+
+            contentColor = checkNotNull(getPrimaryLabelContentObject()).getColor();
+            Text label = getSecondaryLabelContentObject();
+            if (label != null) {
+                secondaryContentColor = label.getColor();
+            }
+        }
+
+        // Populate other colors if they are not found.
+        if (contentColor == null) {
+            contentColor = new ColorProp.Builder(0).build();
+        }
+        if (secondaryContentColor == null) {
+            secondaryContentColor = contentColor;
+        }
+        if (iconTintColor == null) {
+            iconTintColor = contentColor;
+        }
+
+        return new ChipColors(backgroundColor, iconTintColor, contentColor, secondaryContentColor);
+    }
+
+    /** Returns content description of this Chip. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /** Returns custom content from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public LayoutElement getCustomContent() {
+        if (getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return checkNotNull(checkNotNull(mElement.getContents()).get(0));
+        }
+        return null;
+    }
+
+    /** Returns primary label from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getPrimaryLabelContent() {
+        Text primaryLabel = getPrimaryLabelContentObject();
+        return primaryLabel != null ? primaryLabel.getText() : null;
+    }
+
+    /** Returns secondary label from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getSecondaryLabelContent() {
+        Text label = getSecondaryLabelContentObject();
+        return label != null ? label.getText() : null;
+    }
+
+    /** Returns icon id from this Chip if it has been added. Otherwise, it returns null. */
+    @Nullable
+    public String getIconContent() {
+        Image icon = getIconContentObject();
+        return icon != null ? checkNotNull(icon.getResourceId()).getValue() : null;
+    }
+
+    @Nullable
+    private Text getPrimaryLabelContentObject() {
+        return getPrimaryOrSecondaryLabelContent(0);
+    }
+
+    @Nullable
+    private Text getSecondaryLabelContentObject() {
+        return getPrimaryOrSecondaryLabelContent(1);
+    }
+
+    @Nullable
+    private Image getIconContentObject() {
+        if (!getMetadataTag().equals(METADATA_TAG_ICON)) {
+            return null;
+        }
+        return ((Image) ((Row) mElement.getContents().get(0)).getContents().get(0));
+    }
+
+    @Nullable
+    private Text getPrimaryOrSecondaryLabelContent(int index) {
+        String metadataTag = getMetadataTag();
+        if (metadataTag.equals(METADATA_TAG_CUSTOM_CONTENT)) {
+            return null;
+        }
+        // In any other case, text (either primary or primary + label) must be present.
+        Column content;
+        if (metadataTag.equals(METADATA_TAG_ICON)) {
+            content =
+                    (Column)
+                            ((Box) ((Row) mElement.getContents().get(0)).getContents().get(2))
+                                    .getContents()
+                                    .get(0);
+        } else {
+            content = (Column) ((Box) mElement.getContents().get(0)).getContents().get(0);
+        }
+
+        // We need to check this as this can be the case when we called for label, which doesn't
+        // exist.
+        return index < content.getContents().size()
+                ? Text.fromLayoutElement(
+                        ((Box) content.getContents().get(index)).getContents().get(0))
+                : null;
+    }
+
+    /** Returns the horizontal alignment of the content in this Chip. */
+    @HorizontalAlignment
+    public int getHorizontalAlignment() {
+        return checkNotNull(mElement.getHorizontalAlignment()).getValue();
+    }
+
+    /** Returns metadata tag set to this Chip. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns Chip object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * Chip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Chip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Chip) {
+            return (Chip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), Builder.TYPE_TO_TAG.values())) {
+            return null;
+        }
+        // Now we are sure that this element is a Chip.
+        return new Chip(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java
new file mode 100644
index 0000000..a24e6c4
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipColors.java
@@ -0,0 +1,150 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the background and content colors used in a chip Tiles component.
+ *
+ * <p>See {@link ChipDefaults#PRIMARY_COLORS} for the default colors used in a primary styled {@link
+ * Chip}. See {@link ChipDefaults#SECONDARY_COLORS} for the default colors used in a secondary
+ * styled {@link Chip}.
+ */
+public class ChipColors {
+    @NonNull private final ColorProp mBackgroundColor;
+    @NonNull private final ColorProp mIconColor;
+    @NonNull private final ColorProp mContentColor;
+    @NonNull private final ColorProp mSecondaryContentColor;
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component. Should be
+     *     in ARGB format.
+     * @param iconColor The color to be used for an icon in a chip Tiles component. Should be in
+     *     ARGB format.
+     * @param contentColor The text color to be used for a main text in a chip Tiles component.
+     *     Should be in ARGB format.
+     * @param secondaryContentColor The text color to be used for a label text in a chip Tiles
+     *     component. Should be in ARGB format.
+     */
+    public ChipColors(
+            @ColorInt int backgroundColor,
+            @ColorInt int iconColor,
+            @ColorInt int contentColor,
+            @ColorInt int secondaryContentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mIconColor = argb(iconColor);
+        mContentColor = argb(contentColor);
+        mSecondaryContentColor = argb(secondaryContentColor);
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component. Should be
+     *     in ARGB format.
+     * @param contentColor The content color to be used for all items inside a chip Tiles component.
+     *     Should be in ARGB format.
+     */
+    public ChipColors(@ColorInt int backgroundColor, @ColorInt int contentColor) {
+        mBackgroundColor = argb(backgroundColor);
+        mIconColor = argb(contentColor);
+        mContentColor = argb(contentColor);
+        mSecondaryContentColor = argb(contentColor);
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component.
+     * @param iconColor The color to be used for an icon in a chip Tiles component.
+     * @param contentColor The text color to be used for a main text in a chip Tiles component.
+     * @param secondaryContentColor The text color to be used for a label text in a chip Tiles
+     *     component.
+     */
+    public ChipColors(
+            @NonNull ColorProp backgroundColor,
+            @NonNull ColorProp iconColor,
+            @NonNull ColorProp contentColor,
+            @NonNull ColorProp secondaryContentColor) {
+        mBackgroundColor = backgroundColor;
+        mIconColor = iconColor;
+        mContentColor = contentColor;
+        mSecondaryContentColor = secondaryContentColor;
+    }
+
+    /**
+     * Constructor for the {@link ChipColors} object.
+     *
+     * @param backgroundColor The background color to be used for a chip Tiles component.
+     * @param contentColor The content color to be used for all items inside a chip Tiles component.
+     */
+    public ChipColors(@NonNull ColorProp backgroundColor, @NonNull ColorProp contentColor) {
+        mBackgroundColor = backgroundColor;
+        mIconColor = contentColor;
+        mContentColor = contentColor;
+        mSecondaryContentColor = contentColor;
+    }
+
+    /**
+     * Returns a {@link ChipColors} object, using the current Primary colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ChipColors primaryChipColors(@NonNull Colors colors) {
+        return new ChipColors(colors.getPrimary(), colors.getOnPrimary());
+    }
+
+    /**
+     * Returns a {@link ChipColors} object, using the current Surface colors from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ChipColors secondaryChipColors(@NonNull Colors colors) {
+        return new ChipColors(colors.getSurface(), colors.getOnSurface());
+    }
+
+    /** The background color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getBackgroundColor() {
+        return mBackgroundColor;
+    }
+
+    /** The icon color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getIconColor() {
+        return mIconColor;
+    }
+
+    /** The main text color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getContentColor() {
+        return mContentColor;
+    }
+
+    /** The label text color to be used on a chip Tiles components. */
+    @NonNull
+    public ColorProp getSecondaryContentColor() {
+        return mSecondaryContentColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java
new file mode 100644
index 0000000..8059369
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ChipDefaults.java
@@ -0,0 +1,137 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by chip Tiles components. */
+public class ChipDefaults {
+    private ChipDefaults() {}
+
+    /**
+     * The default height for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp DEFAULT_HEIGHT = dp(52);
+
+    /**
+     * The default height for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HEIGHT = dp(32);
+
+    /**
+     * The default height of tappable area for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HEIGHT_TAPPABLE = dp(48);
+
+    /**
+     * The default height for standard {@link TitleChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp TITLE_HEIGHT = dp(60);
+
+    /**
+     * The recommended horizontal margin used for width for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public static final float DEFAULT_MARGIN_PERCENT = 5.2f;
+
+    /**
+     * The recommended horizontal padding for standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp HORIZONTAL_PADDING = dp(14);
+
+    /**
+     * The recommended horizontal padding for standard {@link CompactChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp COMPACT_HORIZONTAL_PADDING = dp(12);
+
+    /**
+     * The recommended horizontal padding for standard {@link TitleChip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp TITLE_HORIZONTAL_PADDING = dp(16);
+
+    /**
+     * The recommended vertical space between icon and text in standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp ICON_SPACER_WIDTH = dp(6);
+
+    /**
+     * The icon size used in standard {@link Chip}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp ICON_SIZE = dp(24);
+
+    /** The recommended colors for a primary {@link Chip}. */
+    @NonNull
+    public static final ChipColors PRIMARY_COLORS = ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link Chip}. */
+    @NonNull
+    public static final ChipColors SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a primary {@link CompactChip}. */
+    @NonNull
+    public static final ChipColors COMPACT_PRIMARY_COLORS =
+            ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link CompactChip}. */
+    @NonNull
+    public static final ChipColors COMPACT_SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a primary {@link TitleChip}. */
+    @NonNull
+    public static final ChipColors TITLE_PRIMARY_COLORS =
+            ChipColors.primaryChipColors(Colors.DEFAULT);
+
+    /** The recommended colors for a secondary {@link TitleChip}. */
+    @NonNull
+    public static final ChipColors TITLE_SECONDARY_COLORS =
+            ChipColors.secondaryChipColors(Colors.DEFAULT);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
new file mode 100644
index 0000000..820be12
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CircularProgressIndicator.java
@@ -0,0 +1,354 @@
+/*
+ * 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.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.degrees;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_COLORS;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_END_ANGLE;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_START_ANGLE;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_STROKE_WIDTH;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.FloatRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DegreesProp;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Arc;
+import androidx.wear.protolayout.LayoutElementBuilders.ArcLine;
+import androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.ModifiersBuilders.Semantics;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link CircularProgressIndicator} that represents circular progress indicator
+ * which supports a gap in the circular track between startAngle and endAngle. [Progress Indicator
+ * doc] (https://developer.android.com/training/wearables/components/progress-indicator)
+ *
+ * <p>The CircularProgressIndicator is a colored arc around the edge of the screen with the given
+ * start and end angles, which can describe a full or partial circle. Behind it is an arc with
+ * optional gap representing full progress. The recommended sizes are defined in {@link
+ * ProgressIndicatorDefaults}. Unless specified, the CircularProgressIndicator will have the full
+ * length.
+ *
+ * <p>The recommended set of {@link ProgressIndicatorColors} can be obtained from {@link
+ * ProgressIndicatorDefaults}, e.g. {@link ProgressIndicatorDefaults#DEFAULT_COLORS} to get a
+ * default color scheme for a {@link CircularProgressIndicator}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * CircularProgressIndicator cpi = new CircularProgressIndicator...
+ * Box box = new Box.Builder().addContent(cpi).build();
+ *
+ * CircularProgressIndicator myCpi = (CircularProgressIndicator) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link CircularProgressIndicator} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * CircularProgressIndicator myCpi =
+ *   CircularProgressIndicator.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class CircularProgressIndicator implements LayoutElement {
+    /**
+     * Tool tag for Metadata in Modifiers, so we know that Arc is actually a
+     * CircularProgressIndicator.
+     */
+    static final String METADATA_TAG = "CPI";
+
+    @NonNull private final Arc mElement;
+    @NonNull private final ArcLine mProgress;
+    @NonNull private final ArcLine mBackground;
+
+    CircularProgressIndicator(@NonNull Arc element) {
+        this.mElement = element;
+        this.mBackground = (ArcLine) element.getContents().get(0);
+        this.mProgress = (ArcLine) element.getContents().get(2);
+    }
+
+    /** Builder class for {@link CircularProgressIndicator} */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private ProgressIndicatorColors mCircularProgressIndicatorColors = DEFAULT_COLORS;
+        @NonNull private DpProp mStrokeWidth = DEFAULT_STROKE_WIDTH;
+        @NonNull private CharSequence mContentDescription = "";
+        @NonNull private DegreesProp mStartAngle = degrees(DEFAULT_START_ANGLE);
+        @NonNull private DegreesProp mEndAngle = degrees(DEFAULT_END_ANGLE);
+
+        @FloatRange(from = 0, to = 1)
+        private float mProgress = 0;
+
+        /** Creates a builder for the {@link CircularProgressIndicator}. */
+        public Builder() {}
+
+        /**
+         * Sets the progress of the {@link CircularProgressIndicator}. Progress should be percentage
+         * from 0 to 1. Progress will be colored in {@link ProgressIndicatorColors#getTrackColor}.
+         * If not set, 0 will be used.
+         */
+        @NonNull
+        public Builder setProgress(@FloatRange(from = 0, to = 1) float progressPercentage) {
+            this.mProgress = progressPercentage;
+            return this;
+        }
+
+        /**
+         * Sets the start angle of the {@link CircularProgressIndicator}'s background arc, where
+         * angle 0 is 12 o'clock. Start angle doesn't need to be within 0-360 range. I.e. -90 is to
+         * start arc from the 9 o'clock. If not set 0 will be used and the indicator will have full
+         * length.
+         */
+        @NonNull
+        public Builder setStartAngle(float startAngle) {
+            this.mStartAngle = degrees(startAngle);
+            return this;
+        }
+
+        /**
+         * Sets the end angle of the {@link CircularProgressIndicator}'s background arc, where angle
+         * 0 is 12 o'clock. End angle doesn't need to be within 0-360 range, but it must be larger
+         * than start angle. If not set 360 will be used and the indicator will have full length.
+         */
+        @NonNull
+        public Builder setEndAngle(float endAngle) {
+            this.mEndAngle = degrees(endAngle);
+            return this;
+        }
+
+        /**
+         * Sets the content description of the {@link CircularProgressIndicator} to be used for
+         * accessibility support.
+         */
+        @NonNull
+        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
+            this.mContentDescription = contentDescription;
+            return this;
+        }
+
+        /**
+         * Sets the colors for the {@link CircularProgressIndicator}. If set, {@link
+         * ProgressIndicatorColors#getIndicatorColor()} will be used for a progress that has been
+         * made, while {@link ProgressIndicatorColors#getTrackColor()} will be used for a background
+         * full size arc. If not set, {@link ProgressIndicatorDefaults#DEFAULT_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setCircularProgressIndicatorColors(
+                @NonNull ProgressIndicatorColors circularProgressIndicatorColors) {
+            this.mCircularProgressIndicatorColors = circularProgressIndicatorColors;
+            return this;
+        }
+
+        /**
+         * Sets the stroke width of the {@link CircularProgressIndicator}. Strongly recommended
+         * value is {@link ProgressIndicatorDefaults#DEFAULT_STROKE_WIDTH}.
+         */
+        @NonNull
+        public Builder setStrokeWidth(@NonNull DpProp strokeWidth) {
+            this.mStrokeWidth = strokeWidth;
+            return this;
+        }
+
+        /**
+         * Sets the stroke width of the {@link CircularProgressIndicator}. Strongly recommended
+         * value is {@link ProgressIndicatorDefaults#DEFAULT_STROKE_WIDTH}.
+         */
+        @NonNull
+        public Builder setStrokeWidth(@Dimension(unit = DP) float strokeWidth) {
+            this.mStrokeWidth = dp(strokeWidth);
+            return this;
+        }
+
+        /**
+         * Constructs and returns {@link CircularProgressIndicator} with the provided field and
+         * look.
+         */
+        @NonNull
+        @Override
+        public CircularProgressIndicator build() {
+            checkAngles();
+
+            DegreesProp length = getLength();
+            Modifiers.Builder modifiers =
+                    new Modifiers.Builder()
+                            .setPadding(new Padding.Builder().setAll(DEFAULT_PADDING).build())
+                            .setMetadata(
+                                    new ElementMetadata.Builder()
+                                            .setTagData(getTagBytes(METADATA_TAG))
+                                            .build());
+
+            if (mContentDescription.length() > 0) {
+                modifiers.setSemantics(
+                        new ModifiersBuilders.Semantics.Builder()
+                                .setContentDescription(mContentDescription.toString())
+                                .build());
+            }
+
+            Arc.Builder element =
+                    new Arc.Builder()
+                            .setAnchorType(LayoutElementBuilders.ARC_ANCHOR_START)
+                            .setAnchorAngle(mStartAngle)
+                            .setModifiers(modifiers.build())
+                            .addContent(
+                                    new ArcLine.Builder()
+                                            .setColor(
+                                                    mCircularProgressIndicatorColors
+                                                            .getTrackColor())
+                                            .setThickness(mStrokeWidth)
+                                            .setLength(length)
+                                            .build())
+                            .addContent(
+                                    // Fill in the space to make a full circle, so that progress is
+                                    // correctly aligned.
+                                    new ArcSpacer.Builder()
+                                            .setLength(degrees(360 - length.getValue()))
+                                            .build())
+                            .addContent(
+                                    new ArcLine.Builder()
+                                            .setColor(
+                                                    mCircularProgressIndicatorColors
+                                                            .getIndicatorColor())
+                                            .setThickness(mStrokeWidth)
+                                            .setLength(degrees(mProgress * length.getValue()))
+                                            .build());
+            return new CircularProgressIndicator(element.build());
+        }
+
+        private void checkAngles() {
+            if (mEndAngle.getValue() < mStartAngle.getValue()) {
+                throw new IllegalArgumentException("End angle must be bigger than start angle.");
+            }
+        }
+
+        @NonNull
+        private DegreesProp getLength() {
+            float startAngle = mStartAngle.getValue();
+            float endAngle = mEndAngle.getValue();
+            if (endAngle <= startAngle) {
+                endAngle += 360;
+            }
+            return degrees(endAngle - startAngle);
+        }
+    }
+
+    /** Returns angle representing progressed part of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getProgress() {
+        return checkNotNull(mProgress.getLength());
+    }
+
+    /** Returns stroke width of this CircularProgressIndicator. */
+    @NonNull
+    public DpProp getStrokeWidth() {
+        return checkNotNull(mProgress.getThickness());
+    }
+
+    /** Returns start angle of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getStartAngle() {
+        return checkNotNull(mElement.getAnchorAngle());
+    }
+
+    /** Returns start angle of this CircularProgressIndicator. */
+    @NonNull
+    public DegreesProp getEndAngle() {
+        float backArcLength = checkNotNull(mBackground.getLength()).getValue();
+        return degrees(getStartAngle().getValue() + backArcLength);
+    }
+
+    /** Returns main arc color of this CircularProgressIndicator. */
+    @NonNull
+    public ProgressIndicatorColors getCircularProgressIndicatorColors() {
+        return new ProgressIndicatorColors(
+                checkNotNull(mProgress.getColor()), checkNotNull(mBackground.getColor()));
+    }
+
+    /** Returns content description of this CircularProgressIndicator. */
+    @Nullable
+    public CharSequence getContentDescription() {
+        Semantics semantics = checkNotNull(mElement.getModifiers()).getSemantics();
+        if (semantics == null) {
+            return null;
+        }
+        return semantics.getContentDescription();
+    }
+
+    /**
+     * Returns metadata tag set to this CircularProgressIndicator, which should be {@link
+     * #METADATA_TAG}.
+     */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns CircularProgressIndicator object from the given LayoutElement (e.g. one retrieved
+     * from a container's content with {@code container.getContents().get(index)}) if that element
+     * can be converted to CircularProgressIndicator. Otherwise, it will return null.
+     */
+    @Nullable
+    public static CircularProgressIndicator fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof CircularProgressIndicator) {
+            return (CircularProgressIndicator) element;
+        }
+        if (!(element instanceof Arc)) {
+            return null;
+        }
+        Arc arcElement = (Arc) element;
+        if (!checkTag(arcElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a CircularProgressIndicator.
+        return new CircularProgressIndicator(arcElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java
new file mode 100644
index 0000000..84026bd
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Colors.java
@@ -0,0 +1,119 @@
+/*
+ * 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.protolayout.material;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+
+/**
+ * Represent the container for default color scheme in your Tile, that can be used to create color
+ * objects for all Material components.
+ *
+ * <p>See {@link #DEFAULT} for default color scheme.
+ */
+public class Colors {
+
+    /**
+     * The default color used for primary elements (i.e. background color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int PRIMARY = 0xFFAECBFA;
+
+    /**
+     * The default color used on primary elements (i.e. content color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int ON_PRIMARY = 0xFF303133;
+
+    /**
+     * The default color used for secondary elements (i.e. background color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int SURFACE = 0xFF303133;
+
+    /**
+     * The default color used on secondary elements (i.e. content color).
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @ColorInt
+    public static final int ON_SURFACE = 0xFFFFFFFF;
+
+    /** The default color scheme to be used in Tiles Material components. */
+    @NonNull
+    public static final Colors DEFAULT = new Colors(PRIMARY, ON_PRIMARY, SURFACE, ON_SURFACE);
+
+    private @ColorInt final int mPrimary;
+    private @ColorInt final int mOnPrimary;
+    private @ColorInt final int mSurface;
+    private @ColorInt final int mOnSurface;
+
+    /**
+     * Constructor for {@link Colors} object.
+     *
+     * @param primary The background color to be used for primary components. Should be in ARGB
+     *     format.
+     * @param onPrimary The content color or tint color to be used for primary components. Should be
+     *     in ARGB format.
+     * @param surface The background color to be used for secondary components. Should be in ARGB
+     *     format.
+     * @param onSurface The content color or tint color to be used for secondary components. Should
+     *     be in ARGB format.
+     */
+    public Colors(
+            @ColorInt int primary,
+            @ColorInt int onPrimary,
+            @ColorInt int surface,
+            @ColorInt int onSurface) {
+        this.mPrimary = primary;
+        this.mOnPrimary = onPrimary;
+        this.mSurface = surface;
+        this.mOnSurface = onSurface;
+    }
+
+    /** The primary color to be used on components. */
+    @ColorInt
+    public int getPrimary() {
+        return mPrimary;
+    }
+
+    /** The onPrimary color to be used on components. */
+    @ColorInt
+    public int getOnPrimary() {
+        return mOnPrimary;
+    }
+
+    /** The surface color to be used on components. */
+    @ColorInt
+    public int getSurface() {
+        return mSurface;
+    }
+
+    /** The onSurface color to be used on components. */
+    @ColorInt
+    public int getOnSurface() {
+        return mOnSurface;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java
new file mode 100644
index 0000000..58bf3b8
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/CompactChip.java
@@ -0,0 +1,234 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT_TAPPABLE;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link CompactChip} that represents clickable object with the text.
+ *
+ * <p>The Chip is Stadium shape and has a max height designed to take no more than one line of text
+ * of {@link Typography#TYPOGRAPHY_CAPTION1} style. Width of the chip is adjustable to the text
+ * size.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults}.,
+ * e.g. {@link ChipDefaults#COMPACT_PRIMARY_COLORS} to get a color scheme for a primary {@link
+ * CompactChip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * CompactChip chip = new CompactChip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * CompactChip myChip = (CompactChip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link CompactChip} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * CompactChip myChip = CompactChip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class CompactChip implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a CompactChip. */
+    static final String METADATA_TAG = "CMPCHP";
+
+    @NonNull private final Box mImpl;
+    @NonNull private final Chip mElement;
+
+    CompactChip(@NonNull Box element) {
+        this.mImpl = element;
+        // We know for sure that content of the Box is Chip.
+        this.mElement = new Chip((Box) element.getContents().get(0));
+    }
+
+    /** Builder class for {@link androidx.wear.protolayout.material.CompactChip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private final String mText;
+        @NonNull private final Clickable mClickable;
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @NonNull private ChipColors mChipColors = COMPACT_PRIMARY_COLORS;
+
+        /**
+         * Creates a builder for the {@link CompactChip} with associated action and the given text
+         *
+         * @param context The application's context.
+         * @param text The text to be displayed in this compact chip.
+         * @param clickable Associated {@link Clickable} for click events. When the CompactChip is
+         *     clicked it will fire the associated action.
+         * @param deviceParameters The device parameters used for styling text.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull String text,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            this.mContext = context;
+            this.mText = text;
+            this.mClickable = clickable;
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the colors for the {@link CompactChip}. If set, {@link
+         * ChipColors#getBackgroundColor()} will be used for the background of the button and {@link
+         * ChipColors#getContentColor()} for the text. If not set, {@link
+         * ChipDefaults#COMPACT_PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /** Constructs and returns {@link CompactChip} with the provided content and look. */
+        @NonNull
+        @Override
+        public CompactChip build() {
+            Chip.Builder chipBuilder =
+                    new Chip.Builder(mContext, mClickable, mDeviceParameters)
+                            .setMetadataTag(METADATA_TAG)
+                            .setChipColors(mChipColors)
+                            .setContentDescription(mText)
+                            .setHorizontalAlignment(HORIZONTAL_ALIGN_CENTER)
+                            .setWidth(wrap())
+                            .setHeight(COMPACT_HEIGHT)
+                            .setMaxLines(1)
+                            .setHorizontalPadding(COMPACT_HORIZONTAL_PADDING)
+                            .setPrimaryLabelContent(mText)
+                            .setPrimaryLabelTypography(Typography.TYPOGRAPHY_CAPTION1)
+                            .setIsPrimaryLabelScalable(false);
+
+            Box tappableChip =
+                    new Box.Builder()
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setClickable(mClickable)
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(getTagBytes(METADATA_TAG))
+                                                            .build())
+                                            .build())
+                            .setWidth(wrap())
+                            .setHeight(COMPACT_HEIGHT_TAPPABLE)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .addContent(chipBuilder.build())
+                            .build();
+
+            return new CompactChip(tappableChip);
+        }
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return mElement.getClickable();
+    }
+
+    /** Returns chip color of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        return mElement.getChipColors();
+    }
+
+    /** Returns text content of this Chip. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(mElement.getPrimaryLabelContent());
+    }
+
+    /** Returns metadata tag set to this CompactChip, which should be {@link #METADATA_TAG}. */
+    @NonNull
+    String getMetadataTag() {
+        return mElement.getMetadataTag();
+    }
+
+    /**
+     * Returns CompactChip object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to CompactChip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static CompactChip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof CompactChip) {
+            return (CompactChip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now to check that inner content of the Box is CompactChip's Chip.
+        LayoutElement innerElement = boxElement.getContents().get(0);
+        if (!(innerElement instanceof Box)) {
+            return null;
+        }
+        Box innerBoxElement = (Box) innerElement;
+        if (!checkTag(innerBoxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+
+        // Now we are sure that this element is a CompactChip.
+        return new CompactChip(boxElement);
+    }
+
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    @Override
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}
diff --git a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt
similarity index 78%
rename from compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
rename to wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt
index 3d299bc..8f2cad2 100644
--- a/compose/foundation/foundation-newtext/src/commonMain/kotlin/androidx/compose/foundation/newtext/text/copypasta/TextPointerIcon.kt
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/DeleteMe.kt
@@ -1,4 +1,4 @@
-/*
+package androidx.wear.protolayout.material/*
  * Copyright 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,8 +14,4 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.newtext.text.copypasta
-
-import androidx.compose.ui.input.pointer.PointerIcon
-
-internal expect val textPointerIcon: PointerIcon
\ No newline at end of file
+// This file exists to trick AGP/lint to work around b/234865137
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java
new file mode 100644
index 0000000..630bf29
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Helper.java
@@ -0,0 +1,134 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Helper class used for Tiles Material.
+ *
+ */
+@RestrictTo(Scope.LIBRARY_GROUP)
+public class Helper {
+    private Helper() {}
+
+    /**
+     * Returns given value if not null or throws {@code NullPointerException} otherwise.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static <T> T checkNotNull(@Nullable T value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+        return value;
+    }
+
+    /** Returns radius in {@link DpProp} of the given diameter. */
+    @NonNull
+    static DpProp radiusOf(DpProp diameter) {
+        return dp(diameter.getValue() / 2);
+    }
+
+    /**
+     * Returns true if the given DeviceParameters belong to the round screen device.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public static boolean isRoundDevice(@NonNull DeviceParameters deviceParameters) {
+        return deviceParameters.getScreenShape() == DeviceParametersBuilders.SCREEN_SHAPE_ROUND;
+    }
+
+    /**
+     * Returns String representation of tag from byte array.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static String getTagName(@NonNull byte[] tagData) {
+        return new String(tagData, StandardCharsets.UTF_8);
+    }
+
+    /**
+     * Returns byte array representation of tag from String.
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static byte[] getTagBytes(@NonNull String tagName) {
+        return tagName.getBytes(StandardCharsets.UTF_8);
+    }
+
+    /** Returns the String representation of metadata tag from the given ElementMetadata. */
+    @NonNull
+    public static String getMetadataTagName(@NonNull ElementMetadata metadata) {
+        return getTagName(getMetadataTagBytes(metadata));
+    }
+
+    /** Returns the metadata tag from the given ElementMetadata. */
+    @NonNull
+    public static byte[] getMetadataTagBytes(@NonNull ElementMetadata metadata) {
+        return checkNotNull(metadata).getTagData();
+    }
+
+    /** Returns true if the given Modifiers have Metadata tag set to the given String value. */
+    public static boolean checkTag(@Nullable Modifiers modifiers, @NonNull String validTag) {
+        return modifiers != null
+                && modifiers.getMetadata() != null
+                && validTag.equals(getMetadataTagName(modifiers.getMetadata()));
+    }
+
+    /**
+     * Returns true if the given Modifiers have Metadata tag set to any of the value in the given
+     * String collection.
+     */
+    public static boolean checkTag(
+            @Nullable Modifiers modifiers, @NonNull Collection<String> validTags) {
+        return modifiers != null
+                && modifiers.getMetadata() != null
+                && validTags.contains(getMetadataTagName(modifiers.getMetadata()));
+    }
+
+    /**
+     * Returns true if the given Modifiers have Metadata tag set with prefix that is equal to the
+     * given String and its length is of the given base array.
+     */
+    public static boolean checkTag(
+            @Nullable Modifiers modifiers, @NonNull String validPrefix, @NonNull byte[] validBase) {
+        if (modifiers == null || modifiers.getMetadata() == null) {
+            return false;
+        }
+        byte[] metadataTag = getMetadataTagBytes(modifiers.getMetadata());
+        byte[] tag = Arrays.copyOf(metadataTag, validPrefix.length());
+        return metadataTag.length == validBase.length && validPrefix.equals(getTagName(tag));
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java
new file mode 100644
index 0000000..668fe3e
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorColors.java
@@ -0,0 +1,83 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+
+/**
+ * Represents the indicator and track colors used in a progress indicator Tiles component.
+ *
+ * <p>See {@link ProgressIndicatorDefaults#DEFAULT_COLORS} for the default colors used in a {@link
+ * CircularProgressIndicator}.
+ */
+public class ProgressIndicatorColors {
+    @NonNull private final ColorProp mIndicatorColor;
+    @NonNull private final ColorProp mTrackColor;
+
+    /**
+     * Constructor for {@link ProgressIndicatorColors} object.
+     *
+     * @param indicatorColor The indicator color to be used for a progress indicator Tiles
+     *     component.
+     * @param trackColor The background track color to be used for a progress indicator Tiles
+     *     component.
+     */
+    public ProgressIndicatorColors(
+            @NonNull ColorProp indicatorColor, @NonNull ColorProp trackColor) {
+        this.mIndicatorColor = indicatorColor;
+        this.mTrackColor = trackColor;
+    }
+
+    /**
+     * Constructor for {@link ProgressIndicatorColors} object.
+     *
+     * @param indicatorColor The indicator color to be used for a progress indicator Tiles
+     *     component. Should be in ARGB format.
+     * @param trackColor The background track color to be used for a progress indicator Tiles
+     *     component. Should be in ARGB format.
+     */
+    public ProgressIndicatorColors(@ColorInt int indicatorColor, @ColorInt int trackColor) {
+        this.mIndicatorColor = argb(indicatorColor);
+        this.mTrackColor = argb(trackColor);
+    }
+
+    /**
+     * Returns a {@link ProgressIndicatorColors} object, using the current Primary color for
+     * indicator color and the current Surface color for the track color from the given {@link
+     * Colors}.
+     */
+    @NonNull
+    public static ProgressIndicatorColors progressIndicatorColors(@NonNull Colors colors) {
+        return new ProgressIndicatorColors(colors.getPrimary(), colors.getSurface());
+    }
+
+    /** The indicator color to be used for a progress indicator Tiles component. */
+    @NonNull
+    public ColorProp getIndicatorColor() {
+        return mIndicatorColor;
+    }
+
+    /** The background track color to be used for a progress indicator Tiles component. */
+    @NonNull
+    public ColorProp getTrackColor() {
+        return mTrackColor;
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java
new file mode 100644
index 0000000..dd2f9cf
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/ProgressIndicatorDefaults.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.material;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+
+/** Contains the default values used by {@link CircularProgressIndicator} Tiles components. */
+public class ProgressIndicatorDefaults {
+    private ProgressIndicatorDefaults() {}
+
+    /** The default stroke width for {@link CircularProgressIndicator} */
+    @NonNull public static final DpProp DEFAULT_STROKE_WIDTH = dp(8);
+
+    /**
+     * The default padding for {@link CircularProgressIndicator}
+     *
+     */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static final DpProp DEFAULT_PADDING = dp(6);
+
+    /** The recommended colors for {@link CircularProgressIndicator}. */
+    @NonNull
+    public static final ProgressIndicatorColors DEFAULT_COLORS =
+            ProgressIndicatorColors.progressIndicatorColors(Colors.DEFAULT);
+
+    static final float DEFAULT_GAP_LENGTH = 47.8f;
+
+    /** The recommended start angle for {@link CircularProgressIndicator} if there's a gap. */
+    public static final float GAP_START_ANGLE = 180 + DEFAULT_GAP_LENGTH / 2 - 360;
+
+    /** The recommended end angle for {@link CircularProgressIndicator} if there's a gap. */
+    public static final float GAP_END_ANGLE = 180 - DEFAULT_GAP_LENGTH / 2;
+
+    /** Start angle for full length {@link CircularProgressIndicator}. */
+    static final float DEFAULT_START_ANGLE = 0;
+
+    /** End angle for full length {@link CircularProgressIndicator}. */
+    static final float DEFAULT_END_ANGLE = 360;
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java
new file mode 100644
index 0000000..ed5e309
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Text.java
@@ -0,0 +1,318 @@
+/*
+ * 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.wear.protolayout.material;
+
+import static androidx.wear.protolayout.ColorBuilders.argb;
+import static androidx.wear.protolayout.LayoutElementBuilders.TEXT_ALIGN_CENTER;
+import static androidx.wear.protolayout.LayoutElementBuilders.TEXT_OVERFLOW_ELLIPSIZE_END;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Typography.TYPOGRAPHY_DISPLAY1;
+import static androidx.wear.protolayout.material.Typography.getFontStyleBuilder;
+import static androidx.wear.protolayout.material.Typography.getLineHeightForTypography;
+
+import android.content.Context;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.ColorBuilders.ColorProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.FontStyle;
+import androidx.wear.protolayout.LayoutElementBuilders.FontWeight;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.TextAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.TextOverflow;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Typography.TypographyName;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link Text} that represents text object holding any information.
+ *
+ * <p>There are pre-built typography styles that can be obtained from constants in {@link
+ * FontStyle}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * Text text = new Text...
+ * Box box = new Box.Builder().addContent(text).build();
+ *
+ * Text myText = (Text) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link Text} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * Text myText = Text.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class Text implements LayoutElement {
+
+    @NonNull private final LayoutElementBuilders.Text mText;
+
+    Text(@NonNull LayoutElementBuilders.Text mText) {
+        this.mText = mText;
+    }
+
+    /** Builder class for {@link Text}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private String mTextContent = "";
+        @NonNull private ColorProp mColor = argb(Colors.DEFAULT.getOnPrimary());
+        private @TypographyName int mTypographyName = TYPOGRAPHY_DISPLAY1;
+        private boolean mItalic = false;
+        private int mMaxLines = 1;
+        private boolean mUnderline = false;
+        @TextAlignment private int mMultilineAlignment = TEXT_ALIGN_CENTER;
+        @NonNull private Modifiers mModifiers = new Modifiers.Builder().build();
+        private @TextOverflow int mOverflow = TEXT_OVERFLOW_ELLIPSIZE_END;
+        private boolean mIsScalable = true;
+        @Nullable private Integer mCustomWeight = null;
+
+        /**
+         * Creates a builder for {@link Text}.
+         *
+         * @param context The application's context.
+         * @param text The text content for this component.
+         */
+        public Builder(@NonNull Context context, @NonNull String text) {
+            mContext = context;
+            mTextContent = text;
+        }
+
+        /**
+         * Sets the typography for the {@link Text}. If not set, {@link
+         * Typography#TYPOGRAPHY_DISPLAY1} will be used.
+         */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is getFontStyle matching getter for this setter as the serialized format of the
+        // Tiles do not allow for a direct reconstruction of the all arguments, but it has FontStyle
+        // object of that text.
+        public Builder setTypography(@TypographyName int typography) {
+            this.mTypographyName = typography;
+            return this;
+        }
+
+        /**
+         * Sets whether the text size will change if user has changed the default font size. If not
+         * set, true will be used.
+         */
+        Builder setIsScalable(boolean isScalable) {
+            this.mIsScalable = isScalable;
+            return this;
+        }
+
+        /**
+         * Sets the color for the {@link Text}. If not set, onPrimary color from the {@link
+         * Colors#DEFAULT} will be used.
+         */
+        @NonNull
+        public Builder setColor(@NonNull ColorProp color) {
+            this.mColor = color;
+            return this;
+        }
+
+        /** Sets the text to be italic. If not set, false will be used. */
+        @NonNull
+        public Builder setItalic(boolean italic) {
+            this.mItalic = italic;
+            return this;
+        }
+
+        /** Sets the text to be underlined. If not set, false will be used. */
+        @NonNull
+        public Builder setUnderline(boolean underline) {
+            this.mUnderline = underline;
+            return this;
+        }
+
+        /** Sets the maximum lines of text. If not set, 1 will be used. */
+        @NonNull
+        public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
+            this.mMaxLines = maxLines;
+            return this;
+        }
+
+        /**
+         * Sets the multiline alignment for text within bounds of the Text element. Note that this
+         * option has no effect for single line of text, and for that, alignment on the outer
+         * container should be used. If not set, {@link TextAlignment#TEXT_ALIGN_CENTER} will be
+         * used.
+         */
+        @NonNull
+        public Builder setMultilineAlignment(@TextAlignment int multilineAlignment) {
+            this.mMultilineAlignment = multilineAlignment;
+            return this;
+        }
+
+        /** Sets the modifiers of text. */
+        @NonNull
+        public Builder setModifiers(@NonNull Modifiers modifiers) {
+            this.mModifiers = modifiers;
+            return this;
+        }
+
+        /**
+         * Sets the overflow for text. If not set, {@link TextAlignment#TEXT_OVERFLOW_ELLIPSIZE_END}
+         * will be used.
+         */
+        @NonNull
+        public Builder setOverflow(@TextOverflow int overflow) {
+            this.mOverflow = overflow;
+            return this;
+        }
+
+        /**
+         * Sets the weight of the font. If not set, default weight for the chosen Typography will be
+         * used.
+         */
+        @NonNull
+        public Builder setWeight(@FontWeight int weight) {
+            this.mCustomWeight = weight;
+            return this;
+        }
+
+        /** Constructs and returns {@link Text} with the provided content and look. */
+        @NonNull
+        @Override
+        public Text build() {
+            FontStyle.Builder fontStyleBuilder =
+                    getFontStyleBuilder(mTypographyName, mContext, mIsScalable)
+                            .setColor(mColor)
+                            .setItalic(mItalic)
+                            .setUnderline(mUnderline);
+            if (mCustomWeight != null) {
+                fontStyleBuilder.setWeight(mCustomWeight);
+            }
+
+            LayoutElementBuilders.Text.Builder text =
+                    new LayoutElementBuilders.Text.Builder()
+                            .setText(mTextContent)
+                            .setFontStyle(fontStyleBuilder.build())
+                            .setLineHeight(getLineHeightForTypography(mTypographyName))
+                            .setMaxLines(mMaxLines)
+                            .setMultilineAlignment(mMultilineAlignment)
+                            .setModifiers(mModifiers)
+                            .setOverflow(mOverflow);
+            return new Text(text.build());
+        }
+    }
+
+    /** Returns the text of this Text element. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(checkNotNull(mText.getText()).getValue());
+    }
+
+    /** Returns the color of this Text element. */
+    @NonNull
+    public ColorProp getColor() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getColor());
+    }
+
+    /** Returns the font style of this Text element. */
+    @NonNull
+    public FontStyle getFontStyle() {
+        return checkNotNull(mText.getFontStyle());
+    }
+
+    /** Returns the line height of this Text element. */
+    public float getLineHeight() {
+        return checkNotNull(mText.getLineHeight()).getValue();
+    }
+
+    /** Returns the max lines of text of this Text element. */
+    public int getMaxLines() {
+        return checkNotNull(mText.getMaxLines()).getValue();
+    }
+
+    /** Returns the multiline alignment of this Text element. */
+    @TextAlignment
+    public int getMultilineAlignment() {
+        return checkNotNull(mText.getMultilineAlignment()).getValue();
+    }
+
+    /** Returns the modifiers of this Text element. */
+    @NonNull
+    public Modifiers getModifiers() {
+        return checkNotNull(mText.getModifiers());
+    }
+
+    /** Returns the overflow of this Text element. */
+    @TextOverflow
+    public int getOverflow() {
+        return checkNotNull(mText.getOverflow()).getValue();
+    }
+
+    /** Returns the overflow of this Text element. */
+    @FontWeight
+    public int getWeight() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getWeight()).getValue();
+    }
+
+    /** Returns whether the Text is in italic. */
+    public boolean isItalic() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getItalic()).getValue();
+    }
+
+    /** Returns whether the Text is underlined. */
+    public boolean isUnderline() {
+        return checkNotNull(checkNotNull(mText.getFontStyle()).getUnderline()).getValue();
+    }
+
+    /**
+     * Returns Material Text object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to Material Text. Otherwise, it will return null.
+     */
+    @Nullable
+    public static Text fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof Text) {
+            return (Text) element;
+        }
+        if (!(element instanceof LayoutElementBuilders.Text)) {
+            return null;
+        }
+        LayoutElementBuilders.Text textElement = (LayoutElementBuilders.Text) element;
+        // We don't need to check the tag as LayoutElement.Text will have the same fields as our
+        // getters even if it's not Material.
+        return new Text(textElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mText.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mText.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java
new file mode 100644
index 0000000..009dd8c
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/TitleChip.java
@@ -0,0 +1,254 @@
+/*
+ * 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.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_HEIGHT;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_HORIZONTAL_PADDING;
+import static androidx.wear.protolayout.material.ChipDefaults.TITLE_PRIMARY_COLORS;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+
+import android.content.Context;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.ModifiersBuilders.Clickable;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+/**
+ * Tiles component {@link TitleChip} that represents clickable object with the text.
+ *
+ * <p>The Title Chip is Stadium shaped object with a larger height then standard Chip and it will
+ * take one line of text of {@link Typography#TYPOGRAPHY_TITLE2} style.
+ *
+ * <p>The recommended set of {@link ChipColors} styles can be obtained from {@link ChipDefaults},
+ * e.g. {@link ChipDefaults#TITLE_PRIMARY_COLORS} to get a color scheme for a primary {@link
+ * TitleChip}.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * TitleChip chip = new TitleChip...
+ * Box box = new Box.Builder().addContent(chip).build();
+ *
+ * TitleChip myChip = (TitleChip) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link TitleChip} object from any layout element, {@link #fromLayoutElement}
+ * method should be used, i.e.:
+ *
+ * <pre>{@code
+ * TitleChip myChip = TitleChip.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ *
+ * @see  androidx.wear.protolayout.material.layouts.PrimaryLayout.Builder#setContent if this
+ * TitleChip is used inside of {@link androidx.wear.protolayout.material.layouts.PrimaryLayout}.
+ */
+public class TitleChip implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a TitleChip. */
+    static final String METADATA_TAG = "TTLCHP";
+
+    @NonNull private final Chip mElement;
+
+    TitleChip(@NonNull Chip element) {
+        this.mElement = element;
+    }
+
+    /** Builder class for {@link TitleChip}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final Context mContext;
+        @NonNull private final String mText;
+        @NonNull private final Clickable mClickable;
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @NonNull private ChipColors mChipColors = TITLE_PRIMARY_COLORS;
+        @HorizontalAlignment private int mHorizontalAlign = HORIZONTAL_ALIGN_CENTER;
+
+        // Indicates that the width isn't set, so it will be automatically set by Chip.Builder
+        // constructor.
+        @Nullable private ContainerDimension mWidth = null;
+
+        /**
+         * Creates a builder for the {@link TitleChip} with associated action and the given text
+         *
+         * @param context The application's context.
+         * @param text The text to be displayed in this title chip. Text will be displayed in 1 line
+         *     and truncated if it doesn't fit.
+         * @param clickable Associated {@link Clickable} for click events. When the TitleChip is
+         *     clicked it will fire the associated action.
+         * @param deviceParameters The device parameters used for styling text.
+         */
+        public Builder(
+                @NonNull Context context,
+                @NonNull String text,
+                @NonNull Clickable clickable,
+                @NonNull DeviceParameters deviceParameters) {
+            this.mContext = context;
+            this.mText = text;
+            this.mClickable = clickable;
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the colors for the {@link TitleChip}. If set, {@link
+         * ChipColors#getBackgroundColor()} will be used for the background of the button and {@link
+         * ChipColors#getContentColor()} for the text. If not set, {@link
+         * ChipDefaults#TITLE_PRIMARY_COLORS} will be used.
+         */
+        @NonNull
+        public Builder setChipColors(@NonNull ChipColors chipColors) {
+            mChipColors = chipColors;
+            return this;
+        }
+
+        /** Sets the horizontal alignment in the chip. If not set, content will be centered. */
+        @NonNull
+        public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+            mHorizontalAlign = horizontalAlignment;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@NonNull ContainerDimension width) {
+            mWidth = width;
+            return this;
+        }
+
+        /**
+         * Sets the width of {@link TitleChip}. If not set, default value will be set to fill the
+         * screen.
+         */
+        @NonNull
+        public Builder setWidth(@Dimension(unit = DP) float width) {
+            mWidth = dp(width);
+            return this;
+        }
+
+        /** Constructs and returns {@link TitleChip} with the provided content and look. */
+        @NonNull
+        @Override
+        public TitleChip build() {
+            Chip.Builder chipBuilder =
+                    new Chip.Builder(mContext, mClickable, mDeviceParameters)
+                            .setMetadataTag(METADATA_TAG)
+                            .setChipColors(mChipColors)
+                            .setContentDescription(mText)
+                            .setHorizontalAlignment(mHorizontalAlign)
+                            .setHeight(TITLE_HEIGHT)
+                            .setMaxLines(1)
+                            .setHorizontalPadding(TITLE_HORIZONTAL_PADDING)
+                            .setPrimaryLabelContent(mText)
+                            .setPrimaryLabelTypography(Typography.TYPOGRAPHY_TITLE2)
+                            .setIsPrimaryLabelScalable(false);
+
+            if (mWidth != null) {
+                chipBuilder.setWidth(mWidth);
+            }
+
+            return new TitleChip(chipBuilder.build());
+        }
+    }
+
+    /** Returns width of this Chip. */
+    @NonNull
+    public ContainerDimension getWidth() {
+        return mElement.getWidth();
+    }
+
+    /** Returns click event action associated with this Chip. */
+    @NonNull
+    public Clickable getClickable() {
+        return mElement.getClickable();
+    }
+
+    /** Returns chip color of this Chip. */
+    @NonNull
+    public ChipColors getChipColors() {
+        return mElement.getChipColors();
+    }
+
+    /** Returns text content of this Chip. */
+    @NonNull
+    public String getText() {
+        return checkNotNull(mElement.getPrimaryLabelContent());
+    }
+
+    /** Returns the horizontal alignment of the content in this Chip. */
+    @HorizontalAlignment
+    public int getHorizontalAlignment() {
+        return mElement.getHorizontalAlignment();
+    }
+
+    /** Returns metadata tag set to this TitleChip, which should be {@link #METADATA_TAG}. */
+    @NonNull
+    String getMetadataTag() {
+        return mElement.getMetadataTag();
+    }
+
+    /**
+     * Returns TitleChip object from the given LayoutElement (e.g. one retrieved from a container's
+     * content with {@code container.getContents().get(index)}) if that element can be converted to
+     * TitleChip. Otherwise, it will return null.
+     */
+    @Nullable
+    public static TitleChip fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof TitleChip) {
+            return (TitleChip) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a TitleChip.
+        return new TitleChip(new Chip(boxElement));
+    }
+
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    @Override
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java
new file mode 100644
index 0000000..d5b5b9f
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/Typography.java
@@ -0,0 +1,298 @@
+/*
+ * 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.wear.protolayout.material;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.annotation.Dimension.SP;
+import static androidx.wear.protolayout.DimensionBuilders.sp;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_VARIANT_BODY;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_VARIANT_TITLE;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_BOLD;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_MEDIUM;
+import static androidx.wear.protolayout.LayoutElementBuilders.FONT_WEIGHT_NORMAL;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.wear.protolayout.DimensionBuilders;
+import androidx.wear.protolayout.DimensionBuilders.SpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.FontStyle;
+import androidx.wear.protolayout.LayoutElementBuilders.FontVariant;
+import androidx.wear.protolayout.LayoutElementBuilders.FontWeight;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Typography styles, currently set up to match Wear's styling. */
+public class Typography {
+    /** Typography for large display text. */
+    public static final int TYPOGRAPHY_DISPLAY1 = 1;
+
+    /** Typography for medium display text. */
+    public static final int TYPOGRAPHY_DISPLAY2 = 2;
+
+    /** Typography for small display text. */
+    public static final int TYPOGRAPHY_DISPLAY3 = 3;
+
+    /** Typography for large title text. */
+    public static final int TYPOGRAPHY_TITLE1 = 4;
+
+    /** Typography for medium title text. */
+    public static final int TYPOGRAPHY_TITLE2 = 5;
+
+    /** Typography for small title text. */
+    public static final int TYPOGRAPHY_TITLE3 = 6;
+
+    /** Typography for large body text. */
+    public static final int TYPOGRAPHY_BODY1 = 7;
+
+    /** Typography for medium body text. */
+    public static final int TYPOGRAPHY_BODY2 = 8;
+
+    /** Typography for bold button text. */
+    public static final int TYPOGRAPHY_BUTTON = 9;
+
+    /** Typography for large caption text. */
+    public static final int TYPOGRAPHY_CAPTION1 = 10;
+
+    /** Typography for medium caption text. */
+    public static final int TYPOGRAPHY_CAPTION2 = 11;
+
+    /** Typography for small caption text. */
+    public static final int TYPOGRAPHY_CAPTION3 = 12;
+
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        TYPOGRAPHY_DISPLAY1,
+        TYPOGRAPHY_DISPLAY2,
+        TYPOGRAPHY_DISPLAY3,
+        TYPOGRAPHY_TITLE1,
+        TYPOGRAPHY_TITLE2,
+        TYPOGRAPHY_TITLE3,
+        TYPOGRAPHY_BODY1,
+        TYPOGRAPHY_BODY2,
+        TYPOGRAPHY_BUTTON,
+        TYPOGRAPHY_CAPTION1,
+        TYPOGRAPHY_CAPTION2,
+        TYPOGRAPHY_CAPTION3
+    })
+    @interface TypographyName {}
+
+    /** Mapping for line height for different typography. */
+    @NonNull
+    private static final Map<Integer, Float> TYPOGRAPHY_TO_LINE_HEIGHT_SP = new HashMap<>();
+
+    static {
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY1, 46f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY2, 40f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_DISPLAY3, 36f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE1, 28f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE2, 24f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_TITLE3, 20f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BODY1, 20f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BODY2, 18f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_BUTTON, 19f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION1, 18f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION2, 16f);
+        TYPOGRAPHY_TO_LINE_HEIGHT_SP.put(TYPOGRAPHY_CAPTION3, 14f);
+    }
+    /**
+     * Returns the {@link FontStyle.Builder} for the given FontStyle code with the recommended size,
+     * weight and letter spacing. Font will be scalable.
+     */
+    @NonNull
+    static FontStyle.Builder getFontStyleBuilder(
+            @TypographyName int fontStyleCode, @NonNull Context context) {
+        return getFontStyleBuilder(fontStyleCode, context, true);
+    }
+
+    private Typography() {}
+
+    /**
+     * Returns the {@link FontStyle.Builder} for the given Typography code with the recommended
+     * size, weight and letter spacing, with the option to make this font not scalable.
+     */
+    @NonNull
+    static FontStyle.Builder getFontStyleBuilder(
+            @TypographyName int typographyCode, @NonNull Context context, boolean isScalable) {
+        switch (typographyCode) {
+            case TYPOGRAPHY_BODY1:
+                return body1(isScalable, context);
+            case TYPOGRAPHY_BODY2:
+                return body2(isScalable, context);
+            case TYPOGRAPHY_BUTTON:
+                return button(isScalable, context);
+            case TYPOGRAPHY_CAPTION1:
+                return caption1(isScalable, context);
+            case TYPOGRAPHY_CAPTION2:
+                return caption2(isScalable, context);
+            case TYPOGRAPHY_CAPTION3:
+                return caption3(isScalable, context);
+            case TYPOGRAPHY_DISPLAY1:
+                return display1(isScalable, context);
+            case TYPOGRAPHY_DISPLAY2:
+                return display2(isScalable, context);
+            case TYPOGRAPHY_DISPLAY3:
+                return display3(isScalable, context);
+            case TYPOGRAPHY_TITLE1:
+                return title1(isScalable, context);
+            case TYPOGRAPHY_TITLE2:
+                return title2(isScalable, context);
+            case TYPOGRAPHY_TITLE3:
+                return title3(isScalable, context);
+            default:
+                // Shouldn't happen.
+                throw new IllegalArgumentException(
+                        "Typography " + typographyCode + " doesn't exist.");
+        }
+    }
+
+    /**
+     * Returns the recommended line height for the given Typography to be added to the Text
+     * component.
+     */
+    @NonNull
+    static SpProp getLineHeightForTypography(@TypographyName int typography) {
+        if (!TYPOGRAPHY_TO_LINE_HEIGHT_SP.containsKey(typography)) {
+            throw new IllegalArgumentException("Typography " + typography + " doesn't exist.");
+        }
+        return sp(checkNotNull(TYPOGRAPHY_TO_LINE_HEIGHT_SP.get(typography)).intValue());
+    }
+
+    @NonNull
+    @SuppressLint("ResourceType")
+    @SuppressWarnings("deprecation")
+    // This is a helper function to make the font not scalable. It should interpret in value as DP
+    // and convert it to SP which is needed to be passed in as a font size. However, we will pass an
+    // SP object to it, because the default style is defined in it, but for the case when the font
+    // size on device in 1, so the DP is equal to SP.
+    private static SpProp dpToSp(@NonNull Context context, @Dimension(unit = DP) float valueDp) {
+        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+        float scaledSp = (valueDp / metrics.scaledDensity) * metrics.density;
+        return sp(scaledSp);
+    }
+
+    // The @Dimension(unit = SP) on sp() is seemingly being ignored, so lint complains that we're
+    // passing SP to something expecting PX. Just suppress the warning for now.
+    @SuppressLint("ResourceType")
+    private static FontStyle.Builder createFontStyleBuilder(
+            @Dimension(unit = SP) int size,
+            @FontWeight int weight,
+            @FontVariant int variant,
+            float letterSpacing,
+            boolean isScalable,
+            @NonNull Context context) {
+        return new FontStyle.Builder()
+                .setSize(isScalable ? DimensionBuilders.sp(size) : dpToSp(context, size))
+                .setLetterSpacing(DimensionBuilders.em(letterSpacing))
+                .setVariant(variant)
+                .setWeight(weight);
+    }
+
+    /** Font style for large display text. */
+    @NonNull
+    private static FontStyle.Builder display1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                40, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for medium display text. */
+    @NonNull
+    private static FontStyle.Builder display2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                34, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.03f, isScalable, context);
+    }
+
+    /** Font style for small display text. */
+    @NonNull
+    private static FontStyle.Builder display3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                30, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.03f, isScalable, context);
+    }
+
+    /** Font style for large title text. */
+    @NonNull
+    private static FontStyle.Builder title1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                24, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.008f, isScalable, context);
+    }
+
+    /** Font style for medium title text. */
+    @NonNull
+    private static FontStyle.Builder title2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                20, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small title text. */
+    @NonNull
+    private static FontStyle.Builder title3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                16, FONT_WEIGHT_MEDIUM, FONT_VARIANT_TITLE, 0.01f, isScalable, context);
+    }
+
+    /** Font style for normal body text. */
+    @NonNull
+    private static FontStyle.Builder body1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                16, FONT_WEIGHT_NORMAL, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small body text. */
+    @NonNull
+    private static FontStyle.Builder body2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                14, FONT_WEIGHT_NORMAL, FONT_VARIANT_BODY, 0.014f, isScalable, context);
+    }
+
+    /** Font style for bold button text. */
+    @NonNull
+    private static FontStyle.Builder button(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                15, FONT_WEIGHT_BOLD, FONT_VARIANT_BODY, 0.03f, isScalable, context);
+    }
+
+    /** Font style for large caption text. */
+    @NonNull
+    private static FontStyle.Builder caption1(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                14, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for medium caption text. */
+    @NonNull
+    private static FontStyle.Builder caption2(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                12, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+
+    /** Font style for small caption text. */
+    @NonNull
+    private static FontStyle.Builder caption3(boolean isScalable, @NonNull Context context) {
+        return createFontStyleBuilder(
+                10, FONT_WEIGHT_MEDIUM, FONT_VARIANT_BODY, 0.01f, isScalable, context);
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md
new file mode 100644
index 0000000..0b7dc77
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/androidx-wear-protolayout-protolayout-material-documentation.md
@@ -0,0 +1,8 @@
+# Module root
+
+Wear ProtoLayout Material
+
+# Package androidx.wear.protolayout.material
+
+This package provides helpers for Wear ProtoLayout, to enable you to use Wear Material components
+such as Buttons and Chips within your ProtoLayout.
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
new file mode 100644
index 0000000..e3e78d2
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/EdgeContentLayout.java
@@ -0,0 +1,381 @@
+/*
+ * 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.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.expand;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagBytes;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.isRoundDevice;
+import static androidx.wear.protolayout.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.CircularProgressIndicator;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tiles layout that represents the suggested layout style for Material Tiles, which has content
+ * around the edge of the screen (e.g. a ProgressIndicator) and the given content inside of it with
+ * the recommended margin and padding applied. Optional primary or secondary label can be added
+ * above and below the main content, respectively.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * EdgeContentLayout ecl = new EdgeContentLayout...
+ * Box box = new Box.Builder().addContent(ecl).build();
+ *
+ * EdgeContentLayout myEcl = (EdgeContentLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link EdgeContentLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * EdgeContentLayout myEcl =
+ *   EdgeContentLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class EdgeContentLayout implements LayoutElement {
+    /**
+     * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a
+     * EdgeContentLayout.
+     */
+    static final String METADATA_TAG_PREFIX = "ECL_";
+
+    /**
+     * Index for byte array that contains bits to check whether the content and indicator are
+     * present or not.
+     */
+    static final int FLAG_INDEX = METADATA_TAG_PREFIX.length();
+
+    /**
+     * Base tool tag for Metadata in Modifiers, so we know that Box is actually a EdgeContentLayout
+     * and what optional content is added.
+     */
+    static final byte[] METADATA_TAG_BASE =
+            Arrays.copyOf(getTagBytes(METADATA_TAG_PREFIX), FLAG_INDEX + 1);
+
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the edge content is present or not.
+     */
+    static final int EDGE_CONTENT_PRESENT = 0x1;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary label is present or not.
+     */
+    static final int PRIMARY_LABEL_PRESENT = 0x2;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the secondary label is present or not.
+     */
+    static final int SECONDARY_LABEL_PRESENT = 0x4;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the main content is present or not.
+     */
+    static final int CONTENT_PRESENT = 0x8;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            flag = true,
+            value = {
+                EDGE_CONTENT_PRESENT,
+                PRIMARY_LABEL_PRESENT,
+                CONTENT_PRESENT,
+                SECONDARY_LABEL_PRESENT
+            })
+    @interface ContentBits {}
+
+    @NonNull private final Box mImpl;
+
+    // This contains inner columns and edge content.
+    @NonNull private final List<LayoutElement> mContents;
+
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mInnerColumn;
+
+    EdgeContentLayout(@NonNull Box layoutElement) {
+        this.mImpl = layoutElement;
+        this.mContents = mImpl.getContents();
+        this.mInnerColumn = ((Column) ((Box) mContents.get(0)).getContents().get(0)).getContents();
+    }
+
+    /** Builder class for {@link EdgeContentLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @Nullable private LayoutElement mEdgeContent = null;
+        @Nullable private LayoutElement mPrimaryLabelText = null;
+        @Nullable private LayoutElement mSecondaryLabelText = null;
+        @Nullable private LayoutElement mContent = null;
+        private byte mMetadataContentByte = 0;
+
+        /**
+         * Creates a builder for the {@link EdgeContentLayout}t. Custom content inside of it can
+         * later be set with ({@link #setContent}.
+         */
+        public Builder(@NonNull DeviceParameters deviceParameters) {
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the content to be around the edges. This can be {@link CircularProgressIndicator}.
+         */
+        @NonNull
+        public Builder setEdgeContent(@NonNull LayoutElement edgeContent) {
+            this.mEdgeContent = edgeContent;
+            mMetadataContentByte = (byte) (mMetadataContentByte | EDGE_CONTENT_PRESENT);
+            return this;
+        }
+
+        /** Sets the content in the primary label slot which will be above the main content. */
+        @NonNull
+        public Builder setPrimaryLabelTextContent(@NonNull LayoutElement primaryLabelText) {
+            this.mPrimaryLabelText = primaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | PRIMARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the content in the secondary label slot which will be below the main content. It is
+         * highly recommended to have primary label set when having secondary label.
+         */
+        @NonNull
+        public Builder setSecondaryLabelTextContent(@NonNull LayoutElement secondaryLabelText) {
+            this.mSecondaryLabelText = secondaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | SECONDARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /** Sets the additional content to this layout, inside of the screen. */
+        @NonNull
+        public Builder setContent(@NonNull LayoutElement content) {
+            this.mContent = content;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_PRESENT);
+            return this;
+        }
+
+        /** Constructs and returns {@link EdgeContentLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        public EdgeContentLayout build() {
+            float thicknessDp =
+                    mEdgeContent instanceof CircularProgressIndicator
+                            ? ((CircularProgressIndicator) mEdgeContent).getStrokeWidth().getValue()
+                            : 0;
+            float horizontalPaddingDp =
+                    isRoundDevice(mDeviceParameters)
+                            ? EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP
+                            : EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
+            float indicatorWidth = 2 * (thicknessDp + DEFAULT_PADDING.getValue());
+            float mainContentHeightDp = mDeviceParameters.getScreenHeightDp() - indicatorWidth;
+            float mainContentWidthDp = mDeviceParameters.getScreenWidthDp() - indicatorWidth;
+
+            DpProp mainContentHeight = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
+            DpProp mainContentWidth = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
+
+            Modifiers modifiers =
+                    new Modifiers.Builder()
+                            .setPadding(
+                                    new Padding.Builder()
+                                            .setStart(dp(horizontalPaddingDp))
+                                            .setEnd(dp(horizontalPaddingDp))
+                                            .build())
+                            .build();
+
+            byte[] metadata = METADATA_TAG_BASE.clone();
+            metadata[FLAG_INDEX] = mMetadataContentByte;
+            Box.Builder mainBoxBuilder =
+                    new Box.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(metadata)
+                                                            .build())
+                                            .build())
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER);
+
+            Column.Builder innerContentBuilder =
+                    new Column.Builder()
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            if (mPrimaryLabelText != null) {
+                innerContentBuilder.addContent(mPrimaryLabelText);
+                innerContentBuilder.addContent(
+                        new Spacer.Builder()
+                                .setHeight(dp(EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP))
+                                .build());
+            }
+
+            if (mContent != null) {
+                innerContentBuilder.addContent(
+                        new Box.Builder()
+                                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                                .addContent(mContent)
+                                .build());
+            }
+
+            if (mSecondaryLabelText != null) {
+                innerContentBuilder.addContent(
+                        new Spacer.Builder()
+                                .setHeight(dp(EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP))
+                                .build());
+                innerContentBuilder.addContent(mSecondaryLabelText);
+            }
+
+            mainBoxBuilder.addContent(
+                    new Box.Builder()
+                            .setModifiers(modifiers)
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
+                            .setHeight(mainContentHeight)
+                            .setWidth(mainContentWidth)
+                            .addContent(innerContentBuilder.build())
+                            .build());
+
+            if (mEdgeContent != null) {
+                mainBoxBuilder.addContent(mEdgeContent);
+            }
+
+            return new EdgeContentLayout(mainBoxBuilder.build());
+        }
+    }
+
+    private boolean areElementsPresent(@ContentBits int elementFlag) {
+        return (getMetadataTag()[FLAG_INDEX] & elementFlag) == elementFlag;
+    }
+
+    /** Returns metadata tag set to this EdgeContentLayout. */
+    @NonNull
+    byte[] getMetadataTag() {
+        return getMetadataTagBytes(checkNotNull(checkNotNull(mImpl.getModifiers()).getMetadata()));
+    }
+
+    /** Returns the inner content from this layout. */
+    @Nullable
+    public LayoutElement getContent() {
+        if (!areElementsPresent(CONTENT_PRESENT)) {
+            return null;
+        }
+        // By tag we know that content exists. It will be at position 0 if there is no primary
+        // label, or at position 2 (primary label, spacer - content) otherwise.
+        int contentPosition = areElementsPresent(PRIMARY_LABEL_PRESENT) ? 2 : 0;
+        return ((Box) mInnerColumn.get(contentPosition)).getContents().get(0);
+    }
+
+    /** Get the primary label content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryLabelTextContent() {
+        if (!areElementsPresent(PRIMARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that primary label exists. It will always be at position 0.
+        return mInnerColumn.get(0);
+    }
+
+    /** Get the secondary label content from this layout. */
+    @Nullable
+    public LayoutElement getSecondaryLabelTextContent() {
+        if (!areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that secondary label exists. It will always be at last position.
+        return mInnerColumn.get(mInnerColumn.size() - 1);
+    }
+
+    /** Returns the edge content from this layout. */
+    @Nullable
+    public LayoutElement getEdgeContent() {
+        if (areElementsPresent(EDGE_CONTENT_PRESENT)) {
+            return mContents.get(1);
+        }
+        return null;
+    }
+
+    /**
+     * Returns EdgeContentLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to EdgeContentLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static EdgeContentLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof EdgeContentLayout) {
+            return (EdgeContentLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG_PREFIX, METADATA_TAG_BASE)) {
+            return null;
+        }
+        // Now we are sure that this element is a EdgeContentLayout.
+        return new EdgeContentLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
new file mode 100644
index 0000000..42a3381
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/LayoutDefaults.java
@@ -0,0 +1,134 @@
+/*
+ * 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.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.material.ButtonDefaults;
+
+/** Contains the default values used by layout templates for Tiles. */
+public class LayoutDefaults {
+    private LayoutDefaults() {}
+
+    /**
+     * The default percentage for the bottom margin for primary chip in the {@link PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT = 2.1f / 100;
+
+    /**
+     * The default percentage for the bottom margin for primary chip in the {@link PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT = 0;
+
+    /**
+     * The default percentage for the top margin for primary chip in the {@link PrimaryLayout} on
+     * round devices.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT = 16.7f / 100;
+
+    /**
+     * The default percentage for the top margin for primary chip in the {@link PrimaryLayout} on
+     * square devices.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT = 13.3f / 100;
+
+    /**
+     * The default spacer above primary label in {@link PrimaryLayout} to make space for Tile icon
+     * on round devices.
+     */
+    static final DpProp PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP = dp(0);
+
+    /**
+     * The default spacer above primary label in {@link PrimaryLayout} to make space for Tile icon
+     * on square devices.
+     */
+    static final DpProp PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP = dp(4);
+
+    /**
+     * The default percentage for the horizontal margin for primary chip in the {@link
+     * PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT = 6.3f / 100;
+
+    /**
+     * The default percentage for the horizontal margin for primary chip in the {@link
+     * PrimaryLayout}.
+     */
+    static final float PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT = 2.8f / 100;
+
+    /**
+     * The padding for the primary chip in {@link PrimaryLayout} so it doesn't bleed off screen if
+     * text is too big.
+     */
+    static final float PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP = 30;
+
+    /**
+     * The padding for the primary chip in {@link PrimaryLayout} so it doesn't bleed off screen if
+     * text is too big.
+     */
+    static final float PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP = 0;
+
+    /** The default horizontal margin in the {@link EdgeContentLayout}. */
+    static final float EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP = 14;
+
+    /** The default horizontal margin in the {@link EdgeContentLayout}. */
+    static final float EDGE_CONTENT_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP = 16;
+
+    /**
+     * The recommended padding that should be above the main content (text) in the {@link
+     * EdgeContentLayout}.
+     */
+    public static final float EDGE_CONTENT_LAYOUT_PADDING_ABOVE_MAIN_CONTENT_DP = 6;
+
+    /**
+     * The recommended padding that should be below the main content (text) in the {@link
+     * EdgeContentLayout}.
+     */
+    public static final float EDGE_CONTENT_LAYOUT_PADDING_BELOW_MAIN_CONTENT_DP = 8;
+
+    /** The default spacer width for slots in a {@link MultiSlotLayout}. */
+    public static final DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH = dp(8);
+
+    /** The recommended space between the main content and additional labels in layouts. */
+    public static final DpProp DEFAULT_VERTICAL_SPACER_HEIGHT = dp(8);
+
+    /** The maximum number of button that can be added to the {@link MultiButtonLayout}. */
+    public static final int MULTI_BUTTON_MAX_NUMBER = 7;
+
+    /**
+     * The default size of button in case when there are 3 or more buttons in the {@link
+     * MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_3_PLUS_SIZE = ButtonDefaults.DEFAULT_SIZE;
+
+    /** The default size of button in case when there 2 buttons in the {@link MultiButtonLayout}. */
+    static final DpProp MULTI_BUTTON_2_SIZE = ButtonDefaults.LARGE_SIZE;
+
+    /**
+     * The default size of button in case when there is 1 button in the {@link MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_1_SIZE = ButtonDefaults.EXTRA_LARGE_SIZE;
+
+    /** The default width for vertical spacer between buttons in the {@link MultiButtonLayout}. */
+    static final DpProp MULTI_BUTTON_SPACER_WIDTH = dp(6);
+
+    /**
+     * The default height for horizontal spacer between buttons in the {@link MultiButtonLayout}.
+     */
+    static final DpProp MULTI_BUTTON_SPACER_HEIGHT = dp(4);
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java
new file mode 100644
index 0000000..e4186c5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiButtonLayout.java
@@ -0,0 +1,399 @@
+/*
+ * 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.wear.protolayout.material.layouts;
+
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_1_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_2_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_3_PLUS_SIZE;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_MAX_NUMBER;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_SPACER_HEIGHT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_BUTTON_SPACER_WIDTH;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.Button;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Opinionated Tiles layout, that can contain between 1 and {@link
+ * LayoutDefaults#MULTI_BUTTON_MAX_NUMBER} number of buttons arranged inline with the Material
+ * guidelines. Can be used as a content passed in to the {@link PrimaryLayout}, but if there is
+ * {@link LayoutDefaults#MULTI_BUTTON_MAX_NUMBER} buttons it should be used on its own.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * MultiButtonLayout mbl = new MultiButtonLayout...
+ * Box box = new Box.Builder().addContent(mbl).build();
+ *
+ * MultiButtonLayout myMbl = (MultiButtonLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link MultiButtonLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * MultiButtonLayout myMbl = MultiButtonLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class MultiButtonLayout implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Box is actually a MultiButtonLayout. */
+    static final String METADATA_TAG = "MBL";
+
+    /** Button distribution where the first row has more buttons than other rows. */
+    public static final int FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY = 1;
+
+    /** Button distribution where the last row has more buttons than other rows. */
+    public static final int FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY = 2;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY, FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY})
+    public @interface ButtonDistribution {}
+
+    @NonNull private final Box mElement;
+
+    MultiButtonLayout(@NonNull Box mElement) {
+        this.mElement = mElement;
+    }
+
+    /** Builder class for {@link MultiButtonLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final List<LayoutElement> mButtonsContent = new ArrayList<>();
+        private @ButtonDistribution int mFiveButtonDistribution =
+                FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+
+        /**
+         * Creates a builder for the {@link MultiButtonLayout}. Content inside of it can later be
+         * added with {@link #addButtonContent}.
+         */
+        public Builder() {}
+
+        /**
+         * Add one new button to the layout. Note that it is accepted to pass in any {@link
+         * LayoutElement}, but it is strongly recommended to add a {@link Button} as the layout is
+         * optimized for it. Any button added after {@link LayoutDefaults#MULTI_BUTTON_MAX_NUMBER}
+         * is reached will be discarded.
+         */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is no direct matching getter for this setter, but there is a getter that gets all
+        // added buttons.
+        public Builder addButtonContent(@NonNull LayoutElement buttonContent) {
+            mButtonsContent.add(buttonContent);
+            return this;
+        }
+
+        /**
+         * Sets the button distribution for this layout. Button distribution is used in case when
+         * there is 5 buttons in the layout to determine whether the 3 buttons row is at the top or
+         * bottom.
+         */
+        @NonNull
+        public Builder setFiveButtonDistribution(@ButtonDistribution int fiveButtonDistribution) {
+            this.mFiveButtonDistribution = fiveButtonDistribution;
+            return this;
+        }
+
+        /** Constructs and returns {@link MultiButtonLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        public MultiButtonLayout build() {
+            int buttonNum = mButtonsContent.size();
+            if (buttonNum > MULTI_BUTTON_MAX_NUMBER) {
+                throw new IllegalArgumentException(
+                        "Too many buttons are added. Maximum number is "
+                                + MULTI_BUTTON_MAX_NUMBER
+                                + ".");
+            }
+
+            LayoutElement buttons = buildButtons(buttonNum);
+            Box.Builder elementBuilder =
+                    new Box.Builder()
+                        .setModifiers(
+                            new Modifiers.Builder()
+                                .setMetadata(
+                                    new ElementMetadata.Builder()
+                                        .setTagData(getTagBytes(METADATA_TAG))
+                                        .build())
+                                .build())
+                        .addContent(buttons);
+
+            return new MultiButtonLayout(elementBuilder.build());
+        }
+
+        @NonNull
+        private LayoutElement buildButtons(int buttonNum) {
+            switch (buttonNum) {
+                case 1:
+                    return wrapButton(mButtonsContent.get(0), MULTI_BUTTON_1_SIZE);
+                case 2:
+                    return build2ButtonRow(
+                            mButtonsContent.get(0), mButtonsContent.get(1), MULTI_BUTTON_2_SIZE);
+                case 3:
+                    return build3ButtonRow(
+                            mButtonsContent.get(0), mButtonsContent.get(1), mButtonsContent.get(2));
+                case 4:
+                    return new Column.Builder()
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(2),
+                                            mButtonsContent.get(3),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .build();
+                case 5:
+                    return new Column.Builder()
+                            .addContent(
+                                    mFiveButtonDistribution == FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY
+                                            ? build3ButtonRow(
+                                                    mButtonsContent.get(0),
+                                                    mButtonsContent.get(1),
+                                                    mButtonsContent.get(2))
+                                            : build2ButtonRow(
+                                                    mButtonsContent.get(0),
+                                                    mButtonsContent.get(1),
+                                                    MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    mFiveButtonDistribution == FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY
+                                            ? build2ButtonRow(
+                                                    mButtonsContent.get(3),
+                                                    mButtonsContent.get(4),
+                                                    MULTI_BUTTON_3_PLUS_SIZE)
+                                            : build3ButtonRow(
+                                                    mButtonsContent.get(2),
+                                                    mButtonsContent.get(3),
+                                                    mButtonsContent.get(4)))
+                            .build();
+                case 6:
+                    return new Column.Builder()
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            mButtonsContent.get(2)))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(3),
+                                            mButtonsContent.get(4),
+                                            mButtonsContent.get(5)))
+                            .build();
+                case 7:
+                    return new Column.Builder()
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(0),
+                                            mButtonsContent.get(1),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build3ButtonRow(
+                                            mButtonsContent.get(2),
+                                            mButtonsContent.get(3),
+                                            mButtonsContent.get(4)))
+                            .addContent(buildVerticalSpacer())
+                            .addContent(
+                                    build2ButtonRow(
+                                            mButtonsContent.get(5),
+                                            mButtonsContent.get(6),
+                                            MULTI_BUTTON_3_PLUS_SIZE))
+                            .build();
+            }
+            // This shouldn't happen, but return an empty Box instead of having this method nullable
+            // and checks above.
+            return new Box.Builder().build();
+        }
+
+        @NonNull
+        private Row build3ButtonRow(
+                @NonNull LayoutElement button1,
+                @NonNull LayoutElement button2,
+                @NonNull LayoutElement button3) {
+            return new Row.Builder()
+                    .setWidth(wrap())
+                    .setHeight(wrap())
+                    .addContent(wrapButton(button1, MULTI_BUTTON_3_PLUS_SIZE))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button2, MULTI_BUTTON_3_PLUS_SIZE))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button3, MULTI_BUTTON_3_PLUS_SIZE))
+                    .build();
+        }
+
+        @NonNull
+        private Row build2ButtonRow(
+                @NonNull LayoutElement button1,
+                @NonNull LayoutElement button2,
+                @NonNull DpProp size) {
+            return new Row.Builder()
+                    .setWidth(wrap())
+                    .setHeight(wrap())
+                    .addContent(wrapButton(button1, size))
+                    .addContent(buildHorizontalSpacer())
+                    .addContent(wrapButton(button2, size))
+                    .build();
+        }
+
+        @NonNull
+        private Spacer buildHorizontalSpacer() {
+            return new Spacer.Builder().setWidth(MULTI_BUTTON_SPACER_WIDTH).build();
+        }
+
+        @NonNull
+        private Spacer buildVerticalSpacer() {
+            return new Spacer.Builder().setHeight(MULTI_BUTTON_SPACER_HEIGHT).build();
+        }
+
+        @NonNull
+        private Box wrapButton(@NonNull LayoutElement button, @NonNull DpProp size) {
+            return new Box.Builder().setWidth(size).setHeight(size).addContent(button).build();
+        }
+    }
+
+    /** Gets the content from this layout, containing all buttons that were added. */
+    @NonNull
+    public List<LayoutElement> getButtonContents() {
+        List<LayoutElement> buttons = new ArrayList<>();
+        List<LayoutElement> contents = mElement.getContents();
+        if (contents.isEmpty()) {
+            return buttons;
+        }
+        LayoutElement innerContent = contents.get(0);
+        if (innerContent instanceof Column) {
+            for (LayoutElement row : ((Column) innerContent).getContents()) {
+                if (row instanceof Row) {
+                    buttons.addAll(getButtonsFromRow((Row) row));
+                }
+            }
+        } else if (innerContent instanceof Row) {
+            return getButtonsFromRow((Row) innerContent);
+        } else if (innerContent instanceof Box) {
+            buttons.add(((Box) innerContent).getContents().get(0));
+        }
+
+        return buttons;
+    }
+
+    /** Returns metadata tag set to this MultiButtonLayouts. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Gets the button distribution from this layout for the case when there is 5 buttons in the
+     * layout. If there is more or less buttons than 5, default {@link
+     * #FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY} will be returned.
+     */
+    public int getFiveButtonDistribution() {
+        List<LayoutElement> contents = mElement.getContents();
+        if (getButtonContents().size() != 5) {
+            return FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+        }
+        LayoutElement innerContent = contents.get(0);
+        if (innerContent instanceof Column && ((Column) innerContent).getContents().size() == 3) {
+            // 1st and 3rd row are buttons. Check whether the first row has 5 (3 buttons + 2 spacer)
+            // - top heavy or 3 (2 buttons + spacer) - bottom heavy elements.
+            LayoutElement firstElement = ((Column) innerContent).getContents().get(0);
+            if (firstElement instanceof Row && ((Row) firstElement).getContents().size() == 5) {
+                return FIVE_BUTTON_DISTRIBUTION_TOP_HEAVY;
+            }
+        }
+        return FIVE_BUTTON_DISTRIBUTION_BOTTOM_HEAVY;
+    }
+
+    private List<LayoutElement> getButtonsFromRow(Row row) {
+        List<LayoutElement> buttons = new ArrayList<>();
+        for (LayoutElement element : row.getContents()) {
+            if (element instanceof Box) {
+                buttons.add(((Box) element).getContents().get(0));
+            }
+        }
+        return buttons;
+    }
+
+    /**
+     * Returns MultiButtonLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to MultiButtonLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static MultiButtonLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof MultiButtonLayout) {
+            return (MultiButtonLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a MultiButtonLayout.
+        return new MultiButtonLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java
new file mode 100644
index 0000000..8f9e903
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/MultiSlotLayout.java
@@ -0,0 +1,237 @@
+/*
+ * 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.wear.protolayout.material.layouts;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagName;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+
+import android.annotation.SuppressLint;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Row;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Opinionated Tiles layout, row like style with horizontally aligned and spaced slots (for icons or
+ * other small content). Should be used as a content passed in to the {@link PrimaryLayout}.
+ *
+ * <p>Recommended number of added slots is 1 to 3. Their width will be the width of an element
+ * passed in, with the {@link LayoutDefaults#MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH} space
+ * between.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * MultiSlotLayout msl = new MultiSlotLayout...
+ * Box box = new Box.Builder().addContent(msl).build();
+ *
+ * MultiSlotLayout myMsl = (MultiSlotLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link MultiSlotLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * MultiSlotLayout myMsl = MultiSlotLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class MultiSlotLayout implements LayoutElement {
+    /** Tool tag for Metadata in Modifiers, so we know that Row is actually a MultiSlotLayout. */
+    static final String METADATA_TAG = "MSL";
+
+    @NonNull private final Row mElement;
+
+    MultiSlotLayout(@NonNull Row mElement) {
+        this.mElement = mElement;
+    }
+
+    /** Builder class for {@link MultiSlotLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+
+        @NonNull private final List<LayoutElement> mSlotsContent = new ArrayList<>();
+        @NonNull private DpProp mHorizontalSpacerWidth = MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+
+        /**
+         * Creates a builder for the {@link MultiSlotLayout}. Content inside of it can later be
+         * added with {@link #addSlotContent}.
+         */
+        public Builder() {}
+
+        /** Add one new slot to the layout with the given content inside. */
+        @NonNull
+        @SuppressWarnings("MissingGetterMatchingBuilder")
+        // There is no direct matching getter for this setter, but there is a getter that gets all
+        // added slots.
+        public Builder addSlotContent(@NonNull LayoutElement slotContent) {
+            mSlotsContent.add(slotContent);
+            return this;
+        }
+
+        /**
+         * Sets the horizontal spacer width which is used as a space between slots if there is more
+         * than one slot. If not set, {@link
+         * LayoutDefaults#MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH} will be used.
+         */
+        @NonNull
+        public Builder setHorizontalSpacerWidth(@Dimension(unit = DP) float width) {
+            this.mHorizontalSpacerWidth = dp(width);
+            return this;
+        }
+
+        /** Constructs and returns {@link MultiSlotLayout} with the provided content and look. */
+        @NonNull
+        @Override
+        // The @Dimension(unit = DP) on mVerticalSpacerHeight.getValue() is seemingly being ignored,
+        // so lint complains that we're passing PX to something expecting DP. Just suppress the
+        // warning for now.
+        @SuppressLint("ResourceType")
+        public MultiSlotLayout build() {
+            Row.Builder rowBuilder =
+                    new Row.Builder()
+                            .setHeight(wrap())
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(wrap())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(getTagBytes(METADATA_TAG))
+                                                            .build())
+                                            .build());
+            if (!mSlotsContent.isEmpty()) {
+
+                boolean isFirst = true;
+                for (LayoutElement slot : mSlotsContent) {
+                    if (!isFirst) {
+                        rowBuilder.addContent(
+                                new Spacer.Builder().setWidth(mHorizontalSpacerWidth).build());
+                    } else {
+                        isFirst = false;
+                    }
+                    rowBuilder.addContent(
+                            new Box.Builder()
+                                    .setWidth(wrap())
+                                    .setHeight(wrap())
+                                    .addContent(slot)
+                                    .build());
+                }
+            }
+
+            return new MultiSlotLayout(rowBuilder.build());
+        }
+    }
+
+    /** Gets the content from this layout, containing all slots that were added. */
+    @NonNull
+    public List<LayoutElement> getSlotContents() {
+        List<LayoutElement> slots = new ArrayList<>();
+        for (LayoutElement slot : mElement.getContents()) {
+            if (slot instanceof Box) {
+                slots.add(((Box) slot).getContents().get(0));
+            }
+        }
+        return slots;
+    }
+
+    /** Gets the width of horizontal spacer that is between slots. */
+    // The @Dimension(unit = DP) on getLinearDimension.getValue() is seemingly being ignored, so
+    // lint complains that we're passing PX to something expecting DP. Just suppress the warning for
+    // now.
+    @SuppressLint("ResourceType")
+    @Dimension(unit = DP)
+    public float getHorizontalSpacerWidth() {
+        for (LayoutElement slot : mElement.getContents()) {
+            if (slot instanceof Spacer) {
+                SpacerDimension width = ((Spacer) slot).getWidth();
+                if (width instanceof DpProp) {
+                    return ((DpProp) width).getValue();
+                }
+            }
+        }
+        return LayoutDefaults.MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH.getValue();
+    }
+
+    /** Returns metadata tag set to this MultiSlotLayout. */
+    @NonNull
+    String getMetadataTag() {
+        return getMetadataTagName(
+                checkNotNull(checkNotNull(mElement.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns MultiSlotLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to MultiSlotLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static MultiSlotLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof MultiSlotLayout) {
+            return (MultiSlotLayout) element;
+        }
+        if (!(element instanceof Row)) {
+            return null;
+        }
+        Row rowElement = (Row) element;
+        if (!checkTag(rowElement.getModifiers(), METADATA_TAG)) {
+            return null;
+        }
+        // Now we are sure that this element is a MultiSlotLayout.
+        return new MultiSlotLayout(rowElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mElement.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mElement.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java
new file mode 100644
index 0000000..2bbbac5
--- /dev/null
+++ b/wear/protolayout/protolayout-material/src/main/java/androidx/wear/protolayout/material/layouts/PrimaryLayout.java
@@ -0,0 +1,540 @@
+/*
+ * 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.wear.protolayout.material.layouts;
+
+import static androidx.annotation.Dimension.DP;
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+import static androidx.wear.protolayout.DimensionBuilders.expand;
+import static androidx.wear.protolayout.DimensionBuilders.wrap;
+import static androidx.wear.protolayout.material.ChipDefaults.COMPACT_HEIGHT_TAPPABLE;
+import static androidx.wear.protolayout.material.Helper.checkNotNull;
+import static androidx.wear.protolayout.material.Helper.checkTag;
+import static androidx.wear.protolayout.material.Helper.getMetadataTagBytes;
+import static androidx.wear.protolayout.material.Helper.getTagBytes;
+import static androidx.wear.protolayout.material.Helper.isRoundDevice;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.DEFAULT_VERTICAL_SPACER_HEIGHT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP;
+import static androidx.wear.protolayout.material.layouts.LayoutDefaults.PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP;
+
+import android.annotation.SuppressLint;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters;
+import androidx.wear.protolayout.DimensionBuilders.DpProp;
+import androidx.wear.protolayout.DimensionBuilders.SpacerDimension;
+import androidx.wear.protolayout.LayoutElementBuilders;
+import androidx.wear.protolayout.LayoutElementBuilders.Box;
+import androidx.wear.protolayout.LayoutElementBuilders.Column;
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement;
+import androidx.wear.protolayout.LayoutElementBuilders.Spacer;
+import androidx.wear.protolayout.ModifiersBuilders.ElementMetadata;
+import androidx.wear.protolayout.ModifiersBuilders.Modifiers;
+import androidx.wear.protolayout.ModifiersBuilders.Padding;
+import androidx.wear.protolayout.expression.Fingerprint;
+import androidx.wear.protolayout.material.CompactChip;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Tiles layout that represents a suggested layout style for Material Tiles with the primary
+ * (compact) chip at the bottom with the given content in the center and the recommended margin and
+ * padding applied. There is a fixed slot for an optional primary label above or optional secondary
+ * label below the main content area.
+ *
+ * <p>It is highly recommended that main content has max lines between 2 and 4 (dependant on labels
+ * present), i.e.: * No labels are present: content with max 4 lines, * 1 label is present: content
+ * with max 3 lines, * 2 labels are present: content with max 2 lines.
+ *
+ * <p>For additional examples and suggested layouts see <a
+ * href="/training/wearables/design/tiles-design-system">Tiles Design System</a>.
+ *
+ * <p>When accessing the contents of a container for testing, note that this element can't be simply
+ * casted back to the original type, i.e.:
+ *
+ * <pre>{@code
+ * PrimaryLayout pl = new PrimaryLayout...
+ * Box box = new Box.Builder().addContent(pl).build();
+ *
+ * PrimaryLayout myPl = (PrimaryLayout) box.getContents().get(0);
+ * }</pre>
+ *
+ * will fail.
+ *
+ * <p>To be able to get {@link PrimaryLayout} object from any layout element, {@link
+ * #fromLayoutElement} method should be used, i.e.:
+ *
+ * <pre>{@code
+ * PrimaryLayout myPl = PrimaryLayout.fromLayoutElement(box.getContents().get(0));
+ * }</pre>
+ */
+public class PrimaryLayout implements LayoutElement {
+    /**
+     * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a PrimaryLayout.
+     */
+    static final String METADATA_TAG_PREFIX = "PL_";
+
+    /** Index for byte array that contains bits to check whether the contents are present or not. */
+    static final int FLAG_INDEX = METADATA_TAG_PREFIX.length();
+
+    /**
+     * Base tool tag for Metadata in Modifiers, so we know that Box is actually a PrimaryLayout and
+     * what optional content is added.
+     */
+    static final byte[] METADATA_TAG_BASE =
+            Arrays.copyOf(getTagBytes(METADATA_TAG_PREFIX), FLAG_INDEX + 1);
+
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary chip is present or not.
+     */
+    static final int CHIP_PRESENT = 0x1;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the primary label is present or not.
+     */
+    static final int PRIMARY_LABEL_PRESENT = 0x2;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the secondary label is present or not.
+     */
+    static final int SECONDARY_LABEL_PRESENT = 0x4;
+    /**
+     * Bit position in a byte on {@link #FLAG_INDEX} index in metadata byte array to check whether
+     * the content is present or not.
+     */
+    static final int CONTENT_PRESENT = 0x8;
+
+    /** Position of the primary label in its own inner column if exists. */
+    static final int PRIMARY_LABEL_POSITION = 1;
+    /** Position of the content in its own inner column. */
+    static final int CONTENT_ONLY_POSITION = 0;
+    /** Position of the primary chip in main layout column. */
+    static final int PRIMARY_CHIP_POSITION = 1;
+
+    @RestrictTo(Scope.LIBRARY)
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            flag = true,
+            value = {CHIP_PRESENT, PRIMARY_LABEL_PRESENT, SECONDARY_LABEL_PRESENT, CONTENT_PRESENT})
+    @interface ContentBits {}
+
+    @NonNull private final Box mImpl;
+
+    // This contains inner columns and primary chip.
+    @NonNull private final List<LayoutElement> mAllContent;
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mPrimaryLabel;
+    // This contains optional labels, spacers and main content.
+    @NonNull private final List<LayoutElement> mContentAndSecondaryLabel;
+
+    PrimaryLayout(@NonNull Box layoutElement) {
+        this.mImpl = layoutElement;
+        this.mAllContent = ((Column) layoutElement.getContents().get(0)).getContents();
+        List<LayoutElement> innerContent = ((Column) mAllContent.get(0)).getContents();
+        this.mPrimaryLabel = ((Column) innerContent.get(0)).getContents();
+        this.mContentAndSecondaryLabel =
+                ((Column) ((Box) innerContent.get(1)).getContents().get(0)).getContents();
+    }
+
+    /** Builder class for {@link PrimaryLayout}. */
+    public static final class Builder implements LayoutElement.Builder {
+        @NonNull private final DeviceParameters mDeviceParameters;
+        @Nullable private LayoutElement mPrimaryChip = null;
+        @Nullable private LayoutElement mPrimaryLabelText = null;
+        @Nullable private LayoutElement mSecondaryLabelText = null;
+        @NonNull private LayoutElement mContent = new Box.Builder().build();
+        @NonNull private DpProp mVerticalSpacerHeight = DEFAULT_VERTICAL_SPACER_HEIGHT;
+        private byte mMetadataContentByte = 0;
+
+        /**
+         * Creates a builder for the {@link PrimaryLayout} from the given content. Content inside of
+         * it can later be set with {@link #setContent}, {@link #setPrimaryChipContent}, {@link
+         * #setPrimaryLabelTextContent} and {@link #setSecondaryLabelTextContent}.
+         */
+        public Builder(@NonNull DeviceParameters deviceParameters) {
+            this.mDeviceParameters = deviceParameters;
+        }
+
+        /**
+         * Sets the element which is in the slot at the bottom of the layout. Note that it is
+         * accepted to pass in any {@link LayoutElement}, but it is strongly recommended to add a
+         * {@link CompactChip} as the layout is optimized for it.
+         */
+        @NonNull
+        public Builder setPrimaryChipContent(@NonNull LayoutElement compactChip) {
+            this.mPrimaryChip = compactChip;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CHIP_PRESENT);
+            return this;
+        }
+
+        /** Sets the content in the primary label slot which will be above the main content. */
+        @NonNull
+        public Builder setPrimaryLabelTextContent(@NonNull LayoutElement primaryLabelText) {
+            this.mPrimaryLabelText = primaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | PRIMARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the content in the primary label slot which will be below the main content. It is
+         * highly recommended to have primary label set when having secondary label.
+         */
+        @NonNull
+        public Builder setSecondaryLabelTextContent(@NonNull LayoutElement secondaryLabelText) {
+            this.mSecondaryLabelText = secondaryLabelText;
+            mMetadataContentByte = (byte) (mMetadataContentByte | SECONDARY_LABEL_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the additional content to this layout, above the primary chip.
+         *
+         * The content slot will wrap the elements' height, so the height of the given content must
+         * be fixed or set to wrap ({@code expand} can't be used).
+         *
+         * This layout has built-in horizontal margins, so the given content should have width set
+         * to {@code expand} to use all the available space, rather than an explicit width which may
+         * lead to clipping.
+         */
+        @NonNull
+        public Builder setContent(@NonNull LayoutElement content) {
+            this.mContent = content;
+            mMetadataContentByte = (byte) (mMetadataContentByte | CONTENT_PRESENT);
+            return this;
+        }
+
+        /**
+         * Sets the vertical spacer height which is used as a space between main content and
+         * secondary label if there is any. If not set, {@link
+         * LayoutDefaults#DEFAULT_VERTICAL_SPACER_HEIGHT} will be used.
+         */
+        @NonNull
+        // The @Dimension(unit = DP) on dp() is seemingly being ignored, so lint complains that
+        // we're passing PX to something expecting DP. Just suppress the warning for now.
+        @SuppressLint("ResourceType")
+        public Builder setVerticalSpacerHeight(@Dimension(unit = DP) float height) {
+            this.mVerticalSpacerHeight = dp(height);
+            return this;
+        }
+
+        /** Constructs and returns {@link PrimaryLayout} with the provided content and look. */
+        // The @Dimension(unit = DP) on dp() is seemingly being ignored, so lint complains that
+        // we're passing DP to something expecting PX. Just suppress the warning for now.
+        @SuppressLint("ResourceType")
+        @NonNull
+        @Override
+        public PrimaryLayout build() {
+            float topPadding = getTopPadding();
+            float bottomPadding = getBottomPadding();
+            float horizontalPadding = getHorizontalPadding();
+            float horizontalChipPadding = getChipHorizontalPadding();
+
+            float primaryChipHeight = mPrimaryChip != null ? COMPACT_HEIGHT_TAPPABLE.getValue() : 0;
+
+            DpProp mainContentHeight =
+                    dp(
+                            mDeviceParameters.getScreenHeightDp()
+                                    - primaryChipHeight
+                                    - bottomPadding
+                                    - topPadding);
+
+            // Layout organization: column(column(primary label + spacer + (box(column(content +
+            // secondary label))) + chip)
+
+            // First column that has all other content and chip.
+            Column.Builder layoutBuilder = new Column.Builder();
+
+            // Contains primary label, main content and secondary label. Primary label will be
+            // wrapped, while other content will be expanded so it can be centered in the remaining
+            // space.
+            Column.Builder contentAreaBuilder =
+                    new Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(mainContentHeight)
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            // Contains main content and secondary label with wrapped height so it can be put inside
+            // of the Box to be centered.
+            Column.Builder contentSecondaryLabelBuilder =
+                    new Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(wrap())
+                            .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            // Needs to be in column because of the spacers.
+            Column.Builder primaryLabelBuilder =
+                    new Column.Builder().setWidth(expand()).setHeight(wrap());
+
+            if (mPrimaryLabelText != null) {
+                primaryLabelBuilder.addContent(
+                        new Spacer.Builder().setHeight(getPrimaryLabelTopSpacerHeight()).build());
+                primaryLabelBuilder.addContent(mPrimaryLabelText);
+            }
+
+            contentAreaBuilder.addContent(primaryLabelBuilder.build());
+
+            contentSecondaryLabelBuilder.addContent(
+                    new Box.Builder()
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(expand())
+                            .setHeight(wrap())
+                            .addContent(mContent)
+                            .build());
+
+            if (mSecondaryLabelText != null) {
+                contentSecondaryLabelBuilder.addContent(
+                        new Spacer.Builder().setHeight(mVerticalSpacerHeight).build());
+                contentSecondaryLabelBuilder.addContent(mSecondaryLabelText);
+            }
+
+            contentAreaBuilder.addContent(
+                    new Box.Builder()
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .addContent(contentSecondaryLabelBuilder.build())
+                            .build());
+
+            layoutBuilder
+                    .setModifiers(
+                            new Modifiers.Builder()
+                                    .setPadding(
+                                            new Padding.Builder()
+                                                    .setStart(dp(horizontalPadding))
+                                                    .setEnd(dp(horizontalPadding))
+                                                    .setTop(dp(topPadding))
+                                                    .setBottom(dp(bottomPadding))
+                                                    .build())
+                                    .build())
+                    .setWidth(expand())
+                    .setHeight(expand())
+                    .setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER);
+
+            layoutBuilder.addContent(contentAreaBuilder.build());
+
+            if (mPrimaryChip != null) {
+                layoutBuilder.addContent(
+                        new Box.Builder()
+                                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_BOTTOM)
+                                .setWidth(expand())
+                                .setHeight(wrap())
+                                .setModifiers(
+                                        new Modifiers.Builder()
+                                                .setPadding(
+                                                        new Padding.Builder()
+                                                                .setStart(dp(horizontalChipPadding))
+                                                                .setEnd(dp(horizontalChipPadding))
+                                                                .build())
+                                                .build())
+                                .addContent(mPrimaryChip)
+                                .build());
+            }
+
+            byte[] metadata = METADATA_TAG_BASE.clone();
+            metadata[FLAG_INDEX] = mMetadataContentByte;
+
+            Box.Builder element =
+                    new Box.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .setModifiers(
+                                    new Modifiers.Builder()
+                                            .setMetadata(
+                                                    new ElementMetadata.Builder()
+                                                            .setTagData(metadata)
+                                                            .build())
+                                            .build())
+                            .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_BOTTOM)
+                            .addContent(layoutBuilder.build());
+
+            return new PrimaryLayout(element.build());
+        }
+
+        /**
+         * Returns the recommended bottom padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        private float getBottomPadding() {
+            return mPrimaryChip != null
+                    ? (mDeviceParameters.getScreenHeightDp()
+                            * (isRoundDevice(mDeviceParameters)
+                                    ? PRIMARY_LAYOUT_MARGIN_BOTTOM_ROUND_PERCENT
+                                    : PRIMARY_LAYOUT_MARGIN_BOTTOM_SQUARE_PERCENT))
+                    : getTopPadding();
+        }
+
+        /**
+         * Returns the recommended top padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getTopPadding() {
+            return mDeviceParameters.getScreenHeightDp()
+                    * (isRoundDevice(mDeviceParameters)
+                            ? PRIMARY_LAYOUT_MARGIN_TOP_ROUND_PERCENT
+                            : PRIMARY_LAYOUT_MARGIN_TOP_SQUARE_PERCENT);
+        }
+
+        /**
+         * Returns the recommended horizontal padding, based on percentage values in {@link
+         * LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getHorizontalPadding() {
+            return mDeviceParameters.getScreenWidthDp()
+                    * (isRoundDevice(mDeviceParameters)
+                            ? PRIMARY_LAYOUT_MARGIN_HORIZONTAL_ROUND_PERCENT
+                            : PRIMARY_LAYOUT_MARGIN_HORIZONTAL_SQUARE_PERCENT);
+        }
+
+        /**
+         * Returns the recommended horizontal padding for primary chip, based on percentage values
+         * and DP values in {@link LayoutDefaults}.
+         */
+        @Dimension(unit = DP)
+        private float getChipHorizontalPadding() {
+            return isRoundDevice(mDeviceParameters)
+                    ? PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_ROUND_DP
+                    : PRIMARY_LAYOUT_CHIP_HORIZONTAL_PADDING_SQUARE_DP;
+        }
+
+        /** Returns the spacer height to be placed above primary label to accommodate Tile icon. */
+        @NonNull
+        private DpProp getPrimaryLabelTopSpacerHeight() {
+            return isRoundDevice(mDeviceParameters)
+                    ? PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_ROUND_DP
+                    : PRIMARY_LAYOUT_PRIMARY_LABEL_SPACER_HEIGHT_SQUARE_DP;
+        }
+    }
+
+    /** Get the primary label content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryLabelTextContent() {
+        if (!areElementsPresent(PRIMARY_LABEL_PRESENT)) {
+            return null;
+        }
+        return mPrimaryLabel.get(PRIMARY_LABEL_POSITION);
+    }
+
+    /** Get the secondary label content from this layout. */
+    @Nullable
+    public LayoutElement getSecondaryLabelTextContent() {
+        if (!areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            return null;
+        }
+        // By tag we know that secondary label exists. It will always be at last position.
+        return mContentAndSecondaryLabel.get(mContentAndSecondaryLabel.size() - 1);
+    }
+
+    /** Get the inner content from this layout. */
+    @Nullable
+    public LayoutElement getContent() {
+        if (!areElementsPresent(CONTENT_PRESENT)) {
+            return null;
+        }
+        return ((Box) mContentAndSecondaryLabel.get(CONTENT_ONLY_POSITION)).getContents().get(0);
+    }
+
+    /** Get the primary chip content from this layout. */
+    @Nullable
+    public LayoutElement getPrimaryChipContent() {
+        if (areElementsPresent(CHIP_PRESENT)) {
+            return ((Box) mAllContent.get(PRIMARY_CHIP_POSITION)).getContents().get(0);
+        }
+        return null;
+    }
+
+    /** Get the vertical spacer height from this layout. */
+    // The @Dimension(unit = DP) on getValue() is seemingly being ignored, so lint complains that
+    // we're passing PX to something expecting DP. Just suppress the warning for now.
+    @SuppressLint("ResourceType")
+    @Dimension(unit = DP)
+    public float getVerticalSpacerHeight() {
+        if (areElementsPresent(SECONDARY_LABEL_PRESENT)) {
+            LayoutElement element = mContentAndSecondaryLabel.get(CONTENT_ONLY_POSITION + 1);
+            if (element instanceof Spacer) {
+                SpacerDimension height = ((Spacer) element).getHeight();
+                if (height instanceof DpProp) {
+                    return ((DpProp) height).getValue();
+                }
+            }
+        }
+        return DEFAULT_VERTICAL_SPACER_HEIGHT.getValue();
+    }
+
+    private boolean areElementsPresent(@ContentBits int elementFlag) {
+        return (getMetadataTag()[FLAG_INDEX] & elementFlag) == elementFlag;
+    }
+
+    /** Returns metadata tag set to this PrimaryLayout. */
+    @NonNull
+    byte[] getMetadataTag() {
+        return getMetadataTagBytes(checkNotNull(checkNotNull(mImpl.getModifiers()).getMetadata()));
+    }
+
+    /**
+     * Returns PrimaryLayout object from the given LayoutElement (e.g. one retrieved from a
+     * container's content with {@code container.getContents().get(index)}) if that element can be
+     * converted to PrimaryLayout. Otherwise, it will return null.
+     */
+    @Nullable
+    public static PrimaryLayout fromLayoutElement(@NonNull LayoutElement element) {
+        if (element instanceof PrimaryLayout) {
+            return (PrimaryLayout) element;
+        }
+        if (!(element instanceof Box)) {
+            return null;
+        }
+        Box boxElement = (Box) element;
+        if (!checkTag(boxElement.getModifiers(), METADATA_TAG_PREFIX, METADATA_TAG_BASE)) {
+            return null;
+        }
+        // Now we are sure that this element is a PrimaryLayout.
+        return new PrimaryLayout(boxElement);
+    }
+
+    @NonNull
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public LayoutElementProto.LayoutElement toLayoutElementProto() {
+        return mImpl.toLayoutElementProto();
+    }
+
+    @Nullable
+    @Override
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    public Fingerprint getFingerprint() {
+        return mImpl.getFingerprint();
+    }
+}
diff --git a/wear/protolayout/protolayout/api/current.txt b/wear/protolayout/protolayout/api/current.txt
index b4afdb2..d4dbbd8 100644
--- a/wear/protolayout/protolayout/api/current.txt
+++ b/wear/protolayout/protolayout/api/current.txt
@@ -180,33 +180,48 @@
     method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
+    method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
     method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  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 public DimensionBuilders.AngularLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint.Builder setAngularAlignment(int);
   }
 
   public static interface DimensionBuilders.ContainerDimension {
   }
 
-  public static interface DimensionBuilders.ContainerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension build();
-  }
-
   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 public DimensionBuilders.DegreesProp.Builder();
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    ctor public DimensionBuilders.DegreesProp.Builder(float);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setValue(float);
   }
 
   public static final class DimensionBuilders.DpProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension 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 implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder androidx.wear.protolayout.DimensionBuilders.SpacerDimension.Builder {
-    ctor public DimensionBuilders.DpProp.Builder();
+  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 public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
   }
 
@@ -220,11 +235,28 @@
     method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
   }
 
-  public static interface DimensionBuilders.ImageDimension {
+  public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getLayoutWeight();
   }
 
-  public static interface DimensionBuilders.ImageDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension build();
+  public static final class DimensionBuilders.ExpandedDimensionProp.Builder {
+    ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp.Builder setLayoutWeight(androidx.wear.protolayout.TypeBuilders.FloatProp);
+  }
+
+  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 public DimensionBuilders.HorizontalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint.Builder setHorizontalAlignment(int);
+  }
+
+  public static interface DimensionBuilders.ImageDimension {
   }
 
   public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ImageDimension {
@@ -232,7 +264,7 @@
     method @IntRange(from=0) public int getAspectRatioWidth();
   }
 
-  public static final class DimensionBuilders.ProportionalDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
+  public static final class DimensionBuilders.ProportionalDimensionProp.Builder {
     ctor public DimensionBuilders.ProportionalDimensionProp.Builder();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp build();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
@@ -252,11 +284,32 @@
   public static interface DimensionBuilders.SpacerDimension {
   }
 
-  public static interface DimensionBuilders.SpacerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
+  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 public DimensionBuilders.VerticalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint.Builder setVerticalAlignment(int);
+  }
+
+  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 public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp.Builder setMinimumSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
   }
 
   public final class LayoutElementBuilders {
+    field public static final int ANGULAR_ALIGNMENT_CENTER = 2; // 0x2
+    field public static final int ANGULAR_ALIGNMENT_END = 3; // 0x3
+    field public static final int ANGULAR_ALIGNMENT_START = 1; // 0x1
+    field public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0; // 0x0
     field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
     field public static final int ARC_ANCHOR_END = 3; // 0x3
     field public static final int ARC_ANCHOR_START = 1; // 0x1
diff --git a/wear/protolayout/protolayout/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
index 19bb4e0..41ff5b2 100644
--- a/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout/api/public_plus_experimental_current.txt
@@ -192,33 +192,48 @@
     method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
+    method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
     method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  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 public DimensionBuilders.AngularLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint.Builder setAngularAlignment(int);
   }
 
   public static interface DimensionBuilders.ContainerDimension {
   }
 
-  public static interface DimensionBuilders.ContainerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension build();
-  }
-
   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 public DimensionBuilders.DegreesProp.Builder();
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    ctor public DimensionBuilders.DegreesProp.Builder(float);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setValue(float);
   }
 
   public static final class DimensionBuilders.DpProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension 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 implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder androidx.wear.protolayout.DimensionBuilders.SpacerDimension.Builder {
-    ctor public DimensionBuilders.DpProp.Builder();
+  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 public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
   }
 
@@ -232,11 +247,28 @@
     method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
   }
 
-  public static interface DimensionBuilders.ImageDimension {
+  public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getLayoutWeight();
   }
 
-  public static interface DimensionBuilders.ImageDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension build();
+  public static final class DimensionBuilders.ExpandedDimensionProp.Builder {
+    ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp.Builder setLayoutWeight(androidx.wear.protolayout.TypeBuilders.FloatProp);
+  }
+
+  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 public DimensionBuilders.HorizontalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint.Builder setHorizontalAlignment(int);
+  }
+
+  public static interface DimensionBuilders.ImageDimension {
   }
 
   public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ImageDimension {
@@ -244,7 +276,7 @@
     method @IntRange(from=0) public int getAspectRatioWidth();
   }
 
-  public static final class DimensionBuilders.ProportionalDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
+  public static final class DimensionBuilders.ProportionalDimensionProp.Builder {
     ctor public DimensionBuilders.ProportionalDimensionProp.Builder();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp build();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
@@ -264,11 +296,32 @@
   public static interface DimensionBuilders.SpacerDimension {
   }
 
-  public static interface DimensionBuilders.SpacerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
+  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 public DimensionBuilders.VerticalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint.Builder setVerticalAlignment(int);
+  }
+
+  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 public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp.Builder setMinimumSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
   }
 
   public final class LayoutElementBuilders {
+    field public static final int ANGULAR_ALIGNMENT_CENTER = 2; // 0x2
+    field public static final int ANGULAR_ALIGNMENT_END = 3; // 0x3
+    field public static final int ANGULAR_ALIGNMENT_START = 1; // 0x1
+    field public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0; // 0x0
     field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
     field public static final int ARC_ANCHOR_END = 3; // 0x3
     field public static final int ARC_ANCHOR_START = 1; // 0x1
diff --git a/wear/protolayout/protolayout/api/restricted_current.txt b/wear/protolayout/protolayout/api/restricted_current.txt
index b4afdb2..d4dbbd8 100644
--- a/wear/protolayout/protolayout/api/restricted_current.txt
+++ b/wear/protolayout/protolayout/api/restricted_current.txt
@@ -180,33 +180,48 @@
     method public static androidx.wear.protolayout.DimensionBuilders.DpProp dp(@Dimension(unit=androidx.annotation.Dimension.DP) float);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(int);
     method public static androidx.wear.protolayout.DimensionBuilders.EmProp em(float);
+    method public static androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp expand();
     method public static androidx.wear.protolayout.DimensionBuilders.SpProp sp(@Dimension(unit=androidx.annotation.Dimension.SP) float);
+    method public static androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp wrap();
+  }
+
+  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 public DimensionBuilders.AngularLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint.Builder setAngularAlignment(int);
   }
 
   public static interface DimensionBuilders.ContainerDimension {
   }
 
-  public static interface DimensionBuilders.ContainerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ContainerDimension build();
-  }
-
   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 public DimensionBuilders.DegreesProp.Builder();
+    ctor @Deprecated public DimensionBuilders.DegreesProp.Builder();
+    ctor public DimensionBuilders.DegreesProp.Builder(float);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DegreesProp.Builder setValue(float);
   }
 
   public static final class DimensionBuilders.DpProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension 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 implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension.Builder androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder androidx.wear.protolayout.DimensionBuilders.SpacerDimension.Builder {
-    ctor public DimensionBuilders.DpProp.Builder();
+  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 public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setDynamicValue(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public androidx.wear.protolayout.DimensionBuilders.DpProp.Builder setValue(@Dimension(unit=androidx.annotation.Dimension.DP) float);
   }
 
@@ -220,11 +235,28 @@
     method public androidx.wear.protolayout.DimensionBuilders.EmProp.Builder setValue(float);
   }
 
-  public static interface DimensionBuilders.ImageDimension {
+  public static final class DimensionBuilders.ExpandedDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ContainerDimension androidx.wear.protolayout.DimensionBuilders.ImageDimension {
+    method public androidx.wear.protolayout.TypeBuilders.FloatProp? getLayoutWeight();
   }
 
-  public static interface DimensionBuilders.ImageDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.ImageDimension build();
+  public static final class DimensionBuilders.ExpandedDimensionProp.Builder {
+    ctor public DimensionBuilders.ExpandedDimensionProp.Builder();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp build();
+    method public androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp.Builder setLayoutWeight(androidx.wear.protolayout.TypeBuilders.FloatProp);
+  }
+
+  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 public DimensionBuilders.HorizontalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.HorizontalLayoutConstraint.Builder setHorizontalAlignment(int);
+  }
+
+  public static interface DimensionBuilders.ImageDimension {
   }
 
   public static final class DimensionBuilders.ProportionalDimensionProp implements androidx.wear.protolayout.DimensionBuilders.ImageDimension {
@@ -232,7 +264,7 @@
     method @IntRange(from=0) public int getAspectRatioWidth();
   }
 
-  public static final class DimensionBuilders.ProportionalDimensionProp.Builder implements androidx.wear.protolayout.DimensionBuilders.ImageDimension.Builder {
+  public static final class DimensionBuilders.ProportionalDimensionProp.Builder {
     ctor public DimensionBuilders.ProportionalDimensionProp.Builder();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp build();
     method public androidx.wear.protolayout.DimensionBuilders.ProportionalDimensionProp.Builder setAspectRatioHeight(@IntRange(from=0) int);
@@ -252,11 +284,32 @@
   public static interface DimensionBuilders.SpacerDimension {
   }
 
-  public static interface DimensionBuilders.SpacerDimension.Builder {
-    method public androidx.wear.protolayout.DimensionBuilders.SpacerDimension build();
+  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 public DimensionBuilders.VerticalLayoutConstraint.Builder(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint build();
+    method public androidx.wear.protolayout.DimensionBuilders.VerticalLayoutConstraint.Builder setVerticalAlignment(int);
+  }
+
+  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 public androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp.Builder setMinimumSize(androidx.wear.protolayout.DimensionBuilders.DpProp);
   }
 
   public final class LayoutElementBuilders {
+    field public static final int ANGULAR_ALIGNMENT_CENTER = 2; // 0x2
+    field public static final int ANGULAR_ALIGNMENT_END = 3; // 0x3
+    field public static final int ANGULAR_ALIGNMENT_START = 1; // 0x1
+    field public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0; // 0x0
     field public static final int ARC_ANCHOR_CENTER = 2; // 0x2
     field public static final int ARC_ANCHOR_END = 3; // 0x3
     field public static final int ARC_ANCHOR_START = 1; // 0x1
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
index 2d04881..a8cb875 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/DimensionBuilders.java
@@ -18,768 +18,1307 @@
 
 import static androidx.annotation.Dimension.DP;
 import static androidx.annotation.Dimension.SP;
+import static androidx.wear.protolayout.expression.Preconditions.checkNotNull;
 
-import android.annotation.SuppressLint;
 import androidx.annotation.Dimension;
 import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.TypeBuilders.FloatProp;
+import androidx.wear.protolayout.expression.DynamicBuilders;
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat;
 import androidx.wear.protolayout.expression.Fingerprint;
 import androidx.wear.protolayout.proto.DimensionProto;
-import androidx.wear.protolayout.proto.TypesProto;
 
 /** Builders for dimensions for layout elements. */
 public final class DimensionBuilders {
-  private DimensionBuilders() {}
+    private DimensionBuilders() {}
 
-  /** Shortcut for building a {@link DpProp} using a measurement in DP. */
-  @NonNull
-  public static DpProp dp(@Dimension(unit = DP) float valueDp) {
-    return new DpProp.Builder().setValue(valueDp).build();
-  }
+    private static final ExpandedDimensionProp EXPAND = new ExpandedDimensionProp.Builder().build();
+    private static final WrappedDimensionProp WRAP = new WrappedDimensionProp.Builder().build();
 
-  /** Shortcut for building a {@link SpProp} using a measurement in SP. */
-  @NonNull
-  public static SpProp sp(@Dimension(unit = SP) float valueSp) {
-    return new SpProp.Builder().setValue(valueSp).build();
-  }
+    /** Shortcut for building a {@link DpProp} using a measurement in DP. */
+    @NonNull
+    public static DpProp dp(@Dimension(unit = DP) float valueDp) {
+        return new DpProp.Builder(valueDp).build();
+    }
 
-  /** Shortcut for building a {@link EmProp} using a measurement in EM. */
-  @NonNull
-  public static EmProp em(int valueEm) {
-    return new EmProp.Builder().setValue(valueEm).build();
-  }
-
-  /** Shortcut for building a {@link EmProp} using a measurement in EM. */
-  @NonNull
-  public static EmProp em(float valueEm) {
-    return new EmProp.Builder().setValue(valueEm).build();
-  }
-
-  /** Shortcut for building an {@link DegreesProp} using a measurement in degrees. */
-  @NonNull
-  public static DegreesProp degrees(float valueDegrees) {
-    return new DegreesProp.Builder().setValue(valueDegrees).build();
-  }
-
-  /** A type for linear dimensions, measured in dp.
-   *
-   * @since 1.0
-   */
-  public static final class DpProp implements ContainerDimension, ImageDimension, SpacerDimension {
-    private final DimensionProto.DpProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    DpProp(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+    /** Shortcut for building a {@link SpProp} using a measurement in SP. */
+    @NonNull
+    public static SpProp sp(@Dimension(unit = SP) float valueSp) {
+        return new SpProp.Builder().setValue(valueSp).build();
     }
 
     /**
-     * Gets the value, in dp.
+     * Shortcut for building a {@link EmProp} using a measurement in EM.
      *
      * @since 1.0
      */
-    @Dimension(unit = DP)
-    public float getValue() {
-      return mImpl.getValue();
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
     @NonNull
-    static DpProp fromProto(@NonNull DimensionProto.DpProp proto) {
-      return new DpProp(proto, null);
-    }
-
-    @NonNull
-    DimensionProto.DpProp toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.ContainerDimension toContainerDimensionProto() {
-      return DimensionProto.ContainerDimension.newBuilder().setLinearDimension(mImpl).build();
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.ImageDimension toImageDimensionProto() {
-      return DimensionProto.ImageDimension.newBuilder().setLinearDimension(mImpl).build();
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.SpacerDimension toSpacerDimensionProto() {
-      return DimensionProto.SpacerDimension.newBuilder().setLinearDimension(mImpl).build();
-    }
-
-    @Override
-    @NonNull
-    public String toString() {
-      return "DpProp{" + "value=" + getValue() + "}";
-    }
-
-    /** Builder for {@link DpProp}. */
-    public static final class Builder
-        implements ContainerDimension.Builder, ImageDimension.Builder, SpacerDimension.Builder {
-      private final DimensionProto.DpProp.Builder mImpl = DimensionProto.DpProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(756413087);
-
-      public Builder() {}
-
-      /**
-       * Sets the value, in dp.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setValue(@Dimension(unit = DP) float value) {
-        mImpl.setValue(value);
-        mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public DpProp build() {
-        return new DpProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for font sizes, measured in sp.
-   *
-   * @since 1.0
-   */
-  public static final class SpProp {
-    private final DimensionProto.SpProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    SpProp(DimensionProto.SpProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+    public static EmProp em(int valueEm) {
+        return new EmProp.Builder().setValue(valueEm).build();
     }
 
     /**
-     * Gets the value, in sp.
+     * Shortcut for building a {@link EmProp} using a measurement in EM.
      *
      * @since 1.0
      */
-    @Dimension(unit = SP)
-    public float getValue() {
-      return mImpl.getValue();
+    @NonNull
+    public static EmProp em(float valueEm) {
+        return new EmProp.Builder().setValue(valueEm).build();
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static SpProp fromProto(@NonNull DimensionProto.SpProp proto) {
-      return new SpProp(proto, null);
-    }
-
-    @NonNull
-    DimensionProto.SpProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link SpProp} */
-    public static final class Builder {
-      private final DimensionProto.SpProp.Builder mImpl = DimensionProto.SpProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(631793260);
-
-      public Builder() {}
-
-      /**
-       * Sets the value, in sp.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setValue(@Dimension(unit = SP) float value) {
-        mImpl.setValue(value);
-        mFingerprint.recordPropertyUpdate(2, Float.floatToIntBits(value));
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public SpProp build() {
-        return new SpProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for font spacing, measured in em.
-   *
-   * @since 1.0
-   */
-  public static final class EmProp {
-    private final DimensionProto.EmProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    EmProp(DimensionProto.EmProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the value, in em.
+     * Shortcut for building an {@link DegreesProp} using a measurement in degrees.
      *
      * @since 1.0
      */
-    public float getValue() {
-      return mImpl.getValue();
+    @NonNull
+    public static DegreesProp degrees(float valueDegrees) {
+        return new DegreesProp.Builder(valueDegrees).build();
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static EmProp fromProto(@NonNull DimensionProto.EmProp proto) {
-      return new EmProp(proto, null);
-    }
-
-    @NonNull
-    DimensionProto.EmProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link EmProp} */
-    public static final class Builder {
-      private final DimensionProto.EmProp.Builder mImpl = DimensionProto.EmProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-659639046);
-
-      public Builder() {}
-
-      /**
-       * Sets the value, in em.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setValue(float value) {
-        mImpl.setValue(value);
-        mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public EmProp build() {
-        return new EmProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for angular dimensions, measured in degrees.
-   *
-   * @since 1.0
-   */
-  public static final class DegreesProp {
-    private final DimensionProto.DegreesProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    DegreesProp(DimensionProto.DegreesProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the value, in degrees.
+     * Shortcut for building an {@link ExpandedDimensionProp} that will expand to the size of its
+     * parent.
      *
      * @since 1.0
      */
-    public float getValue() {
-      return mImpl.getValue();
+    @NonNull
+    public static ExpandedDimensionProp expand() {
+        return EXPAND;
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
+     * Shortcut for building an {@link WrappedDimensionProp} that will shrink to the size of its
+     * children.
      *
+     * @since 1.0
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
     @NonNull
-    static DegreesProp fromProto(@NonNull DimensionProto.DegreesProp proto) {
-      return new DegreesProp(proto, null);
-    }
-
-    @NonNull
-    DimensionProto.DegreesProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link DegreesProp} */
-    public static final class Builder {
-      private final DimensionProto.DegreesProp.Builder mImpl =
-          DimensionProto.DegreesProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1927567665);
-
-      public Builder() {}
-
-      /**
-       * Sets the value, in degrees.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setValue(float value) {
-        mImpl.setValue(value);
-        mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public DegreesProp build() {
-        return new DegreesProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for a dimension that fills all the space it can (i.e. MATCH_PARENT in Android parlance).
-   *
-   * @since 1.0
-   */
-  @RestrictTo(Scope.LIBRARY_GROUP)
-  public static final class ExpandedDimensionProp implements ContainerDimension, ImageDimension {
-    private final DimensionProto.ExpandedDimensionProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ExpandedDimensionProp(
-        DimensionProto.ExpandedDimensionProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+    public static WrappedDimensionProp wrap() {
+        return WRAP;
     }
 
     /**
-     * Gets the layout weight (a dimensionless scalar value) for this element. This will only affect
-     * the width of children of a {@link androidx.wear.protolayout.LayoutElementBuilders.Row} or the
-     * height of children of a {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By
-     * default, all children have equal weight. Where applicable, the width or height of the element
-     * is proportional to the sum of the weights of its siblings.
+     * A type for linear dimensions, measured in dp.
+     *
+     * @since 1.0
+     */
+    public static final class DpProp
+            implements ContainerDimension, ImageDimension, SpacerDimension {
+        private final DimensionProto.DpProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        DpProp(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the static value, in dp.
+         *
+         * @since 1.0
+         */
+        @Dimension(unit = DP)
+        public float getValue() {
+            return mImpl.getValue();
+        }
+
+        /**
+         * Gets the dynamic value, in dp.
+         *
+         * @since 1.2
+         */
+        @Nullable
+        public DynamicFloat getDynamicValue() {
+            if (mImpl.hasDynamicValue()) {
+                return DynamicBuilders.dynamicFloatFromProto(mImpl.getDynamicValue());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static DpProp fromProto(
+                @NonNull DimensionProto.DpProp proto, @Nullable Fingerprint fingerprint) {
+            return new DpProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static DpProp fromProto(@NonNull DimensionProto.DpProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.DpProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ContainerDimension toContainerDimensionProto() {
+            return DimensionProto.ContainerDimension.newBuilder().setLinearDimension(mImpl).build();
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ImageDimension toImageDimensionProto() {
+            return DimensionProto.ImageDimension.newBuilder().setLinearDimension(mImpl).build();
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.SpacerDimension toSpacerDimensionProto() {
+            return DimensionProto.SpacerDimension.newBuilder().setLinearDimension(mImpl).build();
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "DpProp{" + "value=" + getValue() + ", dynamicValue=" + getDynamicValue() + "}";
+        }
+
+        /** Builder for {@link DpProp}. */
+        public static final class Builder
+                implements ContainerDimension.Builder,
+                        ImageDimension.Builder,
+                        SpacerDimension.Builder {
+            private final DimensionProto.DpProp.Builder mImpl = DimensionProto.DpProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(756413087);
+
+            /**
+             * @deprecated Use {@link #Builder(float)} instead.
+             */
+            @Deprecated
+            public Builder() {}
+
+            /**
+             * Creates a instance of {@link Builder}.
+             *
+             * @param staticValue the static value, in dp.
+             */
+            public Builder(@Dimension(unit = DP) float staticValue) {
+                setValue(staticValue);
+            }
+
+            /**
+             * Sets the static value, in dp. If a dynamic value is also set and the renderer
+             * supports dynamic values for the corresponding field, this static value will be
+             * ignored.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setValue(@Dimension(unit = DP) float staticValue) {
+                mImpl.setValue(staticValue);
+                mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(staticValue));
+                return this;
+            }
+
+            /**
+             * Sets the dynamic value, in dp. 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.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setDynamicValue(@NonNull DynamicFloat dynamicValue) {
+                mImpl.setDynamicValue(dynamicValue.toDynamicFloatProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(dynamicValue.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public DpProp build() {
+                if (mImpl.hasDynamicValue() && !mImpl.hasValue()) {
+                    throw new IllegalStateException("Static value is missing.");
+                }
+                return new DpProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    private static class DpPropLayoutConstraint {
+        protected final DimensionProto.DpProp mImpl;
+        @Nullable protected final Fingerprint mFingerprint;
+
+        protected DpPropLayoutConstraint(
+                DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the fixed value to reserve the space when used on a layout-changing data bind.
+         *
+         * @since 1.2
+         */
+        @SuppressWarnings("Unused")
+        @Dimension(unit = DP)
+        public float getValue() {
+            return mImpl.getValueForLayout();
+        }
+
+        @SuppressWarnings("Unused")
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Builder for {@link DpPropLayoutConstraint}. */
+        protected static class Builder {
+            protected final DimensionProto.DpProp.Builder mImpl =
+                    DimensionProto.DpProp.newBuilder();
+            protected final Fingerprint mFingerprint = new Fingerprint(756413088);
+
+            /**
+             * Creates a new builder for {@link DpPropLayoutConstraint}.
+             *
+             * @param value Sets the fixed value to reserve the space when used on a layout-changing
+             *     data bind.
+             * @since 1.2
+             */
+            protected Builder(@Dimension(unit = DP) float value) {
+                setValue(value);
+            }
+
+            /**
+             * Sets the fixed value to reserve the space when used on a layout-changing data bind.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            private Builder setValue(@Dimension(unit = DP) float value) {
+                mImpl.setValueForLayout(value);
+                mFingerprint.recordPropertyUpdate(3, Float.floatToIntBits(value));
+                return this;
+            }
+        }
+    }
+
+    /**
+     * A type for specifying horizontal layout constraints when using {@link DpProp} on a data
+     * bindable layout element.
      *
      * @since 1.2
      */
-    public float getLayoutWeight() {
-      return mImpl.getLayoutWeight().getValue();
-    }
+    public static final class HorizontalLayoutConstraint extends DpPropLayoutConstraint {
+        HorizontalLayoutConstraint(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
+            super(impl, fingerprint);
+        }
 
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
+        /**
+         * Gets the horizontal alignment of the actual content within the space reserved by value.
+         *
+         * @since 1.2
+         */
+        @LayoutElementBuilders.HorizontalAlignment
+        public int getHorizontalAlignment() {
+            return mImpl.getHorizontalAlignmentForLayoutValue();
+        }
 
-    @NonNull
-    static ExpandedDimensionProp fromProto(@NonNull DimensionProto.ExpandedDimensionProp proto) {
-      return new ExpandedDimensionProp(proto, null);
-    }
+        /** Builder for {@link HorizontalLayoutConstraint}. */
+        public static final class Builder extends DpPropLayoutConstraint.Builder {
+            /**
+             * Creates a new builder for {@link HorizontalLayoutConstraint}.
+             *
+             * @param value Sets the fixed value to reserve the space when used on a layout-changing
+             *     data bind.
+             * @since 1.2
+             */
+            public Builder(@Dimension(unit = DP) float value) {
+                super(value);
+            }
 
-    @NonNull
-    DimensionProto.ExpandedDimensionProp toProto() {
-      return mImpl;
-    }
+            /**
+             * Sets the horizontal alignment of the actual content within the space reserved by
+             * value. If not specified, defaults to center alignment.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setHorizontalAlignment(
+                    @LayoutElementBuilders.HorizontalAlignment int horizontalAlignment) {
+                mImpl.setHorizontalAlignmentForLayoutValue(horizontalAlignment);
+                mFingerprint.recordPropertyUpdate(5, horizontalAlignment);
+                return this;
+            }
 
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.ContainerDimension toContainerDimensionProto() {
-      return DimensionProto.ContainerDimension.newBuilder().setExpandedDimension(mImpl).build();
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.ImageDimension toImageDimensionProto() {
-      return DimensionProto.ImageDimension.newBuilder().setExpandedDimension(mImpl).build();
-    }
-
-    /** Builder for {@link ExpandedDimensionProp}. */
-    public static final class Builder
-        implements ContainerDimension.Builder, ImageDimension.Builder {
-      private final DimensionProto.ExpandedDimensionProp.Builder mImpl =
-          DimensionProto.ExpandedDimensionProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-997720604);
-
-      public Builder() {}
-
-      /**
-       * Sets the layout weight (a dimensionless scalar value) for this element. This will only
-       * affect the width of children of a {@link
-       * androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a {@link
-       * androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all children have
-       * equal weight. Where applicable, the width or height of the element is proportional to the
-       * sum of the weights of its siblings.
-       *
-       * @since 1.2
-       */
-      @NonNull
-      public Builder setLayoutWeight(float layoutWeight) {
-        mImpl.setLayoutWeight(TypesProto.FloatProp.newBuilder().setValue(layoutWeight));
-        mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(layoutWeight));
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public ExpandedDimensionProp build() {
-        return new ExpandedDimensionProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for a dimension that sizes itself to the size of its children (i.e. WRAP_CONTENT in
-   * Android parlance).
-   *
-   * @since 1.0
-   */
-  @RestrictTo(Scope.LIBRARY_GROUP)
-  public static final class WrappedDimensionProp implements ContainerDimension {
-    private final DimensionProto.WrappedDimensionProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    WrappedDimensionProp(
-        DimensionProto.WrappedDimensionProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+            /** Builds an instance of {@link HorizontalLayoutConstraint}. */
+            @NonNull
+            public HorizontalLayoutConstraint build() {
+                return new HorizontalLayoutConstraint(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Gets the minimum size of this dimension. If not set, then there is no minimum size.
+     * A type for specifying vertical layout constraints when using {@link DpProp} on a data
+     * bindable layout element.
      *
      * @since 1.2
      */
-    @Dimension(unit = DP)
-    public float getMinimumSizeDp() {
-      return mImpl.getMinimumSize().getValue();
-    }
+    public static final class VerticalLayoutConstraint extends DpPropLayoutConstraint {
+        VerticalLayoutConstraint(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
+            super(impl, fingerprint);
+        }
 
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
+        /**
+         * Gets the vertical alignment of the actual content within the space reserved by value.
+         *
+         * @since 1.2
+         */
+        @LayoutElementBuilders.VerticalAlignment
+        public int getVerticalAlignment() {
+            return mImpl.getVerticalAlignmentForLayoutValue();
+        }
 
-    @NonNull
-    static WrappedDimensionProp fromProto(@NonNull DimensionProto.WrappedDimensionProp proto) {
-      return new WrappedDimensionProp(proto, null);
-    }
+        /** Builder for {@link VerticalLayoutConstraint}. */
+        public static final class Builder extends DpPropLayoutConstraint.Builder {
+            /**
+             * Creates a new builder for {@link VerticalLayoutConstraint}.
+             *
+             * @param value Sets the fixed value to reserve the space when used on a layout-changing
+             *     data bind.
+             * @since 1.2
+             */
+            public Builder(@Dimension(unit = DP) float value) {
+                super(value);
+            }
 
-    @NonNull
-    DimensionProto.WrappedDimensionProp toProto() {
-      return mImpl;
-    }
+            /**
+             * Sets the vertical alignment of the actual content within the space reserved by value.
+             * If not specified, defaults to center alignment.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setVerticalAlignment(
+                    @LayoutElementBuilders.VerticalAlignment int verticalAlignment) {
+                mImpl.setVerticalAlignmentForLayoutValue(verticalAlignment);
+                mFingerprint.recordPropertyUpdate(4, verticalAlignment);
+                return this;
+            }
 
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public DimensionProto.ContainerDimension toContainerDimensionProto() {
-      return DimensionProto.ContainerDimension.newBuilder().setWrappedDimension(mImpl).build();
-    }
-
-    /** Builder for {@link WrappedDimensionProp}. */
-    public static final class Builder implements ContainerDimension.Builder {
-      private final DimensionProto.WrappedDimensionProp.Builder mImpl =
-          DimensionProto.WrappedDimensionProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1118918114);
-
-      public Builder() {}
-
-      /**
-       * Sets the minimum size of this dimension. If not set, then there is no minimum size.
-       *
-       * @since 1.2
-       */
-      @NonNull
-      public Builder setMinimumSizeDp(@Dimension(unit = DP) float minimumSize) {
-        mImpl.setMinimumSize(DimensionProto.DpProp.newBuilder().setValue(minimumSize));
-        mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(minimumSize));
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public WrappedDimensionProp build() {
-        return new WrappedDimensionProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A type for a dimension that scales itself proportionally to another dimension such that the
-   * aspect ratio defined by the given width and height values is preserved.
-   *
-   * <p>Note that the width and height are unitless; only their ratio is relevant. This allows for
-   * specifying an element's size using common ratios (e.g. width=4, height=3), or to allow an
-   * element to be resized proportionally based on the size of an underlying asset (e.g. an 800x600
-   * image being added to a smaller container and resized accordingly).
-   *
-   * @since 1.0
-   */
-  public static final class ProportionalDimensionProp implements ImageDimension {
-    private final DimensionProto.ProportionalDimensionProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ProportionalDimensionProp(
-        DimensionProto.ProportionalDimensionProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+            /** Builds an instance of {@link VerticalLayoutConstraint}. */
+            @NonNull
+            public VerticalLayoutConstraint build() {
+                return new VerticalLayoutConstraint(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Gets the width to be used when calculating the aspect ratio to preserve.
+     * A type for font sizes, measured in sp.
      *
      * @since 1.0
      */
-    @IntRange(from = 0)
-    public int getAspectRatioWidth() {
-      return mImpl.getAspectRatioWidth();
+    public static final class SpProp {
+        private final DimensionProto.SpProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        SpProp(DimensionProto.SpProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the value, in sp.
+         *
+         * @since 1.0
+         */
+        @Dimension(unit = SP)
+        public float getValue() {
+            return mImpl.getValue();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static SpProp fromProto(
+                @NonNull DimensionProto.SpProp proto, @Nullable Fingerprint fingerprint) {
+            return new SpProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static SpProp fromProto(@NonNull DimensionProto.SpProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.SpProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "SpProp{" + "value=" + getValue() + "}";
+        }
+
+        /** Builder for {@link SpProp} */
+        public static final class Builder {
+            private final DimensionProto.SpProp.Builder mImpl = DimensionProto.SpProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(631793260);
+
+            public Builder() {}
+
+            /**
+             * Sets the value, in sp. If a dynamic value is also set and the renderer supports
+             * dynamic values for the corresponding field, this static value will be ignored.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setValue(@Dimension(unit = SP) float value) {
+                mImpl.setValue(value);
+                mFingerprint.recordPropertyUpdate(2, Float.floatToIntBits(value));
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public SpProp build() {
+                return new SpProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Gets the height to be used when calculating the aspect ratio ratio to preserve.
+     * A type for font spacing, measured in em.
      *
      * @since 1.0
      */
-    @IntRange(from = 0)
-    public int getAspectRatioHeight() {
-      return mImpl.getAspectRatioHeight();
+    public static final class EmProp {
+        private final DimensionProto.EmProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        EmProp(DimensionProto.EmProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the value, in em.
+         *
+         * @since 1.0
+         */
+        public float getValue() {
+            return mImpl.getValue();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static EmProp fromProto(
+                @NonNull DimensionProto.EmProp proto, @Nullable Fingerprint fingerprint) {
+            return new EmProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static EmProp fromProto(@NonNull DimensionProto.EmProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.EmProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "EmProp{" + "value=" + getValue() + "}";
+        }
+
+        /** Builder for {@link EmProp} */
+        public static final class Builder {
+            private final DimensionProto.EmProp.Builder mImpl = DimensionProto.EmProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-659639046);
+
+            public Builder() {}
+
+            /**
+             * Sets the value, in em.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setValue(float value) {
+                mImpl.setValue(value);
+                mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public EmProp build() {
+                return new EmProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    @Override
+    /**
+     * A type for angular dimensions, measured in degrees.
+     *
+     * @since 1.0
+     */
+    public static final class DegreesProp {
+        private final DimensionProto.DegreesProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        DegreesProp(DimensionProto.DegreesProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the static value, in degrees.
+         *
+         * @since 1.0
+         */
+        public float getValue() {
+            return mImpl.getValue();
+        }
+
+        /**
+         * Gets the dynamic value, in degrees.
+         *
+         * @since 1.2
+         */
+        @Nullable
+        public DynamicFloat getDynamicValue() {
+            if (mImpl.hasDynamicValue()) {
+                return DynamicBuilders.dynamicFloatFromProto(mImpl.getDynamicValue());
+            } else {
+                return null;
+            }
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static DegreesProp fromProto(
+                @NonNull DimensionProto.DegreesProp proto, @Nullable Fingerprint fingerprint) {
+            return new DegreesProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static DegreesProp fromProto(@NonNull DimensionProto.DegreesProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.DegreesProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "DegreesProp{"
+                    + "value="
+                    + getValue()
+                    + ", dynamicValue="
+                    + getDynamicValue()
+                    + "}";
+        }
+
+        /** Builder for {@link DegreesProp} */
+        public static final class Builder {
+            private final DimensionProto.DegreesProp.Builder mImpl =
+                    DimensionProto.DegreesProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1927567665);
+
+            /**
+             * @deprecated Use {@link #Builder(float)} instead.
+             */
+            @Deprecated
+            public Builder() {}
+
+            /**
+             * Creates a instance of {@link Builder}.
+             *
+             * @param staticValue the static value, in degrees.
+             */
+            public Builder(float staticValue) {
+                setValue(staticValue);
+            }
+
+            /**
+             * Sets the static value, in degrees. If a dynamic value is also set and the renderer
+             * supports dynamic values for the corresponding field, this static value will be
+             * ignored.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setValue(float staticValue) {
+                mImpl.setValue(staticValue);
+                mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(staticValue));
+                return this;
+            }
+
+            /**
+             * Sets the dynamic value, in degrees. 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.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setDynamicValue(@NonNull DynamicFloat dynamicValue) {
+                mImpl.setDynamicValue(dynamicValue.toDynamicFloatProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(dynamicValue.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public DegreesProp build() {
+                if (mImpl.hasDynamicValue() && !mImpl.hasValue()) {
+                    throw new IllegalStateException("Static value is missing.");
+                }
+                return new DegreesProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A type for specifying layout constraints when using {@link DegreesProp} on a data bindable
+     * layout element.
+     *
+     * @since 1.2
+     */
+    public static final class AngularLayoutConstraint {
+        private final DimensionProto.DegreesProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        AngularLayoutConstraint(
+                DimensionProto.DegreesProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the fixed value to reserve the space when used on a layout-changing data bind.
+         *
+         * @since 1.2
+         */
+        @Dimension(unit = DP)
+        public float getValue() {
+            return mImpl.getValueForLayout();
+        }
+
+        /**
+         * Gets angular alignment of the actual content within the space reserved by value.
+         *
+         * @since 1.2
+         */
+        @LayoutElementBuilders.AngularAlignment
+        public int getAngularAlignment() {
+            return mImpl.getAngularAlignmentForLayoutValue();
+        }
+
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Builder for {@link AngularLayoutConstraint}. */
+        public static final class Builder {
+            private final DimensionProto.DegreesProp.Builder mImpl =
+                    DimensionProto.DegreesProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1927567664);
+
+            /**
+             * Creates a new builder for {@link AngularLayoutConstraint}.
+             *
+             * @param value Sets the fixed value to reserve the space when used on a layout-changing
+             *     data bind.
+             * @since 1.2
+             */
+            public Builder(@Dimension(unit = DP) float value) {
+                setValue(value);
+            }
+
+            /**
+             * Sets the fixed value to reserve the space when used on a layout-changing data bind.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            private Builder setValue(@Dimension(unit = DP) float value) {
+                mImpl.setValueForLayout(value);
+                mFingerprint.recordPropertyUpdate(3, Float.floatToIntBits(value));
+                return this;
+            }
+
+            /**
+             * Sets angular alignment of the actual content within the space reserved by value. If
+             * not specified, defaults to center alignment.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setAngularAlignment(
+                    @LayoutElementBuilders.AngularAlignment int angularAlignment) {
+                mImpl.setAngularAlignmentForLayoutValue(angularAlignment);
+                mFingerprint.recordPropertyUpdate(4, angularAlignment);
+                return this;
+            }
+
+            /** Builds an instance of {@link AngularLayoutConstraint}. */
+            @NonNull
+            public AngularLayoutConstraint build() {
+                return new AngularLayoutConstraint(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A type for a dimension that fills all the space it can (i.e. MATCH_PARENT in Android
+     * parlance).
+     *
+     * @since 1.0
+     */
+    public static final class ExpandedDimensionProp implements ContainerDimension, ImageDimension {
+        private final DimensionProto.ExpandedDimensionProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ExpandedDimensionProp(
+                DimensionProto.ExpandedDimensionProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the layout weight (a dimensionless scalar value) for this element. This will only
+         * affect the width of children of a {@link
+         * androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a
+         * {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all children
+         * have equal weight. Where applicable, the width or height of the element is proportional
+         * to the sum of the weights of its siblings.
+         *
+         * @since 1.2
+         */
+        @Nullable
+        public FloatProp getLayoutWeight() {
+            if (mImpl.hasLayoutWeight()) {
+                return FloatProp.fromProto(mImpl.getLayoutWeight());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static ExpandedDimensionProp fromProto(
+                @NonNull DimensionProto.ExpandedDimensionProp proto,
+                @Nullable Fingerprint fingerprint) {
+            return new ExpandedDimensionProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static ExpandedDimensionProp fromProto(
+                @NonNull DimensionProto.ExpandedDimensionProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.ExpandedDimensionProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ContainerDimension toContainerDimensionProto() {
+            return DimensionProto.ContainerDimension.newBuilder()
+                    .setExpandedDimension(mImpl)
+                    .build();
+        }
+
+        /* */
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ImageDimension toImageDimensionProto() {
+            return DimensionProto.ImageDimension.newBuilder().setExpandedDimension(mImpl).build();
+        }
+
+        /** Builder for {@link ExpandedDimensionProp}. */
+        public static final class Builder
+                implements ContainerDimension.Builder, ImageDimension.Builder {
+            private final DimensionProto.ExpandedDimensionProp.Builder mImpl =
+                    DimensionProto.ExpandedDimensionProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-997720604);
+
+            public Builder() {}
+
+            /**
+             * Sets the layout weight (a dimensionless scalar value) for this element. This will
+             * only affect the width of children of a {@link
+             * androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a
+             * {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all
+             * children have equal weight. Where applicable, the width or height of the element is
+             * proportional to the sum of the weights of its siblings.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setLayoutWeight(@NonNull FloatProp layoutWeight) {
+                mImpl.setLayoutWeight(layoutWeight.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(layoutWeight.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ExpandedDimensionProp build() {
+                return new ExpandedDimensionProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A type for a dimension that sizes itself to the size of its children (i.e. WRAP_CONTENT in
+     * Android parlance).
+     *
+     * @since 1.0
+     */
+    public static final class WrappedDimensionProp implements ContainerDimension {
+        private final DimensionProto.WrappedDimensionProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        WrappedDimensionProp(
+                DimensionProto.WrappedDimensionProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the minimum size of this dimension. If not set, then there is no minimum size.
+         *
+         * @since 1.2
+         */
+        @Nullable
+        public DpProp getMinimumSize() {
+            if (mImpl.hasMinimumSize()) {
+                return DpProp.fromProto(mImpl.getMinimumSize());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static WrappedDimensionProp fromProto(
+                @NonNull DimensionProto.WrappedDimensionProp proto,
+                @Nullable Fingerprint fingerprint) {
+            return new WrappedDimensionProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static WrappedDimensionProp fromProto(@NonNull DimensionProto.WrappedDimensionProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.WrappedDimensionProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ContainerDimension toContainerDimensionProto() {
+            return DimensionProto.ContainerDimension.newBuilder()
+                    .setWrappedDimension(mImpl)
+                    .build();
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "WrappedDimensionProp{" + "minimumSize=" + getMinimumSize() + "}";
+        }
+
+        /** Builder for {@link WrappedDimensionProp}. */
+        public static final class Builder implements ContainerDimension.Builder {
+            private final DimensionProto.WrappedDimensionProp.Builder mImpl =
+                    DimensionProto.WrappedDimensionProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1118918114);
+
+            public Builder() {}
+
+            /**
+             * Sets the minimum size of this dimension. If not set, then there is no minimum size.
+             *
+             * <p>Note that this field only supports static values.
+             *
+             * @since 1.2
+             */
+            @NonNull
+            public Builder setMinimumSize(@NonNull DpProp minimumSize) {
+                if (minimumSize.getDynamicValue() != null) {
+                    throw new IllegalArgumentException(
+                            "setMinimumSize doesn't support dynamic values.");
+                }
+
+                mImpl.setMinimumSize(minimumSize.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(minimumSize.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public WrappedDimensionProp build() {
+                return new WrappedDimensionProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A type for a dimension that scales itself proportionally to another dimension such that the
+     * aspect ratio defined by the given width and height values is preserved.
+     *
+     * <p>Note that the width and height are unitless; only their ratio is relevant. This allows for
+     * specifying an element's size using common ratios (e.g. width=4, height=3), or to allow an
+     * element to be resized proportionally based on the size of an underlying asset (e.g. an
+     * 800x600 image being added to a smaller container and resized accordingly).
+     *
+     * @since 1.0
+     */
+    public static final class ProportionalDimensionProp implements ImageDimension {
+        private final DimensionProto.ProportionalDimensionProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ProportionalDimensionProp(
+                DimensionProto.ProportionalDimensionProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the width to be used when calculating the aspect ratio to preserve.
+         *
+         * @since 1.0
+         */
+        @IntRange(from = 0)
+        public int getAspectRatioWidth() {
+            return mImpl.getAspectRatioWidth();
+        }
+
+        /**
+         * Gets the height to be used when calculating the aspect ratio ratio to preserve.
+         *
+         * @since 1.0
+         */
+        @IntRange(from = 0)
+        public int getAspectRatioHeight() {
+            return mImpl.getAspectRatioHeight();
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        /** Creates a new wrapper instance from the proto. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public static ProportionalDimensionProp fromProto(
+                @NonNull DimensionProto.ProportionalDimensionProp proto,
+                @Nullable Fingerprint fingerprint) {
+            return new ProportionalDimensionProp(proto, fingerprint);
+        }
+
+        @NonNull
+        static ProportionalDimensionProp fromProto(
+                @NonNull DimensionProto.ProportionalDimensionProp proto) {
+            return fromProto(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.ProportionalDimensionProp toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public DimensionProto.ImageDimension toImageDimensionProto() {
+            return DimensionProto.ImageDimension.newBuilder()
+                    .setProportionalDimension(mImpl)
+                    .build();
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "ProportionalDimensionProp{"
+                    + "aspectRatioWidth="
+                    + getAspectRatioWidth()
+                    + ", aspectRatioHeight="
+                    + getAspectRatioHeight()
+                    + "}";
+        }
+
+        /** Builder for {@link ProportionalDimensionProp}. */
+        public static final class Builder implements ImageDimension.Builder {
+            private final DimensionProto.ProportionalDimensionProp.Builder mImpl =
+                    DimensionProto.ProportionalDimensionProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1725027476);
+
+            public Builder() {}
+
+            /**
+             * Sets the width to be used when calculating the aspect ratio to preserve.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setAspectRatioWidth(@IntRange(from = 0) int aspectRatioWidth) {
+                mImpl.setAspectRatioWidth(aspectRatioWidth);
+                mFingerprint.recordPropertyUpdate(1, aspectRatioWidth);
+                return this;
+            }
+
+            /**
+             * Sets the height to be used when calculating the aspect ratio ratio to preserve.
+             *
+             * @since 1.0
+             */
+            @NonNull
+            public Builder setAspectRatioHeight(@IntRange(from = 0) int aspectRatioHeight) {
+                mImpl.setAspectRatioHeight(aspectRatioHeight);
+                mFingerprint.recordPropertyUpdate(2, aspectRatioHeight);
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ProportionalDimensionProp build() {
+                return new ProportionalDimensionProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * Interface defining a dimension that can be applied to a container.
+     *
+     * @since 1.0
+     */
+    public interface ContainerDimension {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.ContainerDimension toContainerDimensionProto();
+
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
+
+        /** Builder to create {@link ContainerDimension} objects. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        interface Builder {
+
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            ContainerDimension build();
+        }
+    }
+
+    /** Creates a new wrapper instance from the proto. */
     @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
+    @NonNull
+    public static ContainerDimension containerDimensionFromProto(
+            @NonNull DimensionProto.ContainerDimension proto, @Nullable Fingerprint fingerprint) {
+        if (proto.hasLinearDimension()) {
+            return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
+        }
+        if (proto.hasExpandedDimension()) {
+            return ExpandedDimensionProp.fromProto(proto.getExpandedDimension(), fingerprint);
+        }
+        if (proto.hasWrappedDimension()) {
+            return WrappedDimensionProp.fromProto(proto.getWrappedDimension(), fingerprint);
+        }
+        throw new IllegalStateException(
+                "Proto was not a recognised instance of ContainerDimension");
     }
 
     @NonNull
-    static ProportionalDimensionProp fromProto(
-        @NonNull DimensionProto.ProportionalDimensionProp proto) {
-      return new ProportionalDimensionProp(proto, null);
+    static ContainerDimension containerDimensionFromProto(
+            @NonNull DimensionProto.ContainerDimension proto) {
+        return containerDimensionFromProto(proto, null);
+    }
+
+    /**
+     * Interface defining a dimension that can be applied to an image.
+     *
+     * @since 1.0
+     */
+    public interface ImageDimension {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.ImageDimension toImageDimensionProto();
+
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
+
+        /** Builder to create {@link ImageDimension} objects. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        interface Builder {
+
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            ImageDimension build();
+        }
+    }
+
+    /** Creates a new wrapper instance from the proto. */
+    @RestrictTo(Scope.LIBRARY_GROUP)
+    @NonNull
+    public static ImageDimension imageDimensionFromProto(
+            @NonNull DimensionProto.ImageDimension proto, @Nullable Fingerprint fingerprint) {
+        if (proto.hasLinearDimension()) {
+            return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
+        }
+        if (proto.hasExpandedDimension()) {
+            return ExpandedDimensionProp.fromProto(proto.getExpandedDimension(), fingerprint);
+        }
+        if (proto.hasProportionalDimension()) {
+            return ProportionalDimensionProp.fromProto(
+                    proto.getProportionalDimension(), fingerprint);
+        }
+        throw new IllegalStateException("Proto was not a recognised instance of ImageDimension");
     }
 
     @NonNull
-    DimensionProto.ProportionalDimensionProp toProto() {
-      return mImpl;
+    static ImageDimension imageDimensionFromProto(@NonNull DimensionProto.ImageDimension proto) {
+        return imageDimensionFromProto(proto, null);
     }
 
-    @Override
+    /**
+     * Interface defining a dimension that can be applied to a spacer.
+     *
+     * @since 1.0
+     */
+    public interface SpacerDimension {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        DimensionProto.SpacerDimension toSpacerDimensionProto();
+
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
+
+        /** Builder to create {@link SpacerDimension} objects. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        interface Builder {
+
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            SpacerDimension build();
+        }
+    }
+
+    /** Creates a new wrapper instance from the proto. */
     @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    public DimensionProto.ImageDimension toImageDimensionProto() {
-      return DimensionProto.ImageDimension.newBuilder().setProportionalDimension(mImpl).build();
+    public static SpacerDimension spacerDimensionFromProto(
+            @NonNull DimensionProto.SpacerDimension proto, @Nullable Fingerprint fingerprint) {
+        if (proto.hasLinearDimension()) {
+            return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
+        }
+        throw new IllegalStateException("Proto was not a recognised instance of SpacerDimension");
     }
 
-    /** Builder for {@link ProportionalDimensionProp}. */
-    public static final class Builder implements ImageDimension.Builder {
-      private final DimensionProto.ProportionalDimensionProp.Builder mImpl =
-          DimensionProto.ProportionalDimensionProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1725027476);
-
-      public Builder() {}
-
-      /**
-       * Sets the width to be used when calculating the aspect ratio to preserve.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setAspectRatioWidth(@IntRange(from = 0) int aspectRatioWidth) {
-        mImpl.setAspectRatioWidth(aspectRatioWidth);
-        mFingerprint.recordPropertyUpdate(1, aspectRatioWidth);
-        return this;
-      }
-
-      /**
-       * Sets the height to be used when calculating the aspect ratio ratio to preserve.
-       *
-       * @since 1.0
-       */
-      @NonNull
-      public Builder setAspectRatioHeight(@IntRange(from = 0) int aspectRatioHeight) {
-        mImpl.setAspectRatioHeight(aspectRatioHeight);
-        mFingerprint.recordPropertyUpdate(2, aspectRatioHeight);
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public ProportionalDimensionProp build() {
-        return new ProportionalDimensionProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * Interface defining a dimension that can be applied to a container.
-   *
-   * @since 1.0
-   */
-  public interface ContainerDimension {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
     @NonNull
-    DimensionProto.ContainerDimension toContainerDimensionProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link ContainerDimension} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      ContainerDimension build();
+    static SpacerDimension spacerDimensionFromProto(@NonNull DimensionProto.SpacerDimension proto) {
+        return spacerDimensionFromProto(proto, null);
     }
-  }
-
-  @NonNull
-  static ContainerDimension containerDimensionFromProto(
-      @NonNull DimensionProto.ContainerDimension proto) {
-    if (proto.hasLinearDimension()) {
-      return DpProp.fromProto(proto.getLinearDimension());
-    }
-    if (proto.hasExpandedDimension()) {
-      return ExpandedDimensionProp.fromProto(proto.getExpandedDimension());
-    }
-    if (proto.hasWrappedDimension()) {
-      return WrappedDimensionProp.fromProto(proto.getWrappedDimension());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of ContainerDimension");
-  }
-
-  /**
-   * Interface defining a dimension that can be applied to an image.
-   *
-   * @since 1.0
-   */
-  public interface ImageDimension {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    DimensionProto.ImageDimension toImageDimensionProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link ImageDimension} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      ImageDimension build();
-    }
-  }
-
-  @NonNull
-  static ImageDimension imageDimensionFromProto(@NonNull DimensionProto.ImageDimension proto) {
-    if (proto.hasLinearDimension()) {
-      return DpProp.fromProto(proto.getLinearDimension());
-    }
-    if (proto.hasExpandedDimension()) {
-      return ExpandedDimensionProp.fromProto(proto.getExpandedDimension());
-    }
-    if (proto.hasProportionalDimension()) {
-      return ProportionalDimensionProp.fromProto(proto.getProportionalDimension());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of ImageDimension");
-  }
-
-  /**
-   * Interface defining a dimension that can be applied to a spacer.
-   *
-   * @since 1.0
-   */
-  public interface SpacerDimension {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    DimensionProto.SpacerDimension toSpacerDimensionProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link SpacerDimension} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      SpacerDimension build();
-    }
-  }
-
-  @NonNull
-  static SpacerDimension spacerDimensionFromProto(@NonNull DimensionProto.SpacerDimension proto) {
-    if (proto.hasLinearDimension()) {
-      return DpProp.fromProto(proto.getLinearDimension());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of SpacerDimension");
-  }
 }
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 03a015a..bde4f91b 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
@@ -56,4052 +56,4012 @@
 import java.util.Collections;
 import java.util.List;
 
-/** Builders for composable layout elements that can be combined together to create renderable
- * UI */
+/** Builders for composable layout elements that can be combined together to create renderable UI */
 public final class LayoutElementBuilders {
-  private LayoutElementBuilders() {}
+    private LayoutElementBuilders() {}
 
-  /**
-   * The weight to be applied to the font.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({FONT_WEIGHT_UNDEFINED, FONT_WEIGHT_NORMAL, FONT_WEIGHT_MEDIUM, FONT_WEIGHT_BOLD})
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface FontWeight {}
+    /** The weight to be applied to the font. */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({FONT_WEIGHT_UNDEFINED, FONT_WEIGHT_NORMAL, FONT_WEIGHT_MEDIUM, FONT_WEIGHT_BOLD})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FontWeight {}
 
-  /** Font weight is undefined. */
-  public static final int FONT_WEIGHT_UNDEFINED = 0;
+    /** Font weight is undefined. */
+    public static final int FONT_WEIGHT_UNDEFINED = 0;
 
-  /** Normal font weight. */
-  public static final int FONT_WEIGHT_NORMAL = 400;
+    /** Normal font weight. */
+    public static final int FONT_WEIGHT_NORMAL = 400;
 
-  /** Medium font weight. */
-  @ProtoLayoutExperimental public static final int FONT_WEIGHT_MEDIUM = 500;
+    /** Medium font weight. */
+    @ProtoLayoutExperimental public static final int FONT_WEIGHT_MEDIUM = 500;
 
-  /** Bold font weight. */
-  public static final int FONT_WEIGHT_BOLD = 700;
-
-  /**
-   * The variant of a font. Some renderers may use different fonts for title and body text, which
-   * can be selected using this field.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({FONT_VARIANT_UNDEFINED, FONT_VARIANT_TITLE, FONT_VARIANT_BODY})
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface FontVariant {}
-
-  /** Font variant is undefined. */
-  public static final int FONT_VARIANT_UNDEFINED = 0;
-
-  /** Font variant suited for title text. */
-  public static final int FONT_VARIANT_TITLE = 1;
-
-  /** Font variant suited for body text. */
-  public static final int FONT_VARIANT_BODY = 2;
-
-  /**
-   * The alignment of a {@link SpanImage} within the line height of the surrounding {@link
-   * Spannable}.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({
-    SPAN_VERTICAL_ALIGN_UNDEFINED,
-    SPAN_VERTICAL_ALIGN_BOTTOM,
-    SPAN_VERTICAL_ALIGN_TEXT_BASELINE
-  })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface SpanVerticalAlignment {}
-
-  /** Alignment is undefined. */
-  public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0;
-
-  /**
-   * Align to the bottom of the line (descent of the largest text in this line). If there is no text
-   * in the line containing this image, this will align to the bottom of the line, where the line
-   * height is defined as the height of the largest image in the line.
-   */
-  public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1;
-
-  /**
-   * Align to the baseline of the text. Note that if the line in the {@link Spannable} which
-   * contains this image does not contain any text, the effects of using this alignment are
-   * undefined.
-   */
-  public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2;
-
-  /**
-   * How text that will not fit inside the bounds of a {@link Text} element will be handled.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({TEXT_OVERFLOW_UNDEFINED, TEXT_OVERFLOW_TRUNCATE, TEXT_OVERFLOW_ELLIPSIZE_END})
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface TextOverflow {}
-
-  /** Overflow behavior is undefined. */
-  public static final int TEXT_OVERFLOW_UNDEFINED = 0;
-
-  /**
-   * Truncate the text to fit inside of the {@link Text} element's bounds. If text is truncated, it
-   * will be truncated on a word boundary.
-   */
-  public static final int TEXT_OVERFLOW_TRUNCATE = 1;
-
-  /**
-   * Truncate the text to fit in the {@link Text} element's bounds, but add an ellipsis (i.e. ...)
-   * to the end of the text if it has been truncated.
-   */
-  public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2;
-
-  /**
-   * How content which does not match the dimensions of its bounds (e.g. an image resource being
-   * drawn inside an {@link Image}) will be resized to fit its bounds.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({
-    CONTENT_SCALE_MODE_UNDEFINED,
-    CONTENT_SCALE_MODE_FIT,
-    CONTENT_SCALE_MODE_CROP,
-    CONTENT_SCALE_MODE_FILL_BOUNDS
-  })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface ContentScaleMode {}
-
-  /** Content scaling is undefined. */
-  public static final int CONTENT_SCALE_MODE_UNDEFINED = 0;
-
-  /**
-   * Content will be scaled to fit inside its bounds, proportionally. As an example, If a 10x5 image
-   * was going to be drawn inside a 50x50 {@link Image} element, the actual image resource would be
-   * drawn as a 50x25 image, centered within the 50x50 bounds.
-   */
-  public static final int CONTENT_SCALE_MODE_FIT = 1;
-
-  /**
-   * Content will be resized proportionally so it completely fills its bounds, and anything outside
-   * of the bounds will be cropped. As an example, if a 10x5 image was going to be drawn inside a
-   * 50x50 {@link Image} element, the image resource would be drawn as a 100x50 image, centered
-   * within its bounds (and with 25px cropped from both the left and right sides).
-   */
-  public static final int CONTENT_SCALE_MODE_CROP = 2;
-
-  /**
-   * Content will be resized to fill its bounds, without taking into account the aspect ratio. If a
-   * 10x5 image was going to be drawn inside a 50x50 {@link Image} element, the image would be drawn
-   * as a 50x50 image, stretched vertically.
-   */
-  public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3;
-
-  /** An extensible {@code FontWeight} property. */
-  public static final class FontWeightProp {
-    private final LayoutElementProto.FontWeightProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    FontWeightProp(
-        LayoutElementProto.FontWeightProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the value. Intended for testing purposes only. */
-    @FontWeight
-    public int getValue() {
-      return mImpl.getValue().getNumber();
-    }
+    /** Bold font weight. */
+    public static final int FONT_WEIGHT_BOLD = 700;
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * The variant of a font. Some renderers may use different fonts for title and body text, which
+     * can be selected using this field.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({FONT_VARIANT_UNDEFINED, FONT_VARIANT_TITLE, FONT_VARIANT_BODY})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface FontVariant {}
 
-    @NonNull
-    static FontWeightProp fromProto(@NonNull LayoutElementProto.FontWeightProp proto) {
-      return new FontWeightProp(proto, null);
-    }
+    /** Font variant is undefined. */
+    public static final int FONT_VARIANT_UNDEFINED = 0;
 
-    @NonNull
-    LayoutElementProto.FontWeightProp toProto() {
-      return mImpl;
-    }
+    /** Font variant suited for title text. */
+    public static final int FONT_VARIANT_TITLE = 1;
 
-    /** Builder for {@link FontWeightProp} */
-    public static final class Builder {
-      private final LayoutElementProto.FontWeightProp.Builder mImpl =
-          LayoutElementProto.FontWeightProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1793388920);
-
-      public Builder() {}
-
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@FontWeight int value) {
-        mImpl.setValue(LayoutElementProto.FontWeight.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public FontWeightProp build() {
-        return new FontWeightProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** An extensible {@code FontVariant} property. */
-  @ProtoLayoutExperimental
-  public static final class FontVariantProp {
-    private final LayoutElementProto.FontVariantProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    FontVariantProp(
-        LayoutElementProto.FontVariantProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the value. Intended for testing purposes only. */
-    @FontVariant
-    public int getValue() {
-      return mImpl.getValue().getNumber();
-    }
+    /** Font variant suited for body text. */
+    public static final int FONT_VARIANT_BODY = 2;
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * The alignment of a {@link SpanImage} within the line height of the surrounding {@link
+     * Spannable}.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+        SPAN_VERTICAL_ALIGN_UNDEFINED,
+        SPAN_VERTICAL_ALIGN_BOTTOM,
+        SPAN_VERTICAL_ALIGN_TEXT_BASELINE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SpanVerticalAlignment {}
 
-    @NonNull
-    static FontVariantProp fromProto(@NonNull LayoutElementProto.FontVariantProp proto) {
-      return new FontVariantProp(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.FontVariantProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link FontVariantProp} */
-    public static final class Builder {
-      private final LayoutElementProto.FontVariantProp.Builder mImpl =
-          LayoutElementProto.FontVariantProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-293831500);
-
-      public Builder() {}
-
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@FontVariant int value) {
-        mImpl.setValue(LayoutElementProto.FontVariant.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public FontVariantProp build() {
-        return new FontVariantProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** An extensible {@code SpanVerticalAlignment} property. */
-  public static final class SpanVerticalAlignmentProp {
-    private final LayoutElementProto.SpanVerticalAlignmentProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    SpanVerticalAlignmentProp(
-        LayoutElementProto.SpanVerticalAlignmentProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the value. Intended for testing purposes only. */
-    @SpanVerticalAlignment
-    public int getValue() {
-      return mImpl.getValue().getNumber();
-    }
+    /** Alignment is undefined. */
+    public static final int SPAN_VERTICAL_ALIGN_UNDEFINED = 0;
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * Align to the bottom of the line (descent of the largest text in this line). If there is no
+     * text in the line containing this image, this will align to the bottom of the line, where the
+     * line height is defined as the height of the largest image in the line.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static SpanVerticalAlignmentProp fromProto(
-        @NonNull LayoutElementProto.SpanVerticalAlignmentProp proto) {
-      return new SpanVerticalAlignmentProp(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.SpanVerticalAlignmentProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link SpanVerticalAlignmentProp} */
-    public static final class Builder {
-      private final LayoutElementProto.SpanVerticalAlignmentProp.Builder mImpl =
-          LayoutElementProto.SpanVerticalAlignmentProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1008812329);
-
-      public Builder() {}
-
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@SpanVerticalAlignment int value) {
-        mImpl.setValue(LayoutElementProto.SpanVerticalAlignment.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public SpanVerticalAlignmentProp build() {
-        return new SpanVerticalAlignmentProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** The styling of a font (e.g. font size, and metrics). */
-  public static final class FontStyle {
-    private final LayoutElementProto.FontStyle mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    FontStyle(LayoutElementProto.FontStyle impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
+    public static final int SPAN_VERTICAL_ALIGN_BOTTOM = 1;
 
     /**
-     * Gets the size of the font, in scaled pixels (sp). If not specified, defaults to the size of
-     * the system's "body" font. Intended for testing purposes only.
+     * Align to the baseline of the text. Note that if the line in the {@link Spannable} which
+     * contains this image does not contain any text, the effects of using this alignment are
+     * undefined.
      */
-    @Nullable
-    public SpProp getSize() {
-      if (mImpl.hasSize()) {
-        return SpProp.fromProto(mImpl.getSize());
-      } else {
-        return null;
-      }
-    }
+    public static final int SPAN_VERTICAL_ALIGN_TEXT_BASELINE = 2;
+
+    /** How text that will not fit inside the bounds of a {@link Text} element will be handled. */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({TEXT_OVERFLOW_UNDEFINED, TEXT_OVERFLOW_TRUNCATE, TEXT_OVERFLOW_ELLIPSIZE_END})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TextOverflow {}
+
+    /** Overflow behavior is undefined. */
+    public static final int TEXT_OVERFLOW_UNDEFINED = 0;
 
     /**
-     * Gets whether the text should be rendered in a italic typeface. If not specified, defaults to
-     * "false". Intended for testing purposes only.
+     * Truncate the text to fit inside of the {@link Text} element's bounds. If text is truncated,
+     * it will be truncated on a word boundary.
      */
-    @Nullable
-    public BoolProp getItalic() {
-      if (mImpl.hasItalic()) {
-        return BoolProp.fromProto(mImpl.getItalic());
-      } else {
-        return null;
-      }
-    }
+    public static final int TEXT_OVERFLOW_TRUNCATE = 1;
 
     /**
-     * Gets whether the text should be rendered with an underline. If not specified, defaults to
-     * "false". Intended for testing purposes only.
+     * Truncate the text to fit in the {@link Text} element's bounds, but add an ellipsis (i.e. ...)
+     * to the end of the text if it has been truncated.
      */
-    @Nullable
-    public BoolProp getUnderline() {
-      if (mImpl.hasUnderline()) {
-        return BoolProp.fromProto(mImpl.getUnderline());
-      } else {
-        return null;
-      }
-    }
+    public static final int TEXT_OVERFLOW_ELLIPSIZE_END = 2;
 
     /**
-     * Gets the text color. If not defined, defaults to white. Intended for testing purposes only.
+     * How content which does not match the dimensions of its bounds (e.g. an image resource being
+     * drawn inside an {@link Image}) will be resized to fit its bounds.
      */
-    @Nullable
-    public ColorProp getColor() {
-      if (mImpl.hasColor()) {
-        return ColorProp.fromProto(mImpl.getColor());
-      } else {
-        return null;
-      }
-    }
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+        CONTENT_SCALE_MODE_UNDEFINED,
+        CONTENT_SCALE_MODE_FIT,
+        CONTENT_SCALE_MODE_CROP,
+        CONTENT_SCALE_MODE_FILL_BOUNDS
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ContentScaleMode {}
+
+    /** Content scaling is undefined. */
+    public static final int CONTENT_SCALE_MODE_UNDEFINED = 0;
 
     /**
-     * Gets the weight of the font. If the provided value is not supported on a platform, the
-     * nearest supported value will be used. If not defined, or when set to an invalid value,
-     * defaults to "normal". Intended for testing purposes only.
+     * Content will be scaled to fit inside its bounds, proportionally. As an example, If a 10x5
+     * image was going to be drawn inside a 50x50 {@link Image} element, the actual image resource
+     * would be drawn as a 50x25 image, centered within the 50x50 bounds.
      */
-    @Nullable
-    public FontWeightProp getWeight() {
-      if (mImpl.hasWeight()) {
-        return FontWeightProp.fromProto(mImpl.getWeight());
-      } else {
-        return null;
-      }
-    }
+    public static final int CONTENT_SCALE_MODE_FIT = 1;
 
     /**
-     * Gets the text letter-spacing. Positive numbers increase the space between letters while
-     * negative numbers tighten the space. If not specified, defaults to 0. Intended for testing
-     * purposes only.
+     * Content will be resized proportionally so it completely fills its bounds, and anything
+     * outside of the bounds will be cropped. As an example, if a 10x5 image was going to be drawn
+     * inside a 50x50 {@link Image} element, the image resource would be drawn as a 100x50 image,
+     * centered within its bounds (and with 25px cropped from both the left and right sides).
      */
-    @Nullable
-    public EmProp getLetterSpacing() {
-      if (mImpl.hasLetterSpacing()) {
-        return EmProp.fromProto(mImpl.getLetterSpacing());
-      } else {
-        return null;
-      }
-    }
+    public static final int CONTENT_SCALE_MODE_CROP = 2;
 
     /**
-     * Gets the variant of a font. Some renderers may use different fonts for title and body
-     * text, which can be selected using this field. If not specified, defaults to "body".
-     * Intended for testing purposes only.
+     * Content will be resized to fill its bounds, without taking into account the aspect ratio. If
+     * a 10x5 image was going to be drawn inside a 50x50 {@link Image} element, the image would be
+     * drawn as a 50x50 image, stretched vertically.
      */
+    public static final int CONTENT_SCALE_MODE_FILL_BOUNDS = 3;
+
+    /** An extensible {@code FontWeight} property. */
+    public static final class FontWeightProp {
+        private final LayoutElementProto.FontWeightProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        FontWeightProp(LayoutElementProto.FontWeightProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @FontWeight
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static FontWeightProp fromProto(@NonNull LayoutElementProto.FontWeightProp proto) {
+            return new FontWeightProp(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.FontWeightProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link FontWeightProp} */
+        public static final class Builder {
+            private final LayoutElementProto.FontWeightProp.Builder mImpl =
+                    LayoutElementProto.FontWeightProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1793388920);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@FontWeight int value) {
+                mImpl.setValue(LayoutElementProto.FontWeight.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public FontWeightProp build() {
+                return new FontWeightProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** An extensible {@code FontVariant} property. */
     @ProtoLayoutExperimental
-    @Nullable
-    public FontVariantProp getVariant() {
-      if (mImpl.hasVariant()) {
-        return FontVariantProp.fromProto(mImpl.getVariant());
-      } else {
-        return null;
-      }
-    }
+    public static final class FontVariantProp {
+        private final LayoutElementProto.FontVariantProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
 
-    /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static FontStyle fromProto(@NonNull LayoutElementProto.FontStyle proto) {
-      return new FontStyle(proto, null);
-    }
-
-    /**
-     * Returns the internal proto instance.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.FontStyle toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link FontStyle} */
-    public static final class Builder {
-      private final LayoutElementProto.FontStyle.Builder mImpl =
-          LayoutElementProto.FontStyle.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(181264306);
-
-      public Builder() {}
-
-      /**
-       * Sets the size of the font, in scaled pixels (sp). If not specified, defaults to the size of
-       * the system's "body" font.
-       */
-      @NonNull
-      public Builder setSize(@NonNull SpProp size) {
-        mImpl.setSize(size.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(size.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets whether the text should be rendered in a italic typeface. If not specified, defaults
-       * to "false".
-       */
-      @NonNull
-      public Builder setItalic(@NonNull BoolProp italic) {
-        mImpl.setItalic(italic.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(italic.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets whether the text should be rendered in a italic typeface. If not specified,
-       * defaults to "false".
-       */
-      @SuppressLint("MissingGetterMatchingBuilder")
-      @NonNull
-      public Builder setItalic(boolean italic) {
-        mImpl.setItalic(TypesProto.BoolProp.newBuilder().setValue(italic));
-        return this;
-      }
-      /**
-       * Sets whether the text should be rendered with an underline. If not specified, defaults to
-       * "false".
-       */
-      @NonNull
-      public Builder setUnderline(@NonNull BoolProp underline) {
-        mImpl.setUnderline(underline.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(underline.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets whether the text should be rendered with an underline. If not specified,
-       * defaults to "false".
-       */
-      @SuppressLint("MissingGetterMatchingBuilder")
-      @NonNull
-      public Builder setUnderline(boolean underline) {
-        mImpl.setUnderline(TypesProto.BoolProp.newBuilder().setValue(underline));
-        return this;
-      }
-
-      /**
-       * Sets the text color. If not defined, defaults to white.
-       */
-      @NonNull
-      public Builder setColor(@NonNull ColorProp color) {
-        mImpl.setColor(color.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(color.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the weight of the font. If the provided value is not supported on a platform, the
-       * nearest supported value will be used. If not defined, or when set to an invalid value,
-       * defaults to "normal".
-       */
-      @NonNull
-      public Builder setWeight(@NonNull FontWeightProp weight) {
-        mImpl.setWeight(weight.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(weight.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the weight of the font. If the provided value is not supported on a platform,
-       * the nearest supported value will be used. If not defined, or when set to an invalid
-       * value, defaults to "normal".
-       */
-      @NonNull
-      public Builder setWeight(@FontWeight int weight) {
-        mImpl.setWeight(
-                LayoutElementProto.FontWeightProp.newBuilder()
-                        .setValue(LayoutElementProto.FontWeight.forNumber(weight)));
-        return this;
-      }
-
-      /**
-       * Sets the text letter-spacing. Positive numbers increase the space between letters while
-       * negative numbers tighten the space. If not specified, defaults to 0.
-       */
-      @NonNull
-      public Builder setLetterSpacing(@NonNull EmProp letterSpacing) {
-        mImpl.setLetterSpacing(letterSpacing.toProto());
-        mFingerprint.recordPropertyUpdate(
-            6, checkNotNull(letterSpacing.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the variant of a font. Some renderers may use different fonts for title and body
-       * text, which can be selected using this field. If not specified, defaults to "body".
-       */
-      @ProtoLayoutExperimental
-      @NonNull
-      public Builder setVariant(@NonNull FontVariantProp variant) {
-        mImpl.setVariant(variant.toProto());
-        return this;
-      }
-      /**
-       * Sets the variant of a font. Some renderers may use different fonts for title and body
-       * text, which can be selected using this field. If not specified, defaults to "body".
-       */
-      @ProtoLayoutExperimental
-      @NonNull
-      public Builder setVariant(@FontVariant int variant) {
-        mImpl.setVariant(
-                LayoutElementProto.FontVariantProp.newBuilder()
-                        .setValue(LayoutElementProto.FontVariant.forNumber(variant)));
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public FontStyle build() {
-        return new FontStyle(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** An extensible {@code TextOverflow} property. */
-  public static final class TextOverflowProp {
-    private final LayoutElementProto.TextOverflowProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    TextOverflowProp(
-        LayoutElementProto.TextOverflowProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the value. Intended for testing purposes only. */
-    @TextOverflow
-    public int getValue() {
-      return mImpl.getValue().getNumber();
-    }
-
-    /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static TextOverflowProp fromProto(@NonNull LayoutElementProto.TextOverflowProp proto) {
-      return new TextOverflowProp(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.TextOverflowProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link TextOverflowProp} */
-    public static final class Builder {
-      private final LayoutElementProto.TextOverflowProp.Builder mImpl =
-          LayoutElementProto.TextOverflowProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1183432233);
-
-      public Builder() {}
-
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@TextOverflow int value) {
-        mImpl.setValue(LayoutElementProto.TextOverflow.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public TextOverflowProp build() {
-        return new TextOverflowProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A text string. */
-  public static final class Text implements LayoutElement {
-    private final LayoutElementProto.Text mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Text(LayoutElementProto.Text impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the text to render. Intended for testing purposes only. */
-    @Nullable
-    public StringProp getText() {
-      if (mImpl.hasText()) {
-        return StringProp.fromProto(mImpl.getText());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the style of font to use (size, bold etc). If not specified, defaults to the platform's
-     * default body font. Intended for testing purposes only.
-     */
-    @Nullable
-    public FontStyle getFontStyle() {
-      if (mImpl.hasFontStyle()) {
-        return FontStyle.fromProto(mImpl.getFontStyle());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the maximum number of lines that can be represented by the {@link Text} element. If not
-     * defined, the {@link Text} element will be treated as a single-line element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Int32Prop getMaxLines() {
-      if (mImpl.hasMaxLines()) {
-        return Int32Prop.fromProto(mImpl.getMaxLines());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets alignment of the text within its bounds. Note that a {@link Text} element will size
-     * itself to wrap its contents, so this option is meaningless for single-line text (for that,
-     * use alignment of the outer container). For multi-line text, however, this will set the
-     * alignment of lines relative to the {@link Text} element bounds. If not defined, defaults to
-     * TEXT_ALIGN_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public TextAlignmentProp getMultilineAlignment() {
-      if (mImpl.hasMultilineAlignment()) {
-        return TextAlignmentProp.fromProto(mImpl.getMultilineAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets how to handle text which overflows the bound of the {@link Text} element. A {@link Text}
-     * element will grow as large as possible inside its parent container (while still respecting
-     * max_lines); if it cannot grow large enough to render all of its text, the text which cannot
-     * fit inside its container will be truncated. If not defined, defaults to
-     * TEXT_OVERFLOW_TRUNCATE. Intended for testing purposes only.
-     */
-    @Nullable
-    public TextOverflowProp getOverflow() {
-      if (mImpl.hasOverflow()) {
-        return TextOverflowProp.fromProto(mImpl.getOverflow());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the explicit height between lines of text. This is equivalent to the vertical distance
-     * between subsequent baselines. If not specified, defaults the font's recommended interline
-     * spacing. Intended for testing purposes only.
-     */
-    @Nullable
-    public SpProp getLineHeight() {
-      if (mImpl.hasLineHeight()) {
-        return SpProp.fromProto(mImpl.getLineHeight());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Text fromProto(@NonNull LayoutElementProto.Text proto) {
-      return new Text(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Text toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setText(mImpl).build();
-    }
-
-    /** Builder for {@link Text}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Text.Builder mImpl = LayoutElementProto.Text.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1976530157);
-
-      public Builder() {}
-
-      /**
-       * Sets the text to render.
-       */
-      @NonNull
-      public Builder setText(@NonNull StringProp text) {
-        mImpl.setText(text.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /** Sets the text to render. */
-      @NonNull
-      public Builder setText(@NonNull String text) {
-        mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
-        return this;
-      }
-
-      /**
-       * Sets the style of font to use (size, bold etc). If not specified, defaults to the
-       * platform's default body font.
-       */
-      @NonNull
-      public Builder setFontStyle(@NonNull FontStyle fontStyle) {
-        mImpl.setFontStyle(fontStyle.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the maximum number of lines that can be represented by the {@link Text} element. If
-       * not defined, the {@link Text} element will be treated as a single-line element.
-       */
-      @NonNull
-      public Builder setMaxLines(@NonNull Int32Prop maxLines) {
-        mImpl.setMaxLines(maxLines.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(maxLines.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the maximum number of lines that can be represented by the {@link Text} element.
-       * If not defined, the {@link Text} element will be treated as a single-line element.
-       */
-      @NonNull
-      public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
-        mImpl.setMaxLines(TypesProto.Int32Prop.newBuilder().setValue(maxLines));
-        return this;
-      }
-
-      /**
-       * Sets alignment of the text within its bounds. Note that a {@link Text} element will size
-       * itself to wrap its contents, so this option is meaningless for single-line text (for that,
-       * use alignment of the outer container). For multi-line text, however, this will set the
-       * alignment of lines relative to the {@link Text} element bounds. If not defined, defaults to
-       * TEXT_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setMultilineAlignment(@NonNull TextAlignmentProp multilineAlignment) {
-        mImpl.setMultilineAlignment(multilineAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(multilineAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets alignment of the text within its bounds. Note that a {@link Text} element will
-       * size itself to wrap its contents, so this option is meaningless for single-line text
-       * (for that, use alignment of the outer container). For multi-line text, however, this
-       * will set the alignment of lines relative to the {@link Text} element bounds. If not
-       * defined, defaults to TEXT_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setMultilineAlignment(@TextAlignment int multilineAlignment) {
-        mImpl.setMultilineAlignment(
-                AlignmentProto.TextAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.TextAlignment.forNumber(
-                                        multilineAlignment)));
-        return this;
-      }
-
-      /**
-       * Sets how to handle text which overflows the bound of the {@link Text} element. A {@link
-       * Text} element will grow as large as possible inside its parent container (while still
-       * respecting max_lines); if it cannot grow large enough to render all of its text, the text
-       * which cannot fit inside its container will be truncated. If not defined, defaults to
-       * TEXT_OVERFLOW_TRUNCATE.
-       */
-      @NonNull
-      public Builder setOverflow(@NonNull TextOverflowProp overflow) {
-        mImpl.setOverflow(overflow.toProto());
-        mFingerprint.recordPropertyUpdate(
-            6, checkNotNull(overflow.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets how to handle text which overflows the bound of the {@link Text} element. A
-       * {@link Text} element will grow as large as possible inside its parent container
-       * (while still respecting max_lines); if it cannot grow large enough to render all of
-       * its text, the text which cannot fit inside its container will be truncated. If not
-       * defined, defaults to TEXT_OVERFLOW_TRUNCATE.
-       */
-      @NonNull
-      public Builder setOverflow(@TextOverflow int overflow) {
-        mImpl.setOverflow(
-                LayoutElementProto.TextOverflowProp.newBuilder()
-                        .setValue(LayoutElementProto.TextOverflow.forNumber(overflow)));
-        return this;
-      }
-
-      /**
-       * Sets the explicit height between lines of text. This is equivalent to the vertical distance
-       * between subsequent baselines. If not specified, defaults the font's recommended interline
-       * spacing.
-       */
-      @NonNull
-      public Builder setLineHeight(@NonNull SpProp lineHeight) {
-        mImpl.setLineHeight(lineHeight.toProto());
-        mFingerprint.recordPropertyUpdate(
-            7, checkNotNull(lineHeight.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public Text build() {
-        return new Text(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** An extensible {@code ContentScaleMode} property. */
-  public static final class ContentScaleModeProp {
-    private final LayoutElementProto.ContentScaleModeProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ContentScaleModeProp(
-        LayoutElementProto.ContentScaleModeProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the value. Intended for testing purposes only. */
-    @ContentScaleMode
-    public int getValue() {
-      return mImpl.getValue().getNumber();
-    }
-
-    /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ContentScaleModeProp fromProto(@NonNull LayoutElementProto.ContentScaleModeProp proto) {
-      return new ContentScaleModeProp(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ContentScaleModeProp toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link ContentScaleModeProp} */
-    public static final class Builder {
-      private final LayoutElementProto.ContentScaleModeProp.Builder mImpl =
-          LayoutElementProto.ContentScaleModeProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-893830536);
-
-      public Builder() {}
-
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@ContentScaleMode int value) {
-        mImpl.setValue(LayoutElementProto.ContentScaleMode.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public ContentScaleModeProp build() {
-        return new ContentScaleModeProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** Filtering parameters used for images. This can be used to apply a color tint to images. */
-  public static final class ColorFilter {
-    private final LayoutElementProto.ColorFilter mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ColorFilter(LayoutElementProto.ColorFilter impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the tint color to use. If specified, the image will be tinted, using SRC_IN blending
-     * (that is, all color information will be stripped from the target image, and only the alpha
-     * channel will be blended with the requested color).
-     *
-     * <p>Note that only Android image resources can be tinted; Inline images will not be tinted,
-     * and this property will have no effect. Intended for testing purposes only.
-     */
-    @Nullable
-    public ColorProp getTint() {
-      if (mImpl.hasTint()) {
-        return ColorProp.fromProto(mImpl.getTint());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ColorFilter fromProto(@NonNull LayoutElementProto.ColorFilter proto) {
-      return new ColorFilter(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ColorFilter toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link ColorFilter} */
-    public static final class Builder {
-      private final LayoutElementProto.ColorFilter.Builder mImpl =
-          LayoutElementProto.ColorFilter.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(181311326);
-
-      public Builder() {}
-
-      /**
-       * Sets the tint color to use. If specified, the image will be tinted, using SRC_IN blending
-       * (that is, all color information will be stripped from the target image, and only the alpha
-       * channel will be blended with the requested color).
-       *
-       * <p>Note that only Android image resources can be tinted; Inline images will not be tinted,
-       * and this property will have no effect.
-       */
-      @NonNull
-      public Builder setTint(@NonNull ColorProp tint) {
-        mImpl.setTint(tint.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(tint.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public ColorFilter build() {
-        return new ColorFilter(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * An image.
-   *
-   * <p>Images used in this element must exist in the resource bundle that corresponds to this
-   * layout. Images must have their dimension specified, and will be rendered at this width and
-   * height, regardless of their native dimension.
-   */
-  public static final class Image implements LayoutElement {
-    private final LayoutElementProto.Image mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Image(LayoutElementProto.Image impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the resource_id of the image to render. This must exist in the supplied resource bundle.
-     * Intended for testing purposes only.
-     */
-    @Nullable
-    public StringProp getResourceId() {
-      if (mImpl.hasResourceId()) {
-        return StringProp.fromProto(mImpl.getResourceId());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the width of this image. If not defined, the image will not be rendered. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public ImageDimension getWidth() {
-      if (mImpl.hasWidth()) {
-        return DimensionBuilders.imageDimensionFromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the height of this image. If not defined, the image will not be rendered. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public ImageDimension getHeight() {
-      if (mImpl.hasHeight()) {
-        return DimensionBuilders.imageDimensionFromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets how to scale the image resource inside the bounds specified by width/height if its size
-     * does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT. Intended for testing
-     * purposes only.
-     */
-    @Nullable
-    public ContentScaleModeProp getContentScaleMode() {
-      if (mImpl.hasContentScaleMode()) {
-        return ContentScaleModeProp.fromProto(mImpl.getContentScaleMode());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets filtering parameters for this image. If not specified, defaults to no filtering.
-     * Intended for testing purposes only.
-     */
-    @Nullable
-    public ColorFilter getColorFilter() {
-      if (mImpl.hasColorFilter()) {
-        return ColorFilter.fromProto(mImpl.getColorFilter());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Image fromProto(@NonNull LayoutElementProto.Image proto) {
-      return new Image(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Image toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setImage(mImpl).build();
-    }
-
-    /** Builder for {@link Image}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Image.Builder mImpl = LayoutElementProto.Image.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-543078544);
-
-      public Builder() {}
-
-      /**
-       * Sets the resource_id of the image to render. This must exist in the supplied resource
-       * bundle.
-       */
-      @NonNull
-      public Builder setResourceId(@NonNull StringProp resourceId) {
-        mImpl.setResourceId(resourceId.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(resourceId.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the resource_id of the image to render. This must exist in the supplied resource
-       * bundle.
-       */
-      @NonNull
-      public Builder setResourceId(@NonNull String resourceId) {
-        mImpl.setResourceId(TypesProto.StringProp.newBuilder().setValue(resourceId));
-        return this;
-      }
-
-      /**
-       * Sets the width of this image. If not defined, the image will not be rendered.
-       */
-      @NonNull
-      public Builder setWidth(@NonNull ImageDimension width) {
-        mImpl.setWidth(width.toImageDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the height of this image. If not defined, the image will not be rendered.
-       */
-      @NonNull
-      public Builder setHeight(@NonNull ImageDimension height) {
-        mImpl.setHeight(height.toImageDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets how to scale the image resource inside the bounds specified by width/height if its
-       * size does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT.
-       */
-      @NonNull
-      public Builder setContentScaleMode(@NonNull ContentScaleModeProp contentScaleMode) {
-        mImpl.setContentScaleMode(contentScaleMode.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(contentScaleMode.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets how to scale the image resource inside the bounds specified by width/height if
-       * its size does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT.
-       */
-      @NonNull
-      public Builder setContentScaleMode(@ContentScaleMode int contentScaleMode) {
-        mImpl.setContentScaleMode(
-                LayoutElementProto.ContentScaleModeProp.newBuilder()
-                        .setValue(
-                                LayoutElementProto.ContentScaleMode.forNumber(
-                                        contentScaleMode)));
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets filtering parameters for this image. If not specified, defaults to no filtering. */
-      @NonNull
-      public Builder setColorFilter(@NonNull ColorFilter colorFilter) {
-        mImpl.setColorFilter(colorFilter.toProto());
-        mFingerprint.recordPropertyUpdate(
-            6, checkNotNull(colorFilter.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public Image build() {
-        return new Image(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A simple spacer, typically used to provide padding between adjacent elements. */
-  public static final class Spacer implements LayoutElement {
-    private final LayoutElementProto.Spacer mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Spacer(LayoutElementProto.Spacer impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the width of this {@link Spacer}. When this is added as the direct child of an {@link
-     * Arc}, this must be specified as an angular dimension, otherwise a linear dimension must be
-     * used. If not defined, defaults to 0. Intended for testing purposes only.
-     */
-    @Nullable
-    public SpacerDimension getWidth() {
-      if (mImpl.hasWidth()) {
-        return DimensionBuilders.spacerDimensionFromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the height of this spacer. If not defined, defaults to 0. Intended for testing purposes
-     * only.
-     */
-    @Nullable
-    public SpacerDimension getHeight() {
-      if (mImpl.hasHeight()) {
-        return DimensionBuilders.spacerDimensionFromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Spacer fromProto(@NonNull LayoutElementProto.Spacer proto) {
-      return new Spacer(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Spacer toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setSpacer(mImpl).build();
-    }
-
-    /** Builder for {@link Spacer}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Spacer.Builder mImpl =
-          LayoutElementProto.Spacer.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1748084575);
-
-      public Builder() {}
-
-      /**
-       * Sets the width of this {@link Spacer}. When this is added as the direct child of an {@link
-       * Arc}, this must be specified as an angular dimension, otherwise a linear dimension must be
-       * used. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setWidth(@NonNull SpacerDimension width) {
-        mImpl.setWidth(width.toSpacerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the height of this spacer. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setHeight(@NonNull SpacerDimension height) {
-        mImpl.setHeight(height.toSpacerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public Spacer build() {
-        return new Spacer(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A container which stacks all of its children on top of one another. This also allows to add a
-   * background color, or to have a border around them with some padding.
-   */
-  public static final class Box implements LayoutElement {
-    private final LayoutElementProto.Box mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Box(LayoutElementProto.Box impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the child element(s) to wrap. Intended for testing purposes only. */
-    @NonNull
-    public List<LayoutElement> getContents() {
-      List<LayoutElement> list = new ArrayList<>();
-      for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
-        list.add(LayoutElementBuilders.layoutElementFromProto(item));
-      }
-      return Collections.unmodifiableList(list);
-    }
-
-    /**
-     * Gets the height of this {@link Box}. If not defined, this will size itself to fit all of its
-     * children (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getHeight() {
-      if (mImpl.hasHeight()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the width of this {@link Box}. If not defined, this will size itself to fit all of its
-     * children (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getWidth() {
-      if (mImpl.hasWidth()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the horizontal alignment of the element inside this {@link Box}. If not defined,
-     * defaults to HORIZONTAL_ALIGN_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public HorizontalAlignmentProp getHorizontalAlignment() {
-      if (mImpl.hasHorizontalAlignment()) {
-        return HorizontalAlignmentProp.fromProto(mImpl.getHorizontalAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the vertical alignment of the element inside this {@link Box}. If not defined, defaults
-     * to VERTICAL_ALIGN_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public VerticalAlignmentProp getVerticalAlignment() {
-      if (mImpl.hasVerticalAlignment()) {
-        return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Box fromProto(@NonNull LayoutElementProto.Box proto) {
-      return new Box(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Box toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setBox(mImpl).build();
-    }
-
-    /** Builder for {@link Box}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Box.Builder mImpl = LayoutElementProto.Box.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1881256071);
-
-      public Builder() {}
-
-      /** Adds one item to the child element(s) to wrap. */
-      @NonNull
-      public Builder addContent(@NonNull LayoutElement content) {
-        mImpl.addContents(content.toLayoutElementProto());
-        mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
-        return this;
-      }
-
-      /**
-       * Sets the height of this {@link Box}. If not defined, this will size itself to fit all of
-       * its children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setHeight(@NonNull ContainerDimension height) {
-        mImpl.setHeight(height.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the width of this {@link Box}. If not defined, this will size itself to fit all of its
-       * children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setWidth(@NonNull ContainerDimension width) {
-        mImpl.setWidth(width.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the horizontal alignment of the element inside this {@link Box}. If not defined,
-       * defaults to HORIZONTAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setHorizontalAlignment(@NonNull HorizontalAlignmentProp horizontalAlignment) {
-        mImpl.setHorizontalAlignment(horizontalAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(horizontalAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the horizontal alignment of the element inside this {@link Box}. If not defined,
-       * defaults to HORIZONTAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
-        mImpl.setHorizontalAlignment(
-                AlignmentProto.HorizontalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.HorizontalAlignment.forNumber(
-                                        horizontalAlignment)));
-        return this;
-      }
-
-      /**
-       * Sets the vertical alignment of the element inside this {@link Box}. If not defined,
-       * defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlignment(@NonNull VerticalAlignmentProp verticalAlignment) {
-        mImpl.setVerticalAlignment(verticalAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(verticalAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the vertical alignment of the element inside this {@link Box}. If not defined,
-       * defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlignment(@VerticalAlignment int verticalAlignment) {
-        mImpl.setVerticalAlignment(
-                AlignmentProto.VerticalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.VerticalAlignment.forNumber(
-                                        verticalAlignment)));
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            6, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public Box build() {
-        return new Box(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A portion of text which can be added to a {@link Span}. Two different {@link SpanText} elements
-   * on the same line will be aligned to the same baseline, regardless of the size of each {@link
-   * SpanText}.
-   */
-  public static final class SpanText implements Span {
-    private final LayoutElementProto.SpanText mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    SpanText(LayoutElementProto.SpanText impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the text to render. Intended for testing purposes only. */
-    @Nullable
-    public StringProp getText() {
-      if (mImpl.hasText()) {
-        return StringProp.fromProto(mImpl.getText());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the style of font to use (size, bold etc). If not specified, defaults to the platform's
-     * default body font. Intended for testing purposes only.
-     */
-    @Nullable
-    public FontStyle getFontStyle() {
-      if (mImpl.hasFontStyle()) {
-        return FontStyle.fromProto(mImpl.getFontStyle());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public SpanModifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return SpanModifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static SpanText fromProto(@NonNull LayoutElementProto.SpanText proto) {
-      return new SpanText(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.SpanText toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.Span toSpanProto() {
-      return LayoutElementProto.Span.newBuilder().setText(mImpl).build();
-    }
-
-    /** Builder for {@link SpanText}. */
-    public static final class Builder implements Span.Builder {
-      private final LayoutElementProto.SpanText.Builder mImpl =
-          LayoutElementProto.SpanText.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-221774557);
-
-      public Builder() {}
-
-      /**
-       * Sets the text to render.
-       */
-      @NonNull
-      public Builder setText(@NonNull StringProp text) {
-        mImpl.setText(text.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /** Sets the text to render. */
-      @NonNull
-      public Builder setText(@NonNull String text) {
-        mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
-        return this;
-      }
-
-      /**
-       * Sets the style of font to use (size, bold etc). If not specified, defaults to the
-       * platform's default body font.
-       */
-      @NonNull
-      public Builder setFontStyle(@NonNull FontStyle fontStyle) {
-        mImpl.setFontStyle(fontStyle.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull SpanModifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public SpanText build() {
-        return new SpanText(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** An image which can be added to a {@link Span}. */
-  public static final class SpanImage implements Span {
-    private final LayoutElementProto.SpanImage mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    SpanImage(LayoutElementProto.SpanImage impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the resource_id of the image to render. This must exist in the supplied resource bundle.
-     * Intended for testing purposes only.
-     */
-    @Nullable
-    public StringProp getResourceId() {
-      if (mImpl.hasResourceId()) {
-        return StringProp.fromProto(mImpl.getResourceId());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the width of this image. If not defined, the image will not be rendered. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public DpProp getWidth() {
-      if (mImpl.hasWidth()) {
-        return DpProp.fromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the height of this image. If not defined, the image will not be rendered. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public DpProp getHeight() {
-      if (mImpl.hasHeight()) {
-        return DpProp.fromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public SpanModifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return SpanModifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets alignment of this image within the line height of the surrounding {@link Spannable}. If
-     * undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM. Intended for testing purposes only.
-     */
-    @Nullable
-    public SpanVerticalAlignmentProp getAlignment() {
-      if (mImpl.hasAlignment()) {
-        return SpanVerticalAlignmentProp.fromProto(mImpl.getAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static SpanImage fromProto(@NonNull LayoutElementProto.SpanImage proto) {
-      return new SpanImage(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.SpanImage toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.Span toSpanProto() {
-      return LayoutElementProto.Span.newBuilder().setImage(mImpl).build();
-    }
-
-    /** Builder for {@link SpanImage}. */
-    public static final class Builder implements Span.Builder {
-      private final LayoutElementProto.SpanImage.Builder mImpl =
-          LayoutElementProto.SpanImage.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(502289772);
-
-      public Builder() {}
-
-      /**
-       * Sets the resource_id of the image to render. This must exist in the supplied resource
-       * bundle.
-       */
-      @NonNull
-      public Builder setResourceId(@NonNull StringProp resourceId) {
-        mImpl.setResourceId(resourceId.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(resourceId.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the resource_id of the image to render. This must exist in the supplied resource
-       * bundle.
-       */
-      @NonNull
-      public Builder setResourceId(@NonNull String resourceId) {
-        mImpl.setResourceId(TypesProto.StringProp.newBuilder().setValue(resourceId));
-        return this;
-      }
-
-      /**
-       * Sets the width of this image. If not defined, the image will not be rendered.
-       */
-      @NonNull
-      public Builder setWidth(@NonNull DpProp width) {
-        mImpl.setWidth(width.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the height of this image. If not defined, the image will not be rendered.
-       */
-      @NonNull
-      public Builder setHeight(@NonNull DpProp height) {
-        mImpl.setHeight(height.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull SpanModifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets alignment of this image within the line height of the surrounding {@link Spannable}.
-       * If undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM.
-       */
-      @NonNull
-      public Builder setAlignment(@NonNull SpanVerticalAlignmentProp alignment) {
-        mImpl.setAlignment(alignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(alignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets alignment of this image within the line height of the surrounding {@link
-       * Spannable}. If undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM.
-       */
-      @NonNull
-      public Builder setAlignment(@SpanVerticalAlignment int alignment) {
-        mImpl.setAlignment(
-                LayoutElementProto.SpanVerticalAlignmentProp.newBuilder()
-                        .setValue(
-                                LayoutElementProto.SpanVerticalAlignment.forNumber(
-                                        alignment)));
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public SpanImage build() {
-        return new SpanImage(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * Interface defining a single {@link Span}. Each {@link Span} forms part of a larger {@link
-   * Spannable} widget. At the moment, the only widgets which can be added to {@link Spannable}
-   * containers are {@link SpanText} and {@link SpanImage} elements.
-   */
-  public interface Span {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    LayoutElementProto.Span toSpanProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link Span} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      Span build();
-    }
-  }
-
-  @NonNull
-  static Span spanFromProto(@NonNull LayoutElementProto.Span proto) {
-    if (proto.hasText()) {
-      return SpanText.fromProto(proto.getText());
-    }
-    if (proto.hasImage()) {
-      return SpanImage.fromProto(proto.getImage());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of Span");
-  }
-
-  /**
-   * A container of {@link Span} elements. Currently, this supports {@link SpanImage} and {@link
-   * SpanText} elements, where each individual {@link Span} can have different styling applied to it
-   * but the resulting text will flow naturally. This allows sections of a paragraph of text to have
-   * different styling applied to it, for example, making one or two words bold or italic.
-   */
-  public static final class Spannable implements LayoutElement {
-    private final LayoutElementProto.Spannable mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Spannable(LayoutElementProto.Spannable impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the {@link Span} elements that form this {@link Spannable}. Intended for testing
-     * purposes only.
-     */
-    @NonNull
-    public List<Span> getSpans() {
-      List<Span> list = new ArrayList<>();
-      for (LayoutElementProto.Span item : mImpl.getSpansList()) {
-        list.add(LayoutElementBuilders.spanFromProto(item));
-      }
-      return Collections.unmodifiableList(list);
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the maximum number of lines that can be represented by the {@link Spannable} element. If
-     * not defined, the {@link Spannable} element will be treated as a single-line element. Intended
-     * for testing purposes only.
-     */
-    @Nullable
-    public Int32Prop getMaxLines() {
-      if (mImpl.hasMaxLines()) {
-        return Int32Prop.fromProto(mImpl.getMaxLines());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets alignment of the {@link Spannable} content within its bounds. Note that a {@link
-     * Spannable} element will size itself to wrap its contents, so this option is meaningless for
-     * single-line content (for that, use alignment of the outer container). For multi-line content,
-     * however, this will set the alignment of lines relative to the {@link Spannable} element
-     * bounds. If not defined, defaults to TEXT_ALIGN_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public HorizontalAlignmentProp getMultilineAlignment() {
-      if (mImpl.hasMultilineAlignment()) {
-        return HorizontalAlignmentProp.fromProto(mImpl.getMultilineAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets how to handle content which overflows the bound of the {@link Spannable} element. A
-     * {@link Spannable} element will grow as large as possible inside its parent container (while
-     * still respecting max_lines); if it cannot grow large enough to render all of its content, the
-     * content which cannot fit inside its container will be truncated. If not defined, defaults to
-     * TEXT_OVERFLOW_TRUNCATE. Intended for testing purposes only.
-     */
-    @Nullable
-    public TextOverflowProp getOverflow() {
-      if (mImpl.hasOverflow()) {
-        return TextOverflowProp.fromProto(mImpl.getOverflow());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the explicit height between lines of text. This is equivalent to the vertical distance
-     * between subsequent baselines. If not specified, defaults the font's recommended interline
-     * spacing. Intended for testing purposes only.
-     */
-    @Nullable
-    public SpProp getLineHeight() {
-      if (mImpl.hasLineHeight()) {
-        return SpProp.fromProto(mImpl.getLineHeight());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Spannable fromProto(@NonNull LayoutElementProto.Spannable proto) {
-      return new Spannable(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Spannable toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setSpannable(mImpl).build();
-    }
-
-    /** Builder for {@link Spannable}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Spannable.Builder mImpl =
-          LayoutElementProto.Spannable.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1690284372);
-
-      public Builder() {}
-
-      /** Adds one item to the {@link Span} elements that form this {@link Spannable}. */
-      @NonNull
-      public Builder addSpan(@NonNull Span span) {
-        mImpl.addSpans(span.toSpanProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(span.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the maximum number of lines that can be represented by the {@link Spannable} element.
-       * If not defined, the {@link Spannable} element will be treated as a single-line element.
-       */
-      @NonNull
-      public Builder setMaxLines(@NonNull Int32Prop maxLines) {
-        mImpl.setMaxLines(maxLines.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(maxLines.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets the maximum number of lines that can be represented by the {@link Spannable}
-       * element. If not defined, the {@link Spannable} element will be treated as a
-       * single-line element.
-       */
-      @NonNull
-      public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
-        mImpl.setMaxLines(TypesProto.Int32Prop.newBuilder().setValue(maxLines));
-        return this;
-      }
-
-      /**
-       * Sets alignment of the {@link Spannable} content within its bounds. Note that a {@link
-       * Spannable} element will size itself to wrap its contents, so this option is meaningless for
-       * single-line content (for that, use alignment of the outer container). For multi-line
-       * content, however, this will set the alignment of lines relative to the {@link Spannable}
-       * element bounds. If not defined, defaults to TEXT_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setMultilineAlignment(@NonNull HorizontalAlignmentProp multilineAlignment) {
-        mImpl.setMultilineAlignment(multilineAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(multilineAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets alignment of the {@link Spannable} content within its bounds. Note that a {@link
-       * Spannable} element will size itself to wrap its contents, so this option is
-       * meaningless for single-line content (for that, use alignment of the outer container).
-       * For multi-line content, however, this will set the alignment of lines relative to the
-       * {@link Spannable} element bounds. If not defined, defaults to TEXT_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setMultilineAlignment(@HorizontalAlignment int multilineAlignment) {
-        mImpl.setMultilineAlignment(
-                AlignmentProto.HorizontalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.HorizontalAlignment.forNumber(
-                                        multilineAlignment)));
-        return this;
-      }
-
-      /**
-       * Sets how to handle content which overflows the bound of the {@link Spannable} element. A
-       * {@link Spannable} element will grow as large as possible inside its parent container (while
-       * still respecting max_lines); if it cannot grow large enough to render all of its content,
-       * the content which cannot fit inside its container will be truncated. If not defined,
-       * defaults to TEXT_OVERFLOW_TRUNCATE.
-       */
-      @NonNull
-      public Builder setOverflow(@NonNull TextOverflowProp overflow) {
-        mImpl.setOverflow(overflow.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(overflow.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets how to handle content which overflows the bound of the {@link Spannable}
-       * element. A {@link Spannable} element will grow as large as possible inside its parent
-       * container (while still respecting max_lines); if it cannot grow large enough to
-       * render all of its content, the content which cannot fit inside its container will be
-       * truncated. If not defined, defaults to TEXT_OVERFLOW_TRUNCATE.
-       */
-      @NonNull
-      public Builder setOverflow(@TextOverflow int overflow) {
-        mImpl.setOverflow(
-                LayoutElementProto.TextOverflowProp.newBuilder()
-                        .setValue(LayoutElementProto.TextOverflow.forNumber(overflow)));
-        return this;
-      }
-
-      /**
-       * Sets the explicit height between lines of text. This is equivalent to the vertical distance
-       * between subsequent baselines. If not specified, defaults the font's recommended interline
-       * spacing.
-       */
-      @NonNull
-      public Builder setLineHeight(@NonNull SpProp lineHeight) {
-        mImpl.setLineHeight(lineHeight.toProto());
-        mFingerprint.recordPropertyUpdate(
-            7, checkNotNull(lineHeight.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public Spannable build() {
-        return new Spannable(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A column of elements. Each child element will be laid out vertically, one after another (i.e.
-   * stacking down). This element will size itself to the smallest size required to hold all of its
-   * children (e.g. if it contains three elements sized 10x10, 20x20 and 30x30, the resulting column
-   * will be 30x60).
-   *
-   * <p>If specified, horizontal_alignment can be used to control the gravity inside the container,
-   * affecting the horizontal placement of children whose width are smaller than the resulting
-   * column width.
-   */
-  public static final class Column implements LayoutElement {
-    private final LayoutElementProto.Column mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Column(LayoutElementProto.Column impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the list of child elements to place inside this {@link Column}. Intended for testing
-     * purposes only.
-     */
-    @NonNull
-    public List<LayoutElement> getContents() {
-      List<LayoutElement> list = new ArrayList<>();
-      for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
-        list.add(LayoutElementBuilders.layoutElementFromProto(item));
-      }
-      return Collections.unmodifiableList(list);
-    }
-
-    /**
-     * Gets the horizontal alignment of elements inside this column, if they are narrower than the
-     * resulting width of the column. If not defined, defaults to HORIZONTAL_ALIGN_CENTER. Intended
-     * for testing purposes only.
-     */
-    @Nullable
-    public HorizontalAlignmentProp getHorizontalAlignment() {
-      if (mImpl.hasHorizontalAlignment()) {
-        return HorizontalAlignmentProp.fromProto(mImpl.getHorizontalAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the width of this column. If not defined, this will size itself to fit all of its
-     * children (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getWidth() {
-      if (mImpl.hasWidth()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the height of this column. If not defined, this will size itself to fit all of its
-     * children (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getHeight() {
-      if (mImpl.hasHeight()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Column fromProto(@NonNull LayoutElementProto.Column proto) {
-      return new Column(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Column toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setColumn(mImpl).build();
-    }
-
-    /** Builder for {@link Column}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Column.Builder mImpl =
-          LayoutElementProto.Column.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1411218529);
-
-      public Builder() {}
-
-      /** Adds one item to the list of child elements to place inside this {@link Column}. */
-      @NonNull
-      public Builder addContent(@NonNull LayoutElement content) {
-        mImpl.addContents(content.toLayoutElementProto());
-        mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
-        return this;
-      }
-
-      /**
-       * Sets the horizontal alignment of elements inside this column, if they are narrower than the
-       * resulting width of the column. If not defined, defaults to HORIZONTAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setHorizontalAlignment(@NonNull HorizontalAlignmentProp horizontalAlignment) {
-        mImpl.setHorizontalAlignment(horizontalAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(horizontalAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the horizontal alignment of elements inside this column, if they are narrower
-       * than the resulting width of the column. If not defined, defaults to
-       * HORIZONTAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
-        mImpl.setHorizontalAlignment(
-                AlignmentProto.HorizontalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.HorizontalAlignment.forNumber(
-                                        horizontalAlignment)));
-        return this;
-      }
-
-      /**
-       * Sets the width of this column. If not defined, this will size itself to fit all of its
-       * children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setWidth(@NonNull ContainerDimension width) {
-        mImpl.setWidth(width.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the height of this column. If not defined, this will size itself to fit all of its
-       * children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setHeight(@NonNull ContainerDimension height) {
-        mImpl.setHeight(height.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public Column build() {
-        return new Column(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * A row of elements. Each child will be laid out horizontally, one after another (i.e. stacking
-   * to the right). This element will size itself to the smallest size required to hold all of its
-   * children (e.g. if it contains three elements sized 10x10, 20x20 and 30x30, the resulting row
-   * will be 60x30).
-   *
-   * <p>If specified, vertical_alignment can be used to control the gravity inside the container,
-   * affecting the vertical placement of children whose width are smaller than the resulting row
-   * height.
-   */
-  public static final class Row implements LayoutElement {
-    private final LayoutElementProto.Row mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Row(LayoutElementProto.Row impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the list of child elements to place inside this {@link Row}. Intended for testing
-     * purposes only.
-     */
-    @NonNull
-    public List<LayoutElement> getContents() {
-      List<LayoutElement> list = new ArrayList<>();
-      for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
-        list.add(LayoutElementBuilders.layoutElementFromProto(item));
-      }
-      return Collections.unmodifiableList(list);
-    }
-
-    /**
-     * Gets the vertical alignment of elements inside this row, if they are narrower than the
-     * resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public VerticalAlignmentProp getVerticalAlignment() {
-      if (mImpl.hasVerticalAlignment()) {
-        return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlignment());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the width of this row. If not defined, this will size itself to fit all of its children
-     * (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getWidth() {
-      if (mImpl.hasWidth()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the height of this row. If not defined, this will size itself to fit all of its children
-     * (i.e. a WrappedDimension). Intended for testing purposes only.
-     */
-    @Nullable
-    public ContainerDimension getHeight() {
-      if (mImpl.hasHeight()) {
-        return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Row fromProto(@NonNull LayoutElementProto.Row proto) {
-      return new Row(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Row toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setRow(mImpl).build();
-    }
-
-    /** Builder for {@link Row}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Row.Builder mImpl = LayoutElementProto.Row.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1537205448);
-
-      public Builder() {}
-
-      /** Adds one item to the list of child elements to place inside this {@link Row}. */
-      @NonNull
-      public Builder addContent(@NonNull LayoutElement content) {
-        mImpl.addContents(content.toLayoutElementProto());
-        mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
-        return this;
-      }
-
-      /**
-       * Sets the vertical alignment of elements inside this row, if they are narrower than the
-       * resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlignment(@NonNull VerticalAlignmentProp verticalAlignment) {
-        mImpl.setVerticalAlignment(verticalAlignment.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(verticalAlignment.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the vertical alignment of elements inside this row, if they are narrower than
-       * the resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlignment(@VerticalAlignment int verticalAlignment) {
-        mImpl.setVerticalAlignment(
-                AlignmentProto.VerticalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.VerticalAlignment.forNumber(
-                                        verticalAlignment)));
-        return this;
-      }
-
-      /**
-       * Sets the width of this row. If not defined, this will size itself to fit all of its
-       * children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setWidth(@NonNull ContainerDimension width) {
-        mImpl.setWidth(width.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the height of this row. If not defined, this will size itself to fit all of its
-       * children (i.e. a WrappedDimension).
-       */
-      @NonNull
-      public Builder setHeight(@NonNull ContainerDimension height) {
-        mImpl.setHeight(height.toContainerDimensionProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public Row build() {
-        return new Row(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * 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.
-   */
-  public static final class Arc implements LayoutElement {
-    private final LayoutElementProto.Arc mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    Arc(LayoutElementProto.Arc impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets contents of this container. Intended for testing purposes only. */
-    @NonNull
-    public List<ArcLayoutElement> getContents() {
-      List<ArcLayoutElement> list = new ArrayList<>();
-      for (LayoutElementProto.ArcLayoutElement item : mImpl.getContentsList()) {
-        list.add(LayoutElementBuilders.arcLayoutElementFromProto(item));
-      }
-      return Collections.unmodifiableList(list);
-    }
-
-    /**
-     * Gets the angle for the anchor, used with anchor_type to determine where to draw children.
-     * Note that 0 degrees is the 12 o clock position on a device, and the angle sweeps clockwise.
-     * If not defined, defaults to 0 degrees.
-     *
-     * <p>Values do not have to be clamped to the range 0-360; values less than 0 degrees will sweep
-     * anti-clockwise (i.e. -90 degrees is equivalent to 270 degrees), and values >360 will be be
-     * placed at X mod 360 degrees. Intended for testing purposes only.
-     */
-    @Nullable
-    public DegreesProp getAnchorAngle() {
-      if (mImpl.hasAnchorAngle()) {
-        return DegreesProp.fromProto(mImpl.getAnchorAngle());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets how to align the contents of this container relative to anchor_angle. If not defined,
-     * defaults to ARC_ANCHOR_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public ArcAnchorTypeProp getAnchorType() {
-      if (mImpl.hasAnchorType()) {
-        return ArcAnchorTypeProp.fromProto(mImpl.getAnchorType());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is larger
-     * than the thickness of the element being drawn, this controls whether the element should be
-     * drawn towards the inner or outer edge of the arc, or drawn in the center. If not defined,
-     * defaults to VERTICAL_ALIGN_CENTER. Intended for testing purposes only.
-     */
-    @Nullable
-    public VerticalAlignmentProp getVerticalAlign() {
-      if (mImpl.hasVerticalAlign()) {
-        return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlign());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public Modifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return Modifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static Arc fromProto(@NonNull LayoutElementProto.Arc proto) {
-      return new Arc(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.Arc toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.LayoutElement toLayoutElementProto() {
-      return LayoutElementProto.LayoutElement.newBuilder().setArc(mImpl).build();
-    }
-
-    /** Builder for {@link Arc}. */
-    public static final class Builder implements LayoutElement.Builder {
-      private final LayoutElementProto.Arc.Builder mImpl = LayoutElementProto.Arc.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(299028337);
-
-      public Builder() {}
-
-      /** Adds one item to contents of this container. */
-      @NonNull
-      public Builder addContent(@NonNull ArcLayoutElement content) {
-        mImpl.addContents(content.toArcLayoutElementProto());
-        mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
-        return this;
-      }
-
-      /**
-       * Sets the angle for the anchor, used with anchor_type to determine where to draw children.
-       * Note that 0 degrees is the 12 o clock position on a device, and the angle sweeps clockwise.
-       * If not defined, defaults to 0 degrees.
-       *
-       * <p>Values do not have to be clamped to the range 0-360; values less than 0 degrees will
-       * sweep anti-clockwise (i.e. -90 degrees is equivalent to 270 degrees), and values >360 will
-       * be be placed at X mod 360 degrees.
-       */
-      @NonNull
-      public Builder setAnchorAngle(@NonNull DegreesProp anchorAngle) {
-        mImpl.setAnchorAngle(anchorAngle.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(anchorAngle.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets how to align the contents of this container relative to anchor_angle. If not defined,
-       * defaults to ARC_ANCHOR_CENTER.
-       */
-      @NonNull
-      public Builder setAnchorType(@NonNull ArcAnchorTypeProp anchorType) {
-        mImpl.setAnchorType(anchorType.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(anchorType.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets how to align the contents of this container relative to anchor_angle. If not
-       * defined, defaults to ARC_ANCHOR_CENTER.
-       */
-      @NonNull
-      public Builder setAnchorType(@ArcAnchorType int anchorType) {
-        mImpl.setAnchorType(
-                AlignmentProto.ArcAnchorTypeProp.newBuilder()
-                        .setValue(AlignmentProto.ArcAnchorType.forNumber(anchorType)));
-        return this;
-      }
-
-      /**
-       * Sets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is
-       * larger than the thickness of the element being drawn, this controls whether the element
-       * should be drawn towards the inner or outer edge of the arc, or drawn in the center. If not
-       * defined, defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlign(@NonNull VerticalAlignmentProp verticalAlign) {
-        mImpl.setVerticalAlign(verticalAlign.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(verticalAlign.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-      /**
-       * Sets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is
-       * larger than the thickness of the element being drawn, this controls whether the
-       * element should be drawn towards the inner or outer edge of the arc, or drawn in the
-       * center. If not defined, defaults to VERTICAL_ALIGN_CENTER.
-       */
-      @NonNull
-      public Builder setVerticalAlign(@VerticalAlignment int verticalAlign) {
-        mImpl.setVerticalAlign(
-                AlignmentProto.VerticalAlignmentProp.newBuilder()
-                        .setValue(
-                                AlignmentProto.VerticalAlignment.forNumber(
-                                        verticalAlign)));
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull Modifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public Arc build() {
-        return new Arc(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A text element that can be used in an {@link Arc}. */
-  public static final class ArcText implements ArcLayoutElement {
-    private final LayoutElementProto.ArcText mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ArcText(LayoutElementProto.ArcText impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the text to render. Intended for testing purposes only. */
-    @Nullable
-    public StringProp getText() {
-      if (mImpl.hasText()) {
-        return StringProp.fromProto(mImpl.getText());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the style of font to use (size, bold etc). If not specified, defaults to the platform's
-     * default body font. Intended for testing purposes only.
-     */
-    @Nullable
-    public FontStyle getFontStyle() {
-      if (mImpl.hasFontStyle()) {
-        return FontStyle.fromProto(mImpl.getFontStyle());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public ArcModifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return ArcModifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ArcText fromProto(@NonNull LayoutElementProto.ArcText proto) {
-      return new ArcText(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ArcText toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
-      return LayoutElementProto.ArcLayoutElement.newBuilder().setText(mImpl).build();
-    }
-
-    /** Builder for {@link ArcText}. */
-    public static final class Builder implements ArcLayoutElement.Builder {
-      private final LayoutElementProto.ArcText.Builder mImpl =
-          LayoutElementProto.ArcText.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(434391973);
-
-      public Builder() {}
-
-      /**
-       * Sets the text to render.
-       */
-      @NonNull
-      public Builder setText(@NonNull StringProp text) {
-        mImpl.setText(text.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets the text to render. */
-      @NonNull
-      public Builder setText(@NonNull String text) {
-        mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
-        return this;
-      }
-
-      /**
-       * Sets the style of font to use (size, bold etc). If not specified, defaults to the
-       * platform's default body font.
-       */
-      @NonNull
-      public Builder setFontStyle(@NonNull FontStyle fontStyle) {
-        mImpl.setFontStyle(fontStyle.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull ArcModifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public ArcText build() {
-        return new ArcText(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A line that can be used in an {@link Arc} and renders as a round progress bar. */
-  public static final class ArcLine implements ArcLayoutElement {
-    private final LayoutElementProto.ArcLine mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ArcLine(LayoutElementProto.ArcLine impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the length of this line, in degrees. If not defined, defaults to 0. Intended for testing
-     * purposes only.
-     */
-    @Nullable
-    public DegreesProp getLength() {
-      if (mImpl.hasLength()) {
-        return DegreesProp.fromProto(mImpl.getLength());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the thickness of this line. If not defined, defaults to 0. Intended for testing purposes
-     * only.
-     */
-    @Nullable
-    public DpProp getThickness() {
-      if (mImpl.hasThickness()) {
-        return DpProp.fromProto(mImpl.getThickness());
-      } else {
-        return null;
-      }
-    }
-
-    /** Gets the color of this line. Intended for testing purposes only. */
-    @Nullable
-    public ColorProp getColor() {
-      if (mImpl.hasColor()) {
-        return ColorProp.fromProto(mImpl.getColor());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public ArcModifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return ArcModifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ArcLine fromProto(@NonNull LayoutElementProto.ArcLine proto) {
-      return new ArcLine(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ArcLine toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
-      return LayoutElementProto.ArcLayoutElement.newBuilder().setLine(mImpl).build();
-    }
-
-    /** Builder for {@link ArcLine}. */
-    public static final class Builder implements ArcLayoutElement.Builder {
-      private final LayoutElementProto.ArcLine.Builder mImpl =
-          LayoutElementProto.ArcLine.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-1371793535);
-
-      public Builder() {}
-
-      /**
-       * Sets the length of this line, in degrees. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setLength(@NonNull DegreesProp length) {
-        mImpl.setLength(length.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(length.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the thickness of this line. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setThickness(@NonNull DpProp thickness) {
-        mImpl.setThickness(thickness.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(thickness.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the color of this line.
-       */
-      @NonNull
-      public Builder setColor(@NonNull ColorProp color) {
-        mImpl.setColor(color.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(color.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull ArcModifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            4, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-
-      @Override
-      @NonNull
-      public ArcLine build() {
-        return new ArcLine(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A simple spacer used to provide padding between adjacent elements in an {@link Arc}. */
-  public static final class ArcSpacer implements ArcLayoutElement {
-    private final LayoutElementProto.ArcSpacer mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ArcSpacer(LayoutElementProto.ArcSpacer impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /**
-     * Gets the length of this spacer, in degrees. If not defined, defaults to 0. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public DegreesProp getLength() {
-      if (mImpl.hasLength()) {
-        return DegreesProp.fromProto(mImpl.getLength());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets the thickness of this spacer, in DP. If not defined, defaults to 0. Intended for testing
-     * purposes only.
-     */
-    @Nullable
-    public DpProp getThickness() {
-      if (mImpl.hasThickness()) {
-        return DpProp.fromProto(mImpl.getThickness());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended for
-     * testing purposes only.
-     */
-    @Nullable
-    public ArcModifiers getModifiers() {
-      if (mImpl.hasModifiers()) {
-        return ArcModifiers.fromProto(mImpl.getModifiers());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ArcSpacer fromProto(@NonNull LayoutElementProto.ArcSpacer proto) {
-      return new ArcSpacer(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ArcSpacer toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
-      return LayoutElementProto.ArcLayoutElement.newBuilder().setSpacer(mImpl).build();
-    }
-
-    /** Builder for {@link ArcSpacer}. */
-    public static final class Builder implements ArcLayoutElement.Builder {
-      private final LayoutElementProto.ArcSpacer.Builder mImpl =
-          LayoutElementProto.ArcSpacer.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-179760535);
-
-      public Builder() {}
-
-      /**
-       * Sets the length of this spacer, in degrees. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setLength(@NonNull DegreesProp length) {
-        mImpl.setLength(length.toProto());
-        mFingerprint.recordPropertyUpdate(
-            1, checkNotNull(length.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets the thickness of this spacer, in DP. If not defined, defaults to 0.
-       */
-      @NonNull
-      public Builder setThickness(@NonNull DpProp thickness) {
-        mImpl.setThickness(thickness.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(thickness.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
-      @NonNull
-      public Builder setModifiers(@NonNull ArcModifiers modifiers) {
-        mImpl.setModifiers(modifiers.toProto());
-        mFingerprint.recordPropertyUpdate(
-            3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public ArcSpacer build() {
-        return new ArcSpacer(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** A container that allows a standard {@link LayoutElement} to be added to an {@link Arc}. */
-  public static final class ArcAdapter implements ArcLayoutElement {
-    private final LayoutElementProto.ArcAdapter mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    ArcAdapter(LayoutElementProto.ArcAdapter impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
-
-    /** Gets the element to adapt to an {@link Arc}. Intended for testing purposes only. */
-    @Nullable
-    public LayoutElement getContent() {
-      if (mImpl.hasContent()) {
-        return LayoutElementBuilders.layoutElementFromProto(mImpl.getContent());
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * 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. Intended for testing purposes only.
-     */
-    @Nullable
-    public BoolProp getRotateContents() {
-      if (mImpl.hasRotateContents()) {
-        return BoolProp.fromProto(mImpl.getRotateContents());
-      } else {
-        return null;
-      }
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
-
-    @NonNull
-    static ArcAdapter fromProto(@NonNull LayoutElementProto.ArcAdapter proto) {
-      return new ArcAdapter(proto, null);
-    }
-
-    @NonNull
-    LayoutElementProto.ArcAdapter toProto() {
-      return mImpl;
-    }
-
-    @Override
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
-      return LayoutElementProto.ArcLayoutElement.newBuilder().setAdapter(mImpl).build();
-    }
-
-    /** Builder for {@link ArcAdapter}. */
-    public static final class Builder implements ArcLayoutElement.Builder {
-      private final LayoutElementProto.ArcAdapter.Builder mImpl =
-          LayoutElementProto.ArcAdapter.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1696473935);
-
-      public Builder() {}
-
-      /** Sets the element to adapt to an {@link Arc}. */
-      @NonNull
-      public Builder setContent(@NonNull LayoutElement content) {
-        mImpl.setContent(content.toLayoutElementProto());
-        mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
-        return this;
-      }
-
-      /**
-       * Sets 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.
-       */
-      @NonNull
-      public Builder setRotateContents(@NonNull BoolProp rotateContents) {
-        mImpl.setRotateContents(rotateContents.toProto());
-        mFingerprint.recordPropertyUpdate(
-            2, checkNotNull(rotateContents.getFingerprint()).aggregateValueAsInt());
-        return this;
-      }
-
-      /**
-       * Sets 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.
-       */
-      @SuppressLint("MissingGetterMatchingBuilder")
-      @NonNull
-      public Builder setRotateContents(boolean rotateContents) {
-        mImpl.setRotateContents(TypesProto.BoolProp.newBuilder().setValue(rotateContents));
-        return this;
-      }
-
-      @Override
-      @NonNull
-      public ArcAdapter build() {
-        return new ArcAdapter(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /**
-   * Interface defining the root of all layout elements. This exists to act as a holder for all of
-   * the actual layout elements above.
-   */
-  public interface LayoutElement {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    LayoutElementProto.LayoutElement toLayoutElementProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link LayoutElement} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      LayoutElement build();
-    }
-  }
-
-  @NonNull
-  static LayoutElement layoutElementFromProto(@NonNull LayoutElementProto.LayoutElement proto) {
-    if (proto.hasColumn()) {
-      return Column.fromProto(proto.getColumn());
-    }
-    if (proto.hasRow()) {
-      return Row.fromProto(proto.getRow());
-    }
-    if (proto.hasBox()) {
-      return Box.fromProto(proto.getBox());
-    }
-    if (proto.hasSpacer()) {
-      return Spacer.fromProto(proto.getSpacer());
-    }
-    if (proto.hasText()) {
-      return Text.fromProto(proto.getText());
-    }
-    if (proto.hasImage()) {
-      return Image.fromProto(proto.getImage());
-    }
-    if (proto.hasArc()) {
-      return Arc.fromProto(proto.getArc());
-    }
-    if (proto.hasSpannable()) {
-      return Spannable.fromProto(proto.getSpannable());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of LayoutElement");
-  }
-
-  /**
-   * Interface defining the root of all elements that can be used in an {@link Arc}. This exists to
-   * act as a holder for all of the actual arc layout elements above.
-   */
-  public interface ArcLayoutElement {
-    /**
-     * Get the protocol buffer representation of this object.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    LayoutElementProto.ArcLayoutElement toArcLayoutElementProto();
-
-    /**
-     * Get the fingerprint for this object or null if unknown.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    Fingerprint getFingerprint();
-
-    /** Builder to create {@link ArcLayoutElement} objects. */
-    @SuppressLint("StaticFinalBuilder")
-    interface Builder {
-
-      /** Builds an instance with values accumulated in this Builder. */
-      @NonNull
-      ArcLayoutElement build();
-    }
-  }
-
-  @NonNull
-  static ArcLayoutElement arcLayoutElementFromProto(
-      @NonNull LayoutElementProto.ArcLayoutElement proto) {
-    if (proto.hasText()) {
-      return ArcText.fromProto(proto.getText());
-    }
-    if (proto.hasLine()) {
-      return ArcLine.fromProto(proto.getLine());
-    }
-    if (proto.hasSpacer()) {
-      return ArcSpacer.fromProto(proto.getSpacer());
-    }
-    if (proto.hasAdapter()) {
-      return ArcAdapter.fromProto(proto.getAdapter());
-    }
-    throw new IllegalStateException("Proto was not a recognised instance of ArcLayoutElement");
-  }
-
-  /** A complete layout. */
-  public static final class Layout {
-    private final LayoutElementProto.Layout mImpl;
-
-    private Layout(LayoutElementProto.Layout impl) {
-      this.mImpl = impl;
-    }
-
-    /** Gets the root element in the layout. Intended for testing purposes only. */
-    @Nullable
-    public LayoutElement getRoot() {
-      if (mImpl.hasRoot()) {
-        return LayoutElementBuilders.layoutElementFromProto(mImpl.getRoot());
-      } else {
-        return null;
-      }
-    }
-
-    /** Creates a {@link Layout} object containing the given layout element. */
-    @NonNull
-    public static Layout fromLayoutElement(@NonNull LayoutElement layoutElement) {
-      return new Builder().setRoot(layoutElement).build();
-    }
-
-    /** Converts to byte array representation. */
-    @NonNull
-    @ProtoLayoutExperimental
-    public byte[] toByteArray() {
-      return mImpl.toByteArray();
-    }
-
-    /** Converts from byte array representation. */
-    @SuppressWarnings("ProtoParseWithRegistry")
-    @Nullable
-    @ProtoLayoutExperimental
-    public static Layout fromByteArray(@NonNull byte[] byteArray) {
-      try {
-        return fromProto(LayoutElementProto.Layout.parseFrom(byteArray));
-      } catch (InvalidProtocolBufferException e) {
-        return null;
-      }
-    }
-
-    @NonNull
-    static Layout fromProto(@NonNull LayoutElementProto.Layout proto) {
-      return new Layout(proto);
-    }
-
-    /**
-     * Returns the internal proto instance.
-     *
-     */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @NonNull
-    public LayoutElementProto.Layout toProto() {
-      return mImpl;
-    }
-
-    /** Builder for {@link Layout} */
-    public static final class Builder {
-      private final LayoutElementProto.Layout.Builder mImpl =
-          LayoutElementProto.Layout.newBuilder();
-
-      public Builder() {}
-
-      /** Sets the root element in the layout. */
-      @NonNull
-      public Builder setRoot(@NonNull LayoutElement root) {
-        mImpl.setRoot(root.toLayoutElementProto());
-        @Nullable Fingerprint fingerprint = root.getFingerprint();
-        if (fingerprint != null) {
-          mImpl.setFingerprint(
-              TreeFingerprint.newBuilder().setRoot(fingerprintToProto(fingerprint)));
+        FontVariantProp(
+                LayoutElementProto.FontVariantProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
         }
-        return this;
-      }
 
-      private static FingerprintProto.NodeFingerprint fingerprintToProto(Fingerprint fingerprint) {
-        FingerprintProto.NodeFingerprint.Builder builder =
-            FingerprintProto.NodeFingerprint.newBuilder();
-        if (fingerprint.selfTypeValue() != 0) {
-          builder.setSelfTypeValue(fingerprint.selfTypeValue());
+        /** Gets the value. Intended for testing purposes only. */
+        @FontVariant
+        public int getValue() {
+            return mImpl.getValue().getNumber();
         }
-        if (fingerprint.selfPropsValue() != 0) {
-          builder.setSelfPropsValue(fingerprint.selfPropsValue());
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
         }
-        if (fingerprint.childNodesValue() != 0) {
-          builder.setChildNodesValue(fingerprint.childNodesValue());
+
+        @NonNull
+        static FontVariantProp fromProto(@NonNull LayoutElementProto.FontVariantProp proto) {
+            return new FontVariantProp(proto, null);
         }
-        for (Fingerprint childNode : fingerprint.childNodes()) {
-          builder.addChildNodes(fingerprintToProto(childNode));
+
+        @NonNull
+        LayoutElementProto.FontVariantProp toProto() {
+            return mImpl;
         }
-        return builder.build();
-      }
 
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public Layout build() {
-        return Layout.fromProto(mImpl.build());
-      }
-    }
-  }
+        /** Builder for {@link FontVariantProp} */
+        public static final class Builder {
+            private final LayoutElementProto.FontVariantProp.Builder mImpl =
+                    LayoutElementProto.FontVariantProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-293831500);
 
-  /**
-   * The horizontal alignment of an element within its container.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({
-    HORIZONTAL_ALIGN_UNDEFINED,
-    HORIZONTAL_ALIGN_LEFT,
-    HORIZONTAL_ALIGN_CENTER,
-    HORIZONTAL_ALIGN_RIGHT,
-    HORIZONTAL_ALIGN_START,
-    HORIZONTAL_ALIGN_END
-  })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface HorizontalAlignment {}
+            public Builder() {}
 
-  /** Horizontal alignment is undefined. */
-  public static final int HORIZONTAL_ALIGN_UNDEFINED = 0;
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@FontVariant int value) {
+                mImpl.setValue(LayoutElementProto.FontVariant.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
 
-  /** Horizontally align to the left. */
-  public static final int HORIZONTAL_ALIGN_LEFT = 1;
-
-  /** Horizontally align to center. */
-  public static final int HORIZONTAL_ALIGN_CENTER = 2;
-
-  /** Horizontally align to the right. */
-  public static final int HORIZONTAL_ALIGN_RIGHT = 3;
-
-  /** Horizontally align to the content start (left in LTR layouts, right in RTL layouts). */
-  public static final int HORIZONTAL_ALIGN_START = 4;
-
-  /** Horizontally align to the content end (right in LTR layouts, left in RTL layouts). */
-  public static final int HORIZONTAL_ALIGN_END = 5;
-
-  /**
-   * The vertical alignment of an element within its container.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({
-    VERTICAL_ALIGN_UNDEFINED,
-    VERTICAL_ALIGN_TOP,
-    VERTICAL_ALIGN_CENTER,
-    VERTICAL_ALIGN_BOTTOM
-  })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface VerticalAlignment {}
-
-  /** Vertical alignment is undefined. */
-  public static final int VERTICAL_ALIGN_UNDEFINED = 0;
-
-  /** Vertically align to the top. */
-  public static final int VERTICAL_ALIGN_TOP = 1;
-
-  /** Vertically align to center. */
-  public static final int VERTICAL_ALIGN_CENTER = 2;
-
-  /** Vertically align to the bottom. */
-  public static final int VERTICAL_ALIGN_BOTTOM = 3;
-
-  /**
-   * Alignment of a text element.
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({TEXT_ALIGN_UNDEFINED, TEXT_ALIGN_START, TEXT_ALIGN_CENTER, TEXT_ALIGN_END})
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface TextAlignment {}
-
-  /** Alignment is undefined. */
-  public static final int TEXT_ALIGN_UNDEFINED = 0;
-
-  /**
-   * Align to the "start" of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element
-   * (left in LTR layouts, right in RTL layouts).
-   */
-  public static final int TEXT_ALIGN_START = 1;
-
-  /** Align to the center of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element. */
-  public static final int TEXT_ALIGN_CENTER = 2;
-
-  /**
-   * Align to the "end" of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element (right
-   * in LTR layouts, left in RTL layouts).
-   */
-  public static final int TEXT_ALIGN_END = 3;
-
-  /**
-   * The anchor position of an {@link androidx.wear.tiles.LayoutElementBuilders.Arc}'s elements.
-   * This is used to specify how elements added to an {@link
-   * androidx.wear.tiles.LayoutElementBuilders.Arc} should be laid out with respect to anchor_angle.
-   *
-   * <p>As an example, assume that the following diagrams are wrapped to an arc, and each represents
-   * an {@link androidx.wear.tiles.LayoutElementBuilders.Arc} element containing a single {@link
-   * androidx.wear.tiles.LayoutElementBuilders.Text} element. The {@link
-   * androidx.wear.tiles.LayoutElementBuilders.Text} element's anchor_angle is "0" for all cases.
-   *
-   * <pre>{@code
-   * ARC_ANCHOR_START:
-   * -180                                0                                    180
-   *                                     Hello World!
-   *
-   *
-   * ARC_ANCHOR_CENTER:
-   * -180                                0                                    180
-   *                                Hello World!
-   *
-   * ARC_ANCHOR_END:
-   * -180                                0                                    180
-   *                          Hello World!
-   *
-   * }</pre>
-   *
-   */
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
-  @IntDef({ARC_ANCHOR_UNDEFINED, ARC_ANCHOR_START, ARC_ANCHOR_CENTER, ARC_ANCHOR_END})
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface ArcAnchorType {}
-
-  /** Anchor position is undefined. */
-  public static final int ARC_ANCHOR_UNDEFINED = 0;
-
-  /**
-   * Anchor at the start of the elements. This will cause elements added to an arc to begin at the
-   * given anchor_angle, and sweep around to the right.
-   */
-  public static final int ARC_ANCHOR_START = 1;
-
-  /**
-   * Anchor at the center of the elements. This will cause the center of the whole set of elements
-   * added to an arc to be pinned at the given anchor_angle.
-   */
-  public static final int ARC_ANCHOR_CENTER = 2;
-
-  /**
-   * Anchor at the end of the elements. This will cause the set of elements inside the arc to end at
-   * the specified anchor_angle, i.e. all elements should be to the left of anchor_angle.
-   */
-  public static final int ARC_ANCHOR_END = 3;
-
-  /** An extensible {@code HorizontalAlignment} property. */
-  public static final class HorizontalAlignmentProp {
-    private final AlignmentProto.HorizontalAlignmentProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
-
-    HorizontalAlignmentProp(
-        AlignmentProto.HorizontalAlignmentProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public FontVariantProp build() {
+                return new FontVariantProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    /** Gets the value. Intended for testing purposes only. */
-    @HorizontalAlignment
-    public int getValue() {
-      return mImpl.getValue().getNumber();
+    /** An extensible {@code SpanVerticalAlignment} property. */
+    public static final class SpanVerticalAlignmentProp {
+        private final LayoutElementProto.SpanVerticalAlignmentProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        SpanVerticalAlignmentProp(
+                LayoutElementProto.SpanVerticalAlignmentProp impl,
+                @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @SpanVerticalAlignment
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static SpanVerticalAlignmentProp fromProto(
+                @NonNull LayoutElementProto.SpanVerticalAlignmentProp proto) {
+            return new SpanVerticalAlignmentProp(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.SpanVerticalAlignmentProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link SpanVerticalAlignmentProp} */
+        public static final class Builder {
+            private final LayoutElementProto.SpanVerticalAlignmentProp.Builder mImpl =
+                    LayoutElementProto.SpanVerticalAlignmentProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1008812329);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@SpanVerticalAlignment int value) {
+                mImpl.setValue(LayoutElementProto.SpanVerticalAlignment.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public SpanVerticalAlignmentProp build() {
+                return new SpanVerticalAlignmentProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** The styling of a font (e.g. font size, and metrics). */
+    public static final class FontStyle {
+        private final LayoutElementProto.FontStyle mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        FontStyle(LayoutElementProto.FontStyle impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the size of the font, in scaled pixels (sp). If not specified, defaults to the size
+         * of the system's "body" font. Intended for testing purposes only.
+         */
+        @Nullable
+        public SpProp getSize() {
+            if (mImpl.hasSize()) {
+                return SpProp.fromProto(mImpl.getSize());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets whether the text should be rendered in a italic typeface. If not specified, defaults
+         * to "false". Intended for testing purposes only.
+         */
+        @Nullable
+        public BoolProp getItalic() {
+            if (mImpl.hasItalic()) {
+                return BoolProp.fromProto(mImpl.getItalic());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets whether the text should be rendered with an underline. If not specified, defaults to
+         * "false". Intended for testing purposes only.
+         */
+        @Nullable
+        public BoolProp getUnderline() {
+            if (mImpl.hasUnderline()) {
+                return BoolProp.fromProto(mImpl.getUnderline());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the text color. If not defined, defaults to white. Intended for testing purposes
+         * only.
+         */
+        @Nullable
+        public ColorProp getColor() {
+            if (mImpl.hasColor()) {
+                return ColorProp.fromProto(mImpl.getColor());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the weight of the font. If the provided value is not supported on a platform, the
+         * nearest supported value will be used. If not defined, or when set to an invalid value,
+         * defaults to "normal". Intended for testing purposes only.
+         */
+        @Nullable
+        public FontWeightProp getWeight() {
+            if (mImpl.hasWeight()) {
+                return FontWeightProp.fromProto(mImpl.getWeight());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the text letter-spacing. Positive numbers increase the space between letters while
+         * negative numbers tighten the space. If not specified, defaults to 0. Intended for testing
+         * purposes only.
+         */
+        @Nullable
+        public EmProp getLetterSpacing() {
+            if (mImpl.hasLetterSpacing()) {
+                return EmProp.fromProto(mImpl.getLetterSpacing());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the variant of a font. Some renderers may use different fonts for title and body
+         * text, which can be selected using this field. If not specified, defaults to "body".
+         * Intended for testing purposes only.
+         */
+        @ProtoLayoutExperimental
+        @Nullable
+        public FontVariantProp getVariant() {
+            if (mImpl.hasVariant()) {
+                return FontVariantProp.fromProto(mImpl.getVariant());
+            } else {
+                return null;
+            }
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static FontStyle fromProto(@NonNull LayoutElementProto.FontStyle proto) {
+            return new FontStyle(proto, null);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.FontStyle toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link FontStyle} */
+        public static final class Builder {
+            private final LayoutElementProto.FontStyle.Builder mImpl =
+                    LayoutElementProto.FontStyle.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(181264306);
+
+            public Builder() {}
+
+            /**
+             * Sets the size of the font, in scaled pixels (sp). If not specified, defaults to the
+             * size of the system's "body" font.
+             */
+            @NonNull
+            public Builder setSize(@NonNull SpProp size) {
+                mImpl.setSize(size.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(size.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets whether the text should be rendered in a italic typeface. If not specified,
+             * defaults to "false".
+             */
+            @NonNull
+            public Builder setItalic(@NonNull BoolProp italic) {
+                mImpl.setItalic(italic.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(italic.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets whether the text should be rendered in a italic typeface. If not specified,
+             * defaults to "false".
+             */
+            @SuppressLint("MissingGetterMatchingBuilder")
+            @NonNull
+            public Builder setItalic(boolean italic) {
+                mImpl.setItalic(TypesProto.BoolProp.newBuilder().setValue(italic));
+                return this;
+            }
+            /**
+             * Sets whether the text should be rendered with an underline. If not specified,
+             * defaults to "false".
+             */
+            @NonNull
+            public Builder setUnderline(@NonNull BoolProp underline) {
+                mImpl.setUnderline(underline.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(underline.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets whether the text should be rendered with an underline. If not specified,
+             * defaults to "false".
+             */
+            @SuppressLint("MissingGetterMatchingBuilder")
+            @NonNull
+            public Builder setUnderline(boolean underline) {
+                mImpl.setUnderline(TypesProto.BoolProp.newBuilder().setValue(underline));
+                return this;
+            }
+
+            /** Sets the text color. If not defined, defaults to white. */
+            @NonNull
+            public Builder setColor(@NonNull ColorProp color) {
+                mImpl.setColor(color.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(color.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the weight of the font. If the provided value is not supported on a platform,
+             * the nearest supported value will be used. If not defined, or when set to an invalid
+             * value, defaults to "normal".
+             */
+            @NonNull
+            public Builder setWeight(@NonNull FontWeightProp weight) {
+                mImpl.setWeight(weight.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(weight.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the weight of the font. If the provided value is not supported on a platform,
+             * the nearest supported value will be used. If not defined, or when set to an invalid
+             * value, defaults to "normal".
+             */
+            @NonNull
+            public Builder setWeight(@FontWeight int weight) {
+                mImpl.setWeight(
+                        LayoutElementProto.FontWeightProp.newBuilder()
+                                .setValue(LayoutElementProto.FontWeight.forNumber(weight)));
+                return this;
+            }
+
+            /**
+             * Sets the text letter-spacing. Positive numbers increase the space between letters
+             * while negative numbers tighten the space. If not specified, defaults to 0.
+             */
+            @NonNull
+            public Builder setLetterSpacing(@NonNull EmProp letterSpacing) {
+                mImpl.setLetterSpacing(letterSpacing.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        6, checkNotNull(letterSpacing.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the variant of a font. Some renderers may use different fonts for title and body
+             * text, which can be selected using this field. If not specified, defaults to "body".
+             */
+            @ProtoLayoutExperimental
+            @NonNull
+            public Builder setVariant(@NonNull FontVariantProp variant) {
+                mImpl.setVariant(variant.toProto());
+                return this;
+            }
+            /**
+             * Sets the variant of a font. Some renderers may use different fonts for title and body
+             * text, which can be selected using this field. If not specified, defaults to "body".
+             */
+            @ProtoLayoutExperimental
+            @NonNull
+            public Builder setVariant(@FontVariant int variant) {
+                mImpl.setVariant(
+                        LayoutElementProto.FontVariantProp.newBuilder()
+                                .setValue(LayoutElementProto.FontVariant.forNumber(variant)));
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public FontStyle build() {
+                return new FontStyle(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** An extensible {@code TextOverflow} property. */
+    public static final class TextOverflowProp {
+        private final LayoutElementProto.TextOverflowProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        TextOverflowProp(
+                LayoutElementProto.TextOverflowProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @TextOverflow
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static TextOverflowProp fromProto(@NonNull LayoutElementProto.TextOverflowProp proto) {
+            return new TextOverflowProp(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.TextOverflowProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link TextOverflowProp} */
+        public static final class Builder {
+            private final LayoutElementProto.TextOverflowProp.Builder mImpl =
+                    LayoutElementProto.TextOverflowProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1183432233);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@TextOverflow int value) {
+                mImpl.setValue(LayoutElementProto.TextOverflow.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public TextOverflowProp build() {
+                return new TextOverflowProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A text string. */
+    public static final class Text implements LayoutElement {
+        private final LayoutElementProto.Text mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Text(LayoutElementProto.Text impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the text to render. Intended for testing purposes only. */
+        @Nullable
+        public StringProp getText() {
+            if (mImpl.hasText()) {
+                return StringProp.fromProto(mImpl.getText());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the style of font to use (size, bold etc). If not specified, defaults to the
+         * platform's default body font. Intended for testing purposes only.
+         */
+        @Nullable
+        public FontStyle getFontStyle() {
+            if (mImpl.hasFontStyle()) {
+                return FontStyle.fromProto(mImpl.getFontStyle());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the maximum number of lines that can be represented by the {@link Text} element. If
+         * not defined, the {@link Text} element will be treated as a single-line element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Int32Prop getMaxLines() {
+            if (mImpl.hasMaxLines()) {
+                return Int32Prop.fromProto(mImpl.getMaxLines());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets alignment of the text within its bounds. Note that a {@link Text} element will size
+         * itself to wrap its contents, so this option is meaningless for single-line text (for
+         * that, use alignment of the outer container). For multi-line text, however, this will set
+         * the alignment of lines relative to the {@link Text} element bounds. If not defined,
+         * defaults to TEXT_ALIGN_CENTER. Intended for testing purposes only.
+         */
+        @Nullable
+        public TextAlignmentProp getMultilineAlignment() {
+            if (mImpl.hasMultilineAlignment()) {
+                return TextAlignmentProp.fromProto(mImpl.getMultilineAlignment());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets how to handle text which overflows the bound of the {@link Text} element. A {@link
+         * Text} element will grow as large as possible inside its parent container (while still
+         * respecting max_lines); if it cannot grow large enough to render all of its text, the text
+         * which cannot fit inside its container will be truncated. If not defined, defaults to
+         * TEXT_OVERFLOW_TRUNCATE. Intended for testing purposes only.
+         */
+        @Nullable
+        public TextOverflowProp getOverflow() {
+            if (mImpl.hasOverflow()) {
+                return TextOverflowProp.fromProto(mImpl.getOverflow());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the explicit height between lines of text. This is equivalent to the vertical
+         * distance between subsequent baselines. If not specified, defaults the font's recommended
+         * interline spacing. Intended for testing purposes only.
+         */
+        @Nullable
+        public SpProp getLineHeight() {
+            if (mImpl.hasLineHeight()) {
+                return SpProp.fromProto(mImpl.getLineHeight());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Text fromProto(@NonNull LayoutElementProto.Text proto) {
+            return new Text(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Text toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setText(mImpl).build();
+        }
+
+        /** Builder for {@link Text}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Text.Builder mImpl =
+                    LayoutElementProto.Text.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1976530157);
+
+            public Builder() {}
+
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull StringProp text) {
+                mImpl.setText(text.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull String text) {
+                mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
+                return this;
+            }
+
+            /**
+             * Sets the style of font to use (size, bold etc). If not specified, defaults to the
+             * platform's default body font.
+             */
+            @NonNull
+            public Builder setFontStyle(@NonNull FontStyle fontStyle) {
+                mImpl.setFontStyle(fontStyle.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the maximum number of lines that can be represented by the {@link Text} element.
+             * If not defined, the {@link Text} element will be treated as a single-line element.
+             */
+            @NonNull
+            public Builder setMaxLines(@NonNull Int32Prop maxLines) {
+                mImpl.setMaxLines(maxLines.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(maxLines.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the maximum number of lines that can be represented by the {@link Text} element.
+             * If not defined, the {@link Text} element will be treated as a single-line element.
+             */
+            @NonNull
+            public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
+                mImpl.setMaxLines(TypesProto.Int32Prop.newBuilder().setValue(maxLines));
+                return this;
+            }
+
+            /**
+             * Sets alignment of the text within its bounds. Note that a {@link Text} element will
+             * size itself to wrap its contents, so this option is meaningless for single-line text
+             * (for that, use alignment of the outer container). For multi-line text, however, this
+             * will set the alignment of lines relative to the {@link Text} element bounds. If not
+             * defined, defaults to TEXT_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setMultilineAlignment(@NonNull TextAlignmentProp multilineAlignment) {
+                mImpl.setMultilineAlignment(multilineAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(multilineAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets alignment of the text within its bounds. Note that a {@link Text} element will
+             * size itself to wrap its contents, so this option is meaningless for single-line text
+             * (for that, use alignment of the outer container). For multi-line text, however, this
+             * will set the alignment of lines relative to the {@link Text} element bounds. If not
+             * defined, defaults to TEXT_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setMultilineAlignment(@TextAlignment int multilineAlignment) {
+                mImpl.setMultilineAlignment(
+                        AlignmentProto.TextAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.TextAlignment.forNumber(
+                                                multilineAlignment)));
+                return this;
+            }
+
+            /**
+             * Sets how to handle text which overflows the bound of the {@link Text} element. A
+             * {@link Text} element will grow as large as possible inside its parent container
+             * (while still respecting max_lines); if it cannot grow large enough to render all of
+             * its text, the text which cannot fit inside its container will be truncated. If not
+             * defined, defaults to TEXT_OVERFLOW_TRUNCATE.
+             */
+            @NonNull
+            public Builder setOverflow(@NonNull TextOverflowProp overflow) {
+                mImpl.setOverflow(overflow.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        6, checkNotNull(overflow.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets how to handle text which overflows the bound of the {@link Text} element. A
+             * {@link Text} element will grow as large as possible inside its parent container
+             * (while still respecting max_lines); if it cannot grow large enough to render all of
+             * its text, the text which cannot fit inside its container will be truncated. If not
+             * defined, defaults to TEXT_OVERFLOW_TRUNCATE.
+             */
+            @NonNull
+            public Builder setOverflow(@TextOverflow int overflow) {
+                mImpl.setOverflow(
+                        LayoutElementProto.TextOverflowProp.newBuilder()
+                                .setValue(LayoutElementProto.TextOverflow.forNumber(overflow)));
+                return this;
+            }
+
+            /**
+             * Sets the explicit height between lines of text. This is equivalent to the vertical
+             * distance between subsequent baselines. If not specified, defaults the font's
+             * recommended interline spacing.
+             */
+            @NonNull
+            public Builder setLineHeight(@NonNull SpProp lineHeight) {
+                mImpl.setLineHeight(lineHeight.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        7, checkNotNull(lineHeight.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Text build() {
+                return new Text(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** An extensible {@code ContentScaleMode} property. */
+    public static final class ContentScaleModeProp {
+        private final LayoutElementProto.ContentScaleModeProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ContentScaleModeProp(
+                LayoutElementProto.ContentScaleModeProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @ContentScaleMode
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ContentScaleModeProp fromProto(
+                @NonNull LayoutElementProto.ContentScaleModeProp proto) {
+            return new ContentScaleModeProp(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ContentScaleModeProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link ContentScaleModeProp} */
+        public static final class Builder {
+            private final LayoutElementProto.ContentScaleModeProp.Builder mImpl =
+                    LayoutElementProto.ContentScaleModeProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-893830536);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@ContentScaleMode int value) {
+                mImpl.setValue(LayoutElementProto.ContentScaleMode.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public ContentScaleModeProp build() {
+                return new ContentScaleModeProp(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** Filtering parameters used for images. This can be used to apply a color tint to images. */
+    public static final class ColorFilter {
+        private final LayoutElementProto.ColorFilter mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ColorFilter(LayoutElementProto.ColorFilter impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the tint color to use. If specified, the image will be tinted, using SRC_IN blending
+         * (that is, all color information will be stripped from the target image, and only the
+         * alpha channel will be blended with the requested color).
+         *
+         * <p>Note that only Android image resources can be tinted; Inline images will not be
+         * tinted, and this property will have no effect. Intended for testing purposes only.
+         */
+        @Nullable
+        public ColorProp getTint() {
+            if (mImpl.hasTint()) {
+                return ColorProp.fromProto(mImpl.getTint());
+            } else {
+                return null;
+            }
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ColorFilter fromProto(@NonNull LayoutElementProto.ColorFilter proto) {
+            return new ColorFilter(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ColorFilter toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link ColorFilter} */
+        public static final class Builder {
+            private final LayoutElementProto.ColorFilter.Builder mImpl =
+                    LayoutElementProto.ColorFilter.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(181311326);
+
+            public Builder() {}
+
+            /**
+             * Sets the tint color to use. If specified, the image will be tinted, using SRC_IN
+             * blending (that is, all color information will be stripped from the target image, and
+             * only the alpha channel will be blended with the requested color).
+             *
+             * <p>Note that only Android image resources can be tinted; Inline images will not be
+             * tinted, and this property will have no effect.
+             */
+            @NonNull
+            public Builder setTint(@NonNull ColorProp tint) {
+                mImpl.setTint(tint.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(tint.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public ColorFilter build() {
+                return new ColorFilter(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
+     * An image.
      *
+     * <p>Images used in this element must exist in the resource bundle that corresponds to this
+     * layout. Images must have their dimension specified, and will be rendered at this width and
+     * height, regardless of their native dimension.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
+    public static final class Image implements LayoutElement {
+        private final LayoutElementProto.Image mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Image(LayoutElementProto.Image impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the resource_id of the image to render. This must exist in the supplied resource
+         * bundle. Intended for testing purposes only.
+         */
+        @Nullable
+        public StringProp getResourceId() {
+            if (mImpl.hasResourceId()) {
+                return StringProp.fromProto(mImpl.getResourceId());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the width of this image. If not defined, the image will not be rendered. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public ImageDimension getWidth() {
+            if (mImpl.hasWidth()) {
+                return DimensionBuilders.imageDimensionFromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the height of this image. If not defined, the image will not be rendered. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public ImageDimension getHeight() {
+            if (mImpl.hasHeight()) {
+                return DimensionBuilders.imageDimensionFromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets how to scale the image resource inside the bounds specified by width/height if its
+         * size does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT. Intended for
+         * testing purposes only.
+         */
+        @Nullable
+        public ContentScaleModeProp getContentScaleMode() {
+            if (mImpl.hasContentScaleMode()) {
+                return ContentScaleModeProp.fromProto(mImpl.getContentScaleMode());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets filtering parameters for this image. If not specified, defaults to no filtering.
+         * Intended for testing purposes only.
+         */
+        @Nullable
+        public ColorFilter getColorFilter() {
+            if (mImpl.hasColorFilter()) {
+                return ColorFilter.fromProto(mImpl.getColorFilter());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Image fromProto(@NonNull LayoutElementProto.Image proto) {
+            return new Image(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Image toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setImage(mImpl).build();
+        }
+
+        /** Builder for {@link Image}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Image.Builder mImpl =
+                    LayoutElementProto.Image.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-543078544);
+
+            public Builder() {}
+
+            /**
+             * Sets the resource_id of the image to render. This must exist in the supplied resource
+             * bundle.
+             */
+            @NonNull
+            public Builder setResourceId(@NonNull StringProp resourceId) {
+                mImpl.setResourceId(resourceId.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(resourceId.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the resource_id of the image to render. This must exist in the supplied resource
+             * bundle.
+             */
+            @NonNull
+            public Builder setResourceId(@NonNull String resourceId) {
+                mImpl.setResourceId(TypesProto.StringProp.newBuilder().setValue(resourceId));
+                return this;
+            }
+
+            /** Sets the width of this image. If not defined, the image will not be rendered. */
+            @NonNull
+            public Builder setWidth(@NonNull ImageDimension width) {
+                mImpl.setWidth(width.toImageDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the height of this image. If not defined, the image will not be rendered. */
+            @NonNull
+            public Builder setHeight(@NonNull ImageDimension height) {
+                mImpl.setHeight(height.toImageDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets how to scale the image resource inside the bounds specified by width/height if
+             * its size does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT.
+             */
+            @NonNull
+            public Builder setContentScaleMode(@NonNull ContentScaleModeProp contentScaleMode) {
+                mImpl.setContentScaleMode(contentScaleMode.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(contentScaleMode.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets how to scale the image resource inside the bounds specified by width/height if
+             * its size does not match those bounds. Defaults to CONTENT_SCALE_MODE_FIT.
+             */
+            @NonNull
+            public Builder setContentScaleMode(@ContentScaleMode int contentScaleMode) {
+                mImpl.setContentScaleMode(
+                        LayoutElementProto.ContentScaleModeProp.newBuilder()
+                                .setValue(
+                                        LayoutElementProto.ContentScaleMode.forNumber(
+                                                contentScaleMode)));
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets filtering parameters for this image. If not specified, defaults to no filtering.
+             */
+            @NonNull
+            public Builder setColorFilter(@NonNull ColorFilter colorFilter) {
+                mImpl.setColorFilter(colorFilter.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        6, checkNotNull(colorFilter.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Image build() {
+                return new Image(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    @NonNull
-    static HorizontalAlignmentProp fromProto(
-        @NonNull AlignmentProto.HorizontalAlignmentProp proto) {
-      return new HorizontalAlignmentProp(proto, null);
-    }
+    /** A simple spacer, typically used to provide padding between adjacent elements. */
+    public static final class Spacer implements LayoutElement {
+        private final LayoutElementProto.Spacer mImpl;
+        @Nullable private final Fingerprint mFingerprint;
 
-    @NonNull
-    AlignmentProto.HorizontalAlignmentProp toProto() {
-      return mImpl;
-    }
+        Spacer(LayoutElementProto.Spacer impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
 
-    /** Builder for {@link HorizontalAlignmentProp} */
-    public static final class Builder {
-      private final AlignmentProto.HorizontalAlignmentProp.Builder mImpl =
-          AlignmentProto.HorizontalAlignmentProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(-384830516);
+        /**
+         * Gets the width of this {@link Spacer}. When this is added as the direct child of an
+         * {@link Arc}, this must be specified as an angular dimension, otherwise a linear dimension
+         * must be used. If not defined, defaults to 0. Intended for testing purposes only.
+         */
+        @Nullable
+        public SpacerDimension getWidth() {
+            if (mImpl.hasWidth()) {
+                return DimensionBuilders.spacerDimensionFromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
 
-      public Builder() {}
+        /**
+         * Gets the height of this spacer. If not defined, defaults to 0. Intended for testing
+         * purposes only.
+         */
+        @Nullable
+        public SpacerDimension getHeight() {
+            if (mImpl.hasHeight()) {
+                return DimensionBuilders.spacerDimensionFromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
 
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@HorizontalAlignment int value) {
-        mImpl.setValue(AlignmentProto.HorizontalAlignment.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
 
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public HorizontalAlignmentProp build() {
-        return new HorizontalAlignmentProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
 
-  /** An extensible {@code VerticalAlignment} property. */
-  public static final class VerticalAlignmentProp {
-    private final AlignmentProto.VerticalAlignmentProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
+        @NonNull
+        static Spacer fromProto(@NonNull LayoutElementProto.Spacer proto) {
+            return new Spacer(proto, null);
+        }
 
-    VerticalAlignmentProp(
-        AlignmentProto.VerticalAlignmentProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
+        @NonNull
+        LayoutElementProto.Spacer toProto() {
+            return mImpl;
+        }
 
-    /** Gets the value. Intended for testing purposes only. */
-    @VerticalAlignment
-    public int getValue() {
-      return mImpl.getValue().getNumber();
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setSpacer(mImpl).build();
+        }
+
+        /** Builder for {@link Spacer}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Spacer.Builder mImpl =
+                    LayoutElementProto.Spacer.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1748084575);
+
+            public Builder() {}
+
+            /**
+             * Sets the width of this {@link Spacer}. When this is added as the direct child of an
+             * {@link Arc}, this must be specified as an angular dimension, otherwise a linear
+             * dimension must be used. If not defined, defaults to 0.
+             */
+            @NonNull
+            public Builder setWidth(@NonNull SpacerDimension width) {
+                mImpl.setWidth(width.toSpacerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the height of this spacer. If not defined, defaults to 0. */
+            @NonNull
+            public Builder setHeight(@NonNull SpacerDimension height) {
+                mImpl.setHeight(height.toSpacerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Spacer build() {
+                return new Spacer(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * A container which stacks all of its children on top of one another. This also allows to add a
+     * background color, or to have a border around them with some padding.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
-    }
+    public static final class Box implements LayoutElement {
+        private final LayoutElementProto.Box mImpl;
+        @Nullable private final Fingerprint mFingerprint;
 
-    @NonNull
-    static VerticalAlignmentProp fromProto(@NonNull AlignmentProto.VerticalAlignmentProp proto) {
-      return new VerticalAlignmentProp(proto, null);
-    }
+        Box(LayoutElementProto.Box impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
 
-    @NonNull
-    AlignmentProto.VerticalAlignmentProp toProto() {
-      return mImpl;
-    }
+        /** Gets the child element(s) to wrap. Intended for testing purposes only. */
+        @NonNull
+        public List<LayoutElement> getContents() {
+            List<LayoutElement> list = new ArrayList<>();
+            for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
+                list.add(LayoutElementBuilders.layoutElementFromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
 
-    /** Builder for {@link VerticalAlignmentProp} */
-    public static final class Builder {
-      private final AlignmentProto.VerticalAlignmentProp.Builder mImpl =
-          AlignmentProto.VerticalAlignmentProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1443510393);
+        /**
+         * Gets the height of this {@link Box}. If not defined, this will size itself to fit all of
+         * its children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getHeight() {
+            if (mImpl.hasHeight()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
 
-      public Builder() {}
+        /**
+         * Gets the width of this {@link Box}. If not defined, this will size itself to fit all of
+         * its children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getWidth() {
+            if (mImpl.hasWidth()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
 
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@VerticalAlignment int value) {
-        mImpl.setValue(AlignmentProto.VerticalAlignment.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
+        /**
+         * Gets the horizontal alignment of the element inside this {@link Box}. If not defined,
+         * defaults to HORIZONTAL_ALIGN_CENTER. Intended for testing purposes only.
+         */
+        @Nullable
+        public HorizontalAlignmentProp getHorizontalAlignment() {
+            if (mImpl.hasHorizontalAlignment()) {
+                return HorizontalAlignmentProp.fromProto(mImpl.getHorizontalAlignment());
+            } else {
+                return null;
+            }
+        }
 
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public VerticalAlignmentProp build() {
-        return new VerticalAlignmentProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
+        /**
+         * Gets the vertical alignment of the element inside this {@link Box}. If not defined,
+         * defaults to VERTICAL_ALIGN_CENTER. Intended for testing purposes only.
+         */
+        @Nullable
+        public VerticalAlignmentProp getVerticalAlignment() {
+            if (mImpl.hasVerticalAlignment()) {
+                return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlignment());
+            } else {
+                return null;
+            }
+        }
 
-  /** An extensible {@code TextAlignment} property. */
-  public static final class TextAlignmentProp {
-    private final AlignmentProto.TextAlignmentProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
 
-    TextAlignmentProp(
-        AlignmentProto.TextAlignmentProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
 
-    /** Gets the value. Intended for testing purposes only. */
-    @TextAlignment
-    public int getValue() {
-      return mImpl.getValue().getNumber();
+        @NonNull
+        static Box fromProto(@NonNull LayoutElementProto.Box proto) {
+            return new Box(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Box toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setBox(mImpl).build();
+        }
+
+        /** Builder for {@link Box}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Box.Builder mImpl =
+                    LayoutElementProto.Box.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1881256071);
+
+            public Builder() {}
+
+            /** Adds one item to the child element(s) to wrap. */
+            @NonNull
+            public Builder addContent(@NonNull LayoutElement content) {
+                mImpl.addContents(content.toLayoutElementProto());
+                mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
+                return this;
+            }
+
+            /**
+             * Sets the height of this {@link Box}. If not defined, this will size itself to fit all
+             * of its children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setHeight(@NonNull ContainerDimension height) {
+                mImpl.setHeight(height.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the width of this {@link Box}. If not defined, this will size itself to fit all
+             * of its children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setWidth(@NonNull ContainerDimension width) {
+                mImpl.setWidth(width.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the horizontal alignment of the element inside this {@link Box}. If not defined,
+             * defaults to HORIZONTAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setHorizontalAlignment(
+                    @NonNull HorizontalAlignmentProp horizontalAlignment) {
+                mImpl.setHorizontalAlignment(horizontalAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4,
+                        checkNotNull(horizontalAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the horizontal alignment of the element inside this {@link Box}. If not defined,
+             * defaults to HORIZONTAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+                mImpl.setHorizontalAlignment(
+                        AlignmentProto.HorizontalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.HorizontalAlignment.forNumber(
+                                                horizontalAlignment)));
+                return this;
+            }
+
+            /**
+             * Sets the vertical alignment of the element inside this {@link Box}. If not defined,
+             * defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlignment(@NonNull VerticalAlignmentProp verticalAlignment) {
+                mImpl.setVerticalAlignment(verticalAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(verticalAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the vertical alignment of the element inside this {@link Box}. If not defined,
+             * defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlignment(@VerticalAlignment int verticalAlignment) {
+                mImpl.setVerticalAlignment(
+                        AlignmentProto.VerticalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.VerticalAlignment.forNumber(
+                                                verticalAlignment)));
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        6, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Box build() {
+                return new Box(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * A portion of text which can be added to a {@link Span}. Two different {@link SpanText}
+     * elements on the same line will be aligned to the same baseline, regardless of the size of
+     * each {@link SpanText}.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
+    public static final class SpanText implements Span {
+        private final LayoutElementProto.SpanText mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        SpanText(LayoutElementProto.SpanText impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the text to render. Intended for testing purposes only. */
+        @Nullable
+        public StringProp getText() {
+            if (mImpl.hasText()) {
+                return StringProp.fromProto(mImpl.getText());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the style of font to use (size, bold etc). If not specified, defaults to the
+         * platform's default body font. Intended for testing purposes only.
+         */
+        @Nullable
+        public FontStyle getFontStyle() {
+            if (mImpl.hasFontStyle()) {
+                return FontStyle.fromProto(mImpl.getFontStyle());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public SpanModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return SpanModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static SpanText fromProto(@NonNull LayoutElementProto.SpanText proto) {
+            return new SpanText(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.SpanText toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.Span toSpanProto() {
+            return LayoutElementProto.Span.newBuilder().setText(mImpl).build();
+        }
+
+        /** Builder for {@link SpanText}. */
+        public static final class Builder implements Span.Builder {
+            private final LayoutElementProto.SpanText.Builder mImpl =
+                    LayoutElementProto.SpanText.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-221774557);
+
+            public Builder() {}
+
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull StringProp text) {
+                mImpl.setText(text.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull String text) {
+                mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
+                return this;
+            }
+
+            /**
+             * Sets the style of font to use (size, bold etc). If not specified, defaults to the
+             * platform's default body font.
+             */
+            @NonNull
+            public Builder setFontStyle(@NonNull FontStyle fontStyle) {
+                mImpl.setFontStyle(fontStyle.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull SpanModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public SpanText build() {
+                return new SpanText(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    @NonNull
-    static TextAlignmentProp fromProto(@NonNull AlignmentProto.TextAlignmentProp proto) {
-      return new TextAlignmentProp(proto, null);
-    }
+    /** An image which can be added to a {@link Span}. */
+    public static final class SpanImage implements Span {
+        private final LayoutElementProto.SpanImage mImpl;
+        @Nullable private final Fingerprint mFingerprint;
 
-    @NonNull
-    AlignmentProto.TextAlignmentProp toProto() {
-      return mImpl;
-    }
+        SpanImage(LayoutElementProto.SpanImage impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
 
-    /** Builder for {@link TextAlignmentProp} */
-    public static final class Builder {
-      private final AlignmentProto.TextAlignmentProp.Builder mImpl =
-          AlignmentProto.TextAlignmentProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(797507251);
+        /**
+         * Gets the resource_id of the image to render. This must exist in the supplied resource
+         * bundle. Intended for testing purposes only.
+         */
+        @Nullable
+        public StringProp getResourceId() {
+            if (mImpl.hasResourceId()) {
+                return StringProp.fromProto(mImpl.getResourceId());
+            } else {
+                return null;
+            }
+        }
 
-      public Builder() {}
+        /**
+         * Gets the width of this image. If not defined, the image will not be rendered. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public DpProp getWidth() {
+            if (mImpl.hasWidth()) {
+                return DpProp.fromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
 
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@TextAlignment int value) {
-        mImpl.setValue(AlignmentProto.TextAlignment.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
+        /**
+         * Gets the height of this image. If not defined, the image will not be rendered. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public DpProp getHeight() {
+            if (mImpl.hasHeight()) {
+                return DpProp.fromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
 
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public TextAlignmentProp build() {
-        return new TextAlignmentProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public SpanModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return SpanModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
 
-  /** An extensible {@code ArcAnchorType} property. */
-  public static final class ArcAnchorTypeProp {
-    private final AlignmentProto.ArcAnchorTypeProp mImpl;
-    @Nullable private final Fingerprint mFingerprint;
+        /**
+         * Gets alignment of this image within the line height of the surrounding {@link Spannable}.
+         * If undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM. Intended for testing purposes only.
+         */
+        @Nullable
+        public SpanVerticalAlignmentProp getAlignment() {
+            if (mImpl.hasAlignment()) {
+                return SpanVerticalAlignmentProp.fromProto(mImpl.getAlignment());
+            } else {
+                return null;
+            }
+        }
 
-    ArcAnchorTypeProp(
-        AlignmentProto.ArcAnchorTypeProp impl, @Nullable Fingerprint fingerprint) {
-      this.mImpl = impl;
-      this.mFingerprint = fingerprint;
-    }
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
 
-    /** Gets the value. Intended for testing purposes only. */
-    @ArcAnchorType
-    public int getValue() {
-      return mImpl.getValue().getNumber();
+        @NonNull
+        static SpanImage fromProto(@NonNull LayoutElementProto.SpanImage proto) {
+            return new SpanImage(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.SpanImage toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.Span toSpanProto() {
+            return LayoutElementProto.Span.newBuilder().setImage(mImpl).build();
+        }
+
+        /** Builder for {@link SpanImage}. */
+        public static final class Builder implements Span.Builder {
+            private final LayoutElementProto.SpanImage.Builder mImpl =
+                    LayoutElementProto.SpanImage.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(502289772);
+
+            public Builder() {}
+
+            /**
+             * Sets the resource_id of the image to render. This must exist in the supplied resource
+             * bundle.
+             */
+            @NonNull
+            public Builder setResourceId(@NonNull StringProp resourceId) {
+                mImpl.setResourceId(resourceId.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(resourceId.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the resource_id of the image to render. This must exist in the supplied resource
+             * bundle.
+             */
+            @NonNull
+            public Builder setResourceId(@NonNull String resourceId) {
+                mImpl.setResourceId(TypesProto.StringProp.newBuilder().setValue(resourceId));
+                return this;
+            }
+
+            /** Sets the width of this image. If not defined, the image will not be rendered. */
+            @NonNull
+            public Builder setWidth(@NonNull DpProp width) {
+                mImpl.setWidth(width.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the height of this image. If not defined, the image will not be rendered. */
+            @NonNull
+            public Builder setHeight(@NonNull DpProp height) {
+                mImpl.setHeight(height.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull SpanModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets alignment of this image within the line height of the surrounding {@link
+             * Spannable}. If undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM.
+             */
+            @NonNull
+            public Builder setAlignment(@NonNull SpanVerticalAlignmentProp alignment) {
+                mImpl.setAlignment(alignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(alignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets alignment of this image within the line height of the surrounding {@link
+             * Spannable}. If undefined, defaults to SPAN_VERTICAL_ALIGN_BOTTOM.
+             */
+            @NonNull
+            public Builder setAlignment(@SpanVerticalAlignment int alignment) {
+                mImpl.setAlignment(
+                        LayoutElementProto.SpanVerticalAlignmentProp.newBuilder()
+                                .setValue(
+                                        LayoutElementProto.SpanVerticalAlignment.forNumber(
+                                                alignment)));
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public SpanImage build() {
+                return new SpanImage(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
     /**
-     * Get the fingerprint for this object, or null if unknown.
-     *
+     * Interface defining a single {@link Span}. Each {@link Span} forms part of a larger {@link
+     * Spannable} widget. At the moment, the only widgets which can be added to {@link Spannable}
+     * containers are {@link SpanText} and {@link SpanImage} elements.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
-    @Nullable
-    public Fingerprint getFingerprint() {
-      return mFingerprint;
+    public interface Span {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        LayoutElementProto.Span toSpanProto();
+
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
+
+        /** Builder to create {@link Span} objects. */
+        @SuppressLint("StaticFinalBuilder")
+        interface Builder {
+
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            Span build();
+        }
     }
 
     @NonNull
-    static ArcAnchorTypeProp fromProto(@NonNull AlignmentProto.ArcAnchorTypeProp proto) {
-      return new ArcAnchorTypeProp(proto, null);
+    static Span spanFromProto(@NonNull LayoutElementProto.Span proto) {
+        if (proto.hasText()) {
+            return SpanText.fromProto(proto.getText());
+        }
+        if (proto.hasImage()) {
+            return SpanImage.fromProto(proto.getImage());
+        }
+        throw new IllegalStateException("Proto was not a recognised instance of Span");
+    }
+
+    /**
+     * A container of {@link Span} elements. Currently, this supports {@link SpanImage} and {@link
+     * SpanText} elements, where each individual {@link Span} can have different styling applied to
+     * it but the resulting text will flow naturally. This allows sections of a paragraph of text to
+     * have different styling applied to it, for example, making one or two words bold or italic.
+     */
+    public static final class Spannable implements LayoutElement {
+        private final LayoutElementProto.Spannable mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Spannable(LayoutElementProto.Spannable impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the {@link Span} elements that form this {@link Spannable}. Intended for testing
+         * purposes only.
+         */
+        @NonNull
+        public List<Span> getSpans() {
+            List<Span> list = new ArrayList<>();
+            for (LayoutElementProto.Span item : mImpl.getSpansList()) {
+                list.add(LayoutElementBuilders.spanFromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the maximum number of lines that can be represented by the {@link Spannable}
+         * element. If not defined, the {@link Spannable} element will be treated as a single-line
+         * element. Intended for testing purposes only.
+         */
+        @Nullable
+        public Int32Prop getMaxLines() {
+            if (mImpl.hasMaxLines()) {
+                return Int32Prop.fromProto(mImpl.getMaxLines());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets alignment of the {@link Spannable} content within its bounds. Note that a {@link
+         * Spannable} element will size itself to wrap its contents, so this option is meaningless
+         * for single-line content (for that, use alignment of the outer container). For multi-line
+         * content, however, this will set the alignment of lines relative to the {@link Spannable}
+         * element bounds. If not defined, defaults to TEXT_ALIGN_CENTER. Intended for testing
+         * purposes only.
+         */
+        @Nullable
+        public HorizontalAlignmentProp getMultilineAlignment() {
+            if (mImpl.hasMultilineAlignment()) {
+                return HorizontalAlignmentProp.fromProto(mImpl.getMultilineAlignment());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets how to handle content which overflows the bound of the {@link Spannable} element. A
+         * {@link Spannable} element will grow as large as possible inside its parent container
+         * (while still respecting max_lines); if it cannot grow large enough to render all of its
+         * content, the content which cannot fit inside its container will be truncated. If not
+         * defined, defaults to TEXT_OVERFLOW_TRUNCATE. Intended for testing purposes only.
+         */
+        @Nullable
+        public TextOverflowProp getOverflow() {
+            if (mImpl.hasOverflow()) {
+                return TextOverflowProp.fromProto(mImpl.getOverflow());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the explicit height between lines of text. This is equivalent to the vertical
+         * distance between subsequent baselines. If not specified, defaults the font's recommended
+         * interline spacing. Intended for testing purposes only.
+         */
+        @Nullable
+        public SpProp getLineHeight() {
+            if (mImpl.hasLineHeight()) {
+                return SpProp.fromProto(mImpl.getLineHeight());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Spannable fromProto(@NonNull LayoutElementProto.Spannable proto) {
+            return new Spannable(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Spannable toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setSpannable(mImpl).build();
+        }
+
+        /** Builder for {@link Spannable}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Spannable.Builder mImpl =
+                    LayoutElementProto.Spannable.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1690284372);
+
+            public Builder() {}
+
+            /** Adds one item to the {@link Span} elements that form this {@link Spannable}. */
+            @NonNull
+            public Builder addSpan(@NonNull Span span) {
+                mImpl.addSpans(span.toSpanProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(span.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the maximum number of lines that can be represented by the {@link Spannable}
+             * element. If not defined, the {@link Spannable} element will be treated as a
+             * single-line element.
+             */
+            @NonNull
+            public Builder setMaxLines(@NonNull Int32Prop maxLines) {
+                mImpl.setMaxLines(maxLines.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(maxLines.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets the maximum number of lines that can be represented by the {@link Spannable}
+             * element. If not defined, the {@link Spannable} element will be treated as a
+             * single-line element.
+             */
+            @NonNull
+            public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
+                mImpl.setMaxLines(TypesProto.Int32Prop.newBuilder().setValue(maxLines));
+                return this;
+            }
+
+            /**
+             * Sets alignment of the {@link Spannable} content within its bounds. Note that a {@link
+             * Spannable} element will size itself to wrap its contents, so this option is
+             * meaningless for single-line content (for that, use alignment of the outer container).
+             * For multi-line content, however, this will set the alignment of lines relative to the
+             * {@link Spannable} element bounds. If not defined, defaults to TEXT_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setMultilineAlignment(
+                    @NonNull HorizontalAlignmentProp multilineAlignment) {
+                mImpl.setMultilineAlignment(multilineAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(multilineAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets alignment of the {@link Spannable} content within its bounds. Note that a {@link
+             * Spannable} element will size itself to wrap its contents, so this option is
+             * meaningless for single-line content (for that, use alignment of the outer container).
+             * For multi-line content, however, this will set the alignment of lines relative to the
+             * {@link Spannable} element bounds. If not defined, defaults to TEXT_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setMultilineAlignment(@HorizontalAlignment int multilineAlignment) {
+                mImpl.setMultilineAlignment(
+                        AlignmentProto.HorizontalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.HorizontalAlignment.forNumber(
+                                                multilineAlignment)));
+                return this;
+            }
+
+            /**
+             * Sets how to handle content which overflows the bound of the {@link Spannable}
+             * element. A {@link Spannable} element will grow as large as possible inside its parent
+             * container (while still respecting max_lines); if it cannot grow large enough to
+             * render all of its content, the content which cannot fit inside its container will be
+             * truncated. If not defined, defaults to TEXT_OVERFLOW_TRUNCATE.
+             */
+            @NonNull
+            public Builder setOverflow(@NonNull TextOverflowProp overflow) {
+                mImpl.setOverflow(overflow.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(overflow.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets how to handle content which overflows the bound of the {@link Spannable}
+             * element. A {@link Spannable} element will grow as large as possible inside its parent
+             * container (while still respecting max_lines); if it cannot grow large enough to
+             * render all of its content, the content which cannot fit inside its container will be
+             * truncated. If not defined, defaults to TEXT_OVERFLOW_TRUNCATE.
+             */
+            @NonNull
+            public Builder setOverflow(@TextOverflow int overflow) {
+                mImpl.setOverflow(
+                        LayoutElementProto.TextOverflowProp.newBuilder()
+                                .setValue(LayoutElementProto.TextOverflow.forNumber(overflow)));
+                return this;
+            }
+
+            /**
+             * Sets the explicit height between lines of text. This is equivalent to the vertical
+             * distance between subsequent baselines. If not specified, defaults the font's
+             * recommended interline spacing.
+             */
+            @NonNull
+            public Builder setLineHeight(@NonNull SpProp lineHeight) {
+                mImpl.setLineHeight(lineHeight.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        7, checkNotNull(lineHeight.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Spannable build() {
+                return new Spannable(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A column of elements. Each child element will be laid out vertically, one after another (i.e.
+     * stacking down). This element will size itself to the smallest size required to hold all of
+     * its children (e.g. if it contains three elements sized 10x10, 20x20 and 30x30, the resulting
+     * column will be 30x60).
+     *
+     * <p>If specified, horizontal_alignment can be used to control the gravity inside the
+     * container, affecting the horizontal placement of children whose width are smaller than the
+     * resulting column width.
+     */
+    public static final class Column implements LayoutElement {
+        private final LayoutElementProto.Column mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Column(LayoutElementProto.Column impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the list of child elements to place inside this {@link Column}. Intended for testing
+         * purposes only.
+         */
+        @NonNull
+        public List<LayoutElement> getContents() {
+            List<LayoutElement> list = new ArrayList<>();
+            for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
+                list.add(LayoutElementBuilders.layoutElementFromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
+
+        /**
+         * Gets the horizontal alignment of elements inside this column, if they are narrower than
+         * the resulting width of the column. If not defined, defaults to HORIZONTAL_ALIGN_CENTER.
+         * Intended for testing purposes only.
+         */
+        @Nullable
+        public HorizontalAlignmentProp getHorizontalAlignment() {
+            if (mImpl.hasHorizontalAlignment()) {
+                return HorizontalAlignmentProp.fromProto(mImpl.getHorizontalAlignment());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the width of this column. If not defined, this will size itself to fit all of its
+         * children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getWidth() {
+            if (mImpl.hasWidth()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the height of this column. If not defined, this will size itself to fit all of its
+         * children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getHeight() {
+            if (mImpl.hasHeight()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Column fromProto(@NonNull LayoutElementProto.Column proto) {
+            return new Column(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Column toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setColumn(mImpl).build();
+        }
+
+        /** Builder for {@link Column}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Column.Builder mImpl =
+                    LayoutElementProto.Column.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1411218529);
+
+            public Builder() {}
+
+            /** Adds one item to the list of child elements to place inside this {@link Column}. */
+            @NonNull
+            public Builder addContent(@NonNull LayoutElement content) {
+                mImpl.addContents(content.toLayoutElementProto());
+                mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
+                return this;
+            }
+
+            /**
+             * Sets the horizontal alignment of elements inside this column, if they are narrower
+             * than the resulting width of the column. If not defined, defaults to
+             * HORIZONTAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setHorizontalAlignment(
+                    @NonNull HorizontalAlignmentProp horizontalAlignment) {
+                mImpl.setHorizontalAlignment(horizontalAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2,
+                        checkNotNull(horizontalAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the horizontal alignment of elements inside this column, if they are narrower
+             * than the resulting width of the column. If not defined, defaults to
+             * HORIZONTAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setHorizontalAlignment(@HorizontalAlignment int horizontalAlignment) {
+                mImpl.setHorizontalAlignment(
+                        AlignmentProto.HorizontalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.HorizontalAlignment.forNumber(
+                                                horizontalAlignment)));
+                return this;
+            }
+
+            /**
+             * Sets the width of this column. If not defined, this will size itself to fit all of
+             * its children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setWidth(@NonNull ContainerDimension width) {
+                mImpl.setWidth(width.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the height of this column. If not defined, this will size itself to fit all of
+             * its children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setHeight(@NonNull ContainerDimension height) {
+                mImpl.setHeight(height.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Column build() {
+                return new Column(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * A row of elements. Each child will be laid out horizontally, one after another (i.e. stacking
+     * to the right). This element will size itself to the smallest size required to hold all of its
+     * children (e.g. if it contains three elements sized 10x10, 20x20 and 30x30, the resulting row
+     * will be 60x30).
+     *
+     * <p>If specified, vertical_alignment can be used to control the gravity inside the container,
+     * affecting the vertical placement of children whose width are smaller than the resulting row
+     * height.
+     */
+    public static final class Row implements LayoutElement {
+        private final LayoutElementProto.Row mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Row(LayoutElementProto.Row impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the list of child elements to place inside this {@link Row}. Intended for testing
+         * purposes only.
+         */
+        @NonNull
+        public List<LayoutElement> getContents() {
+            List<LayoutElement> list = new ArrayList<>();
+            for (LayoutElementProto.LayoutElement item : mImpl.getContentsList()) {
+                list.add(LayoutElementBuilders.layoutElementFromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
+
+        /**
+         * Gets the vertical alignment of elements inside this row, if they are narrower than the
+         * resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public VerticalAlignmentProp getVerticalAlignment() {
+            if (mImpl.hasVerticalAlignment()) {
+                return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlignment());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the width of this row. If not defined, this will size itself to fit all of its
+         * children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getWidth() {
+            if (mImpl.hasWidth()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getWidth());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the height of this row. If not defined, this will size itself to fit all of its
+         * children (i.e. a WrappedDimension). Intended for testing purposes only.
+         */
+        @Nullable
+        public ContainerDimension getHeight() {
+            if (mImpl.hasHeight()) {
+                return DimensionBuilders.containerDimensionFromProto(mImpl.getHeight());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Row fromProto(@NonNull LayoutElementProto.Row proto) {
+            return new Row(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Row toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setRow(mImpl).build();
+        }
+
+        /** Builder for {@link Row}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Row.Builder mImpl =
+                    LayoutElementProto.Row.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1537205448);
+
+            public Builder() {}
+
+            /** Adds one item to the list of child elements to place inside this {@link Row}. */
+            @NonNull
+            public Builder addContent(@NonNull LayoutElement content) {
+                mImpl.addContents(content.toLayoutElementProto());
+                mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
+                return this;
+            }
+
+            /**
+             * Sets the vertical alignment of elements inside this row, if they are narrower than
+             * the resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlignment(@NonNull VerticalAlignmentProp verticalAlignment) {
+                mImpl.setVerticalAlignment(verticalAlignment.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(verticalAlignment.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the vertical alignment of elements inside this row, if they are narrower than
+             * the resulting height of the row. If not defined, defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlignment(@VerticalAlignment int verticalAlignment) {
+                mImpl.setVerticalAlignment(
+                        AlignmentProto.VerticalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.VerticalAlignment.forNumber(
+                                                verticalAlignment)));
+                return this;
+            }
+
+            /**
+             * Sets the width of this row. If not defined, this will size itself to fit all of its
+             * children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setWidth(@NonNull ContainerDimension width) {
+                mImpl.setWidth(width.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(width.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets the height of this row. If not defined, this will size itself to fit all of its
+             * children (i.e. a WrappedDimension).
+             */
+            @NonNull
+            public Builder setHeight(@NonNull ContainerDimension height) {
+                mImpl.setHeight(height.toContainerDimensionProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(height.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Row build() {
+                return new Row(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * 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.
+     */
+    public static final class Arc implements LayoutElement {
+        private final LayoutElementProto.Arc mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        Arc(LayoutElementProto.Arc impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets contents of this container. Intended for testing purposes only. */
+        @NonNull
+        public List<ArcLayoutElement> getContents() {
+            List<ArcLayoutElement> list = new ArrayList<>();
+            for (LayoutElementProto.ArcLayoutElement item : mImpl.getContentsList()) {
+                list.add(LayoutElementBuilders.arcLayoutElementFromProto(item));
+            }
+            return Collections.unmodifiableList(list);
+        }
+
+        /**
+         * Gets the angle for the anchor, used with anchor_type to determine where to draw children.
+         * Note that 0 degrees is the 12 o clock position on a device, and the angle sweeps
+         * clockwise. If not defined, defaults to 0 degrees.
+         *
+         * <p>Values do not have to be clamped to the range 0-360; values less than 0 degrees will
+         * sweep anti-clockwise (i.e. -90 degrees is equivalent to 270 degrees), and values >360
+         * will be be placed at X mod 360 degrees. Intended for testing purposes only.
+         */
+        @Nullable
+        public DegreesProp getAnchorAngle() {
+            if (mImpl.hasAnchorAngle()) {
+                return DegreesProp.fromProto(mImpl.getAnchorAngle());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets how to align the contents of this container relative to anchor_angle. If not
+         * defined, defaults to ARC_ANCHOR_CENTER. Intended for testing purposes only.
+         */
+        @Nullable
+        public ArcAnchorTypeProp getAnchorType() {
+            if (mImpl.hasAnchorType()) {
+                return ArcAnchorTypeProp.fromProto(mImpl.getAnchorType());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is
+         * larger than the thickness of the element being drawn, this controls whether the element
+         * should be drawn towards the inner or outer edge of the arc, or drawn in the center. If
+         * not defined, defaults to VERTICAL_ALIGN_CENTER. Intended for testing purposes only.
+         */
+        @Nullable
+        public VerticalAlignmentProp getVerticalAlign() {
+            if (mImpl.hasVerticalAlign()) {
+                return VerticalAlignmentProp.fromProto(mImpl.getVerticalAlign());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public Modifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return Modifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static Arc fromProto(@NonNull LayoutElementProto.Arc proto) {
+            return new Arc(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.Arc toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.LayoutElement toLayoutElementProto() {
+            return LayoutElementProto.LayoutElement.newBuilder().setArc(mImpl).build();
+        }
+
+        /** Builder for {@link Arc}. */
+        public static final class Builder implements LayoutElement.Builder {
+            private final LayoutElementProto.Arc.Builder mImpl =
+                    LayoutElementProto.Arc.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(299028337);
+
+            public Builder() {}
+
+            /** Adds one item to contents of this container. */
+            @NonNull
+            public Builder addContent(@NonNull ArcLayoutElement content) {
+                mImpl.addContents(content.toArcLayoutElementProto());
+                mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
+                return this;
+            }
+
+            /**
+             * Sets the angle for the anchor, used with anchor_type to determine where to draw
+             * children. Note that 0 degrees is the 12 o clock position on a device, and the angle
+             * sweeps clockwise. If not defined, defaults to 0 degrees.
+             *
+             * <p>Values do not have to be clamped to the range 0-360; values less than 0 degrees
+             * will sweep anti-clockwise (i.e. -90 degrees is equivalent to 270 degrees), and values
+             * >360 will be be placed at X mod 360 degrees.
+             */
+            @NonNull
+            public Builder setAnchorAngle(@NonNull DegreesProp anchorAngle) {
+                mImpl.setAnchorAngle(anchorAngle.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(anchorAngle.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets how to align the contents of this container relative to anchor_angle. If not
+             * defined, defaults to ARC_ANCHOR_CENTER.
+             */
+            @NonNull
+            public Builder setAnchorType(@NonNull ArcAnchorTypeProp anchorType) {
+                mImpl.setAnchorType(anchorType.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(anchorType.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets how to align the contents of this container relative to anchor_angle. If not
+             * defined, defaults to ARC_ANCHOR_CENTER.
+             */
+            @NonNull
+            public Builder setAnchorType(@ArcAnchorType int anchorType) {
+                mImpl.setAnchorType(
+                        AlignmentProto.ArcAnchorTypeProp.newBuilder()
+                                .setValue(AlignmentProto.ArcAnchorType.forNumber(anchorType)));
+                return this;
+            }
+
+            /**
+             * Sets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is
+             * larger than the thickness of the element being drawn, this controls whether the
+             * element should be drawn towards the inner or outer edge of the arc, or drawn in the
+             * center. If not defined, defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlign(@NonNull VerticalAlignmentProp verticalAlign) {
+                mImpl.setVerticalAlign(verticalAlign.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(verticalAlign.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+            /**
+             * Sets vertical alignment of elements within the arc. If the {@link Arc}'s thickness is
+             * larger than the thickness of the element being drawn, this controls whether the
+             * element should be drawn towards the inner or outer edge of the arc, or drawn in the
+             * center. If not defined, defaults to VERTICAL_ALIGN_CENTER.
+             */
+            @NonNull
+            public Builder setVerticalAlign(@VerticalAlignment int verticalAlign) {
+                mImpl.setVerticalAlign(
+                        AlignmentProto.VerticalAlignmentProp.newBuilder()
+                                .setValue(
+                                        AlignmentProto.VerticalAlignment.forNumber(verticalAlign)));
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull Modifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        5, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public Arc build() {
+                return new Arc(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A text element that can be used in an {@link Arc}. */
+    public static final class ArcText implements ArcLayoutElement {
+        private final LayoutElementProto.ArcText mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ArcText(LayoutElementProto.ArcText impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the text to render. Intended for testing purposes only. */
+        @Nullable
+        public StringProp getText() {
+            if (mImpl.hasText()) {
+                return StringProp.fromProto(mImpl.getText());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the style of font to use (size, bold etc). If not specified, defaults to the
+         * platform's default body font. Intended for testing purposes only.
+         */
+        @Nullable
+        public FontStyle getFontStyle() {
+            if (mImpl.hasFontStyle()) {
+                return FontStyle.fromProto(mImpl.getFontStyle());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public ArcModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return ArcModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ArcText fromProto(@NonNull LayoutElementProto.ArcText proto) {
+            return new ArcText(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ArcText toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
+            return LayoutElementProto.ArcLayoutElement.newBuilder().setText(mImpl).build();
+        }
+
+        /** Builder for {@link ArcText}. */
+        public static final class Builder implements ArcLayoutElement.Builder {
+            private final LayoutElementProto.ArcText.Builder mImpl =
+                    LayoutElementProto.ArcText.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(434391973);
+
+            public Builder() {}
+
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull StringProp text) {
+                mImpl.setText(text.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(text.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the text to render. */
+            @NonNull
+            public Builder setText(@NonNull String text) {
+                mImpl.setText(TypesProto.StringProp.newBuilder().setValue(text));
+                return this;
+            }
+
+            /**
+             * Sets the style of font to use (size, bold etc). If not specified, defaults to the
+             * platform's default body font.
+             */
+            @NonNull
+            public Builder setFontStyle(@NonNull FontStyle fontStyle) {
+                mImpl.setFontStyle(fontStyle.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(fontStyle.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull ArcModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ArcText build() {
+                return new ArcText(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A line that can be used in an {@link Arc} and renders as a round progress bar. */
+    public static final class ArcLine implements ArcLayoutElement {
+        private final LayoutElementProto.ArcLine mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ArcLine(LayoutElementProto.ArcLine impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the length of this line, in degrees. If not defined, defaults to 0. Intended for
+         * testing purposes only.
+         */
+        @Nullable
+        public DegreesProp getLength() {
+            if (mImpl.hasLength()) {
+                return DegreesProp.fromProto(mImpl.getLength());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the thickness of this line. If not defined, defaults to 0. Intended for testing
+         * purposes only.
+         */
+        @Nullable
+        public DpProp getThickness() {
+            if (mImpl.hasThickness()) {
+                return DpProp.fromProto(mImpl.getThickness());
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the color of this line. Intended for testing purposes only. */
+        @Nullable
+        public ColorProp getColor() {
+            if (mImpl.hasColor()) {
+                return ColorProp.fromProto(mImpl.getColor());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public ArcModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return ArcModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ArcLine fromProto(@NonNull LayoutElementProto.ArcLine proto) {
+            return new ArcLine(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ArcLine toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
+            return LayoutElementProto.ArcLayoutElement.newBuilder().setLine(mImpl).build();
+        }
+
+        /** Builder for {@link ArcLine}. */
+        public static final class Builder implements ArcLayoutElement.Builder {
+            private final LayoutElementProto.ArcLine.Builder mImpl =
+                    LayoutElementProto.ArcLine.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-1371793535);
+
+            public Builder() {}
+
+            /** Sets the length of this line, in degrees. If not defined, defaults to 0. */
+            @NonNull
+            public Builder setLength(@NonNull DegreesProp length) {
+                mImpl.setLength(length.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(length.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the thickness of this line. If not defined, defaults to 0. */
+            @NonNull
+            public Builder setThickness(@NonNull DpProp thickness) {
+                mImpl.setThickness(thickness.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(thickness.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the color of this line. */
+            @NonNull
+            public Builder setColor(@NonNull ColorProp color) {
+                mImpl.setColor(color.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(color.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull ArcModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        4, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ArcLine build() {
+                return new ArcLine(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A simple spacer used to provide padding between adjacent elements in an {@link Arc}. */
+    public static final class ArcSpacer implements ArcLayoutElement {
+        private final LayoutElementProto.ArcSpacer mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ArcSpacer(LayoutElementProto.ArcSpacer impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /**
+         * Gets the length of this spacer, in degrees. If not defined, defaults to 0. Intended for
+         * testing purposes only.
+         */
+        @Nullable
+        public DegreesProp getLength() {
+            if (mImpl.hasLength()) {
+                return DegreesProp.fromProto(mImpl.getLength());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets the thickness of this spacer, in DP. If not defined, defaults to 0. Intended for
+         * testing purposes only.
+         */
+        @Nullable
+        public DpProp getThickness() {
+            if (mImpl.hasThickness()) {
+                return DpProp.fromProto(mImpl.getThickness());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Gets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. Intended
+         * for testing purposes only.
+         */
+        @Nullable
+        public ArcModifiers getModifiers() {
+            if (mImpl.hasModifiers()) {
+                return ArcModifiers.fromProto(mImpl.getModifiers());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ArcSpacer fromProto(@NonNull LayoutElementProto.ArcSpacer proto) {
+            return new ArcSpacer(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ArcSpacer toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
+            return LayoutElementProto.ArcLayoutElement.newBuilder().setSpacer(mImpl).build();
+        }
+
+        /** Builder for {@link ArcSpacer}. */
+        public static final class Builder implements ArcLayoutElement.Builder {
+            private final LayoutElementProto.ArcSpacer.Builder mImpl =
+                    LayoutElementProto.ArcSpacer.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-179760535);
+
+            public Builder() {}
+
+            /** Sets the length of this spacer, in degrees. If not defined, defaults to 0. */
+            @NonNull
+            public Builder setLength(@NonNull DegreesProp length) {
+                mImpl.setLength(length.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        1, checkNotNull(length.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets the thickness of this spacer, in DP. If not defined, defaults to 0. */
+            @NonNull
+            public Builder setThickness(@NonNull DpProp thickness) {
+                mImpl.setThickness(thickness.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(thickness.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /** Sets {@link androidx.wear.tiles.ModifiersBuilders.Modifiers} for this element. */
+            @NonNull
+            public Builder setModifiers(@NonNull ArcModifiers modifiers) {
+                mImpl.setModifiers(modifiers.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        3, checkNotNull(modifiers.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ArcSpacer build() {
+                return new ArcSpacer(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /** A container that allows a standard {@link LayoutElement} to be added to an {@link Arc}. */
+    public static final class ArcAdapter implements ArcLayoutElement {
+        private final LayoutElementProto.ArcAdapter mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ArcAdapter(LayoutElementProto.ArcAdapter impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the element to adapt to an {@link Arc}. Intended for testing purposes only. */
+        @Nullable
+        public LayoutElement getContent() {
+            if (mImpl.hasContent()) {
+                return LayoutElementBuilders.layoutElementFromProto(mImpl.getContent());
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * 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. Intended for testing purposes
+         * only.
+         */
+        @Nullable
+        public BoolProp getRotateContents() {
+            if (mImpl.hasRotateContents()) {
+                return BoolProp.fromProto(mImpl.getRotateContents());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ArcAdapter fromProto(@NonNull LayoutElementProto.ArcAdapter proto) {
+            return new ArcAdapter(proto, null);
+        }
+
+        @NonNull
+        LayoutElementProto.ArcAdapter toProto() {
+            return mImpl;
+        }
+
+        @Override
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.ArcLayoutElement toArcLayoutElementProto() {
+            return LayoutElementProto.ArcLayoutElement.newBuilder().setAdapter(mImpl).build();
+        }
+
+        /** Builder for {@link ArcAdapter}. */
+        public static final class Builder implements ArcLayoutElement.Builder {
+            private final LayoutElementProto.ArcAdapter.Builder mImpl =
+                    LayoutElementProto.ArcAdapter.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1696473935);
+
+            public Builder() {}
+
+            /** Sets the element to adapt to an {@link Arc}. */
+            @NonNull
+            public Builder setContent(@NonNull LayoutElement content) {
+                mImpl.setContent(content.toLayoutElementProto());
+                mFingerprint.addChildNode(checkNotNull(content.getFingerprint()));
+                return this;
+            }
+
+            /**
+             * Sets 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.
+             */
+            @NonNull
+            public Builder setRotateContents(@NonNull BoolProp rotateContents) {
+                mImpl.setRotateContents(rotateContents.toProto());
+                mFingerprint.recordPropertyUpdate(
+                        2, checkNotNull(rotateContents.getFingerprint()).aggregateValueAsInt());
+                return this;
+            }
+
+            /**
+             * Sets 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.
+             */
+            @SuppressLint("MissingGetterMatchingBuilder")
+            @NonNull
+            public Builder setRotateContents(boolean rotateContents) {
+                mImpl.setRotateContents(TypesProto.BoolProp.newBuilder().setValue(rotateContents));
+                return this;
+            }
+
+            @Override
+            @NonNull
+            public ArcAdapter build() {
+                return new ArcAdapter(mImpl.build(), mFingerprint);
+            }
+        }
+    }
+
+    /**
+     * Interface defining the root of all layout elements. This exists to act as a holder for all of
+     * the actual layout elements above.
+     */
+    public interface LayoutElement {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        LayoutElementProto.LayoutElement toLayoutElementProto();
+
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
+
+        /** Builder to create {@link LayoutElement} objects. */
+        @SuppressLint("StaticFinalBuilder")
+        interface Builder {
+
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            LayoutElement build();
+        }
     }
 
     @NonNull
-    AlignmentProto.ArcAnchorTypeProp toProto() {
-      return mImpl;
+    static LayoutElement layoutElementFromProto(@NonNull LayoutElementProto.LayoutElement proto) {
+        if (proto.hasColumn()) {
+            return Column.fromProto(proto.getColumn());
+        }
+        if (proto.hasRow()) {
+            return Row.fromProto(proto.getRow());
+        }
+        if (proto.hasBox()) {
+            return Box.fromProto(proto.getBox());
+        }
+        if (proto.hasSpacer()) {
+            return Spacer.fromProto(proto.getSpacer());
+        }
+        if (proto.hasText()) {
+            return Text.fromProto(proto.getText());
+        }
+        if (proto.hasImage()) {
+            return Image.fromProto(proto.getImage());
+        }
+        if (proto.hasArc()) {
+            return Arc.fromProto(proto.getArc());
+        }
+        if (proto.hasSpannable()) {
+            return Spannable.fromProto(proto.getSpannable());
+        }
+        throw new IllegalStateException("Proto was not a recognised instance of LayoutElement");
     }
 
-    /** Builder for {@link ArcAnchorTypeProp} */
-    public static final class Builder {
-      private final AlignmentProto.ArcAnchorTypeProp.Builder mImpl =
-          AlignmentProto.ArcAnchorTypeProp.newBuilder();
-      private final Fingerprint mFingerprint = new Fingerprint(1193249074);
+    /**
+     * Interface defining the root of all elements that can be used in an {@link Arc}. This exists
+     * to act as a holder for all of the actual arc layout elements above.
+     */
+    public interface ArcLayoutElement {
+        /** Get the protocol buffer representation of this object. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        LayoutElementProto.ArcLayoutElement toArcLayoutElementProto();
 
-      public Builder() {}
+        /** Get the fingerprint for this object or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        Fingerprint getFingerprint();
 
-      /** Sets the value. */
-      @NonNull
-      public Builder setValue(@ArcAnchorType int value) {
-        mImpl.setValue(AlignmentProto.ArcAnchorType.forNumber(value));
-        mFingerprint.recordPropertyUpdate(1, value);
-        return this;
-      }
+        /** Builder to create {@link ArcLayoutElement} objects. */
+        @SuppressLint("StaticFinalBuilder")
+        interface Builder {
 
-      /** Builds an instance from accumulated values. */
-      @NonNull
-      public ArcAnchorTypeProp build() {
-        return new ArcAnchorTypeProp(mImpl.build(), mFingerprint);
-      }
-    }
-  }
-
-  /** Font styles, currently set up to match Wear's font styling. */
-  public static class FontStyles {
-    private static final int LARGE_SCREEN_WIDTH_DP = 210;
-
-    private FontStyles() {
+            /** Builds an instance with values accumulated in this Builder. */
+            @NonNull
+            ArcLayoutElement build();
+        }
     }
 
-    private static boolean isLargeScreen(@NonNull DeviceParameters deviceParameters) {
-      return deviceParameters.getScreenWidthDp() >= LARGE_SCREEN_WIDTH_DP;
-    }
-
-    /** Font style for large display text. */
     @NonNull
-    public static FontStyle.Builder display1(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 54 : 50));
+    static ArcLayoutElement arcLayoutElementFromProto(
+            @NonNull LayoutElementProto.ArcLayoutElement proto) {
+        if (proto.hasText()) {
+            return ArcText.fromProto(proto.getText());
+        }
+        if (proto.hasLine()) {
+            return ArcLine.fromProto(proto.getLine());
+        }
+        if (proto.hasSpacer()) {
+            return ArcSpacer.fromProto(proto.getSpacer());
+        }
+        if (proto.hasAdapter()) {
+            return ArcAdapter.fromProto(proto.getAdapter());
+        }
+        throw new IllegalStateException("Proto was not a recognised instance of ArcLayoutElement");
     }
 
-    /** Font style for medium display text. */
-    @NonNull
-    public static FontStyle.Builder display2(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 44 : 40));
+    /** A complete layout. */
+    public static final class Layout {
+        private final LayoutElementProto.Layout mImpl;
+
+        private Layout(LayoutElementProto.Layout impl) {
+            this.mImpl = impl;
+        }
+
+        /** Gets the root element in the layout. Intended for testing purposes only. */
+        @Nullable
+        public LayoutElement getRoot() {
+            if (mImpl.hasRoot()) {
+                return LayoutElementBuilders.layoutElementFromProto(mImpl.getRoot());
+            } else {
+                return null;
+            }
+        }
+
+        /** Creates a {@link Layout} object containing the given layout element. */
+        @NonNull
+        public static Layout fromLayoutElement(@NonNull LayoutElement layoutElement) {
+            return new Builder().setRoot(layoutElement).build();
+        }
+
+        /** Converts to byte array representation. */
+        @NonNull
+        @ProtoLayoutExperimental
+        public byte[] toByteArray() {
+            return mImpl.toByteArray();
+        }
+
+        /** Converts from byte array representation. */
+        @SuppressWarnings("ProtoParseWithRegistry")
+        @Nullable
+        @ProtoLayoutExperimental
+        public static Layout fromByteArray(@NonNull byte[] byteArray) {
+            try {
+                return fromProto(LayoutElementProto.Layout.parseFrom(byteArray));
+            } catch (InvalidProtocolBufferException e) {
+                return null;
+            }
+        }
+
+        @NonNull
+        static Layout fromProto(@NonNull LayoutElementProto.Layout proto) {
+            return new Layout(proto);
+        }
+
+        /** Returns the internal proto instance. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @NonNull
+        public LayoutElementProto.Layout toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link Layout} */
+        public static final class Builder {
+            private final LayoutElementProto.Layout.Builder mImpl =
+                    LayoutElementProto.Layout.newBuilder();
+
+            public Builder() {}
+
+            /** Sets the root element in the layout. */
+            @NonNull
+            public Builder setRoot(@NonNull LayoutElement root) {
+                mImpl.setRoot(root.toLayoutElementProto());
+                @Nullable Fingerprint fingerprint = root.getFingerprint();
+                if (fingerprint != null) {
+                    mImpl.setFingerprint(
+                            TreeFingerprint.newBuilder().setRoot(fingerprintToProto(fingerprint)));
+                }
+                return this;
+            }
+
+            private static FingerprintProto.NodeFingerprint fingerprintToProto(
+                    Fingerprint fingerprint) {
+                FingerprintProto.NodeFingerprint.Builder builder =
+                        FingerprintProto.NodeFingerprint.newBuilder();
+                if (fingerprint.selfTypeValue() != 0) {
+                    builder.setSelfTypeValue(fingerprint.selfTypeValue());
+                }
+                if (fingerprint.selfPropsValue() != 0) {
+                    builder.setSelfPropsValue(fingerprint.selfPropsValue());
+                }
+                if (fingerprint.childNodesValue() != 0) {
+                    builder.setChildNodesValue(fingerprint.childNodesValue());
+                }
+                for (Fingerprint childNode : fingerprint.childNodes()) {
+                    builder.addChildNodes(fingerprintToProto(childNode));
+                }
+                return builder.build();
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public Layout build() {
+                return Layout.fromProto(mImpl.build());
+            }
+        }
     }
 
-    /** Font style for small display text. */
-    @NonNull
-    public static FontStyle.Builder display3(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 34 : 30));
+    /** The horizontal alignment of an element within its container. */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+        HORIZONTAL_ALIGN_UNDEFINED,
+        HORIZONTAL_ALIGN_LEFT,
+        HORIZONTAL_ALIGN_CENTER,
+        HORIZONTAL_ALIGN_RIGHT,
+        HORIZONTAL_ALIGN_START,
+        HORIZONTAL_ALIGN_END
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface HorizontalAlignment {}
+
+    /** Horizontal alignment is undefined. */
+    public static final int HORIZONTAL_ALIGN_UNDEFINED = 0;
+
+    /** Horizontally align to the left. */
+    public static final int HORIZONTAL_ALIGN_LEFT = 1;
+
+    /** Horizontally align to center. */
+    public static final int HORIZONTAL_ALIGN_CENTER = 2;
+
+    /** Horizontally align to the right. */
+    public static final int HORIZONTAL_ALIGN_RIGHT = 3;
+
+    /** Horizontally align to the content start (left in LTR layouts, right in RTL layouts). */
+    public static final int HORIZONTAL_ALIGN_START = 4;
+
+    /** Horizontally align to the content end (right in LTR layouts, left in RTL layouts). */
+    public static final int HORIZONTAL_ALIGN_END = 5;
+
+    /** The vertical alignment of an element within its container. */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+        VERTICAL_ALIGN_UNDEFINED,
+        VERTICAL_ALIGN_TOP,
+        VERTICAL_ALIGN_CENTER,
+        VERTICAL_ALIGN_BOTTOM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface VerticalAlignment {}
+
+    /** Vertical alignment is undefined. */
+    public static final int VERTICAL_ALIGN_UNDEFINED = 0;
+
+    /** Vertically align to the top. */
+    public static final int VERTICAL_ALIGN_TOP = 1;
+
+    /** Vertically align to center. */
+    public static final int VERTICAL_ALIGN_CENTER = 2;
+
+    /** Vertically align to the bottom. */
+    public static final int VERTICAL_ALIGN_BOTTOM = 3;
+
+    /** Alignment of a text element. */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({TEXT_ALIGN_UNDEFINED, TEXT_ALIGN_START, TEXT_ALIGN_CENTER, TEXT_ALIGN_END})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TextAlignment {}
+
+    /** Alignment is undefined. */
+    public static final int TEXT_ALIGN_UNDEFINED = 0;
+
+    /**
+     * Align to the "start" of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element
+     * (left in LTR layouts, right in RTL layouts).
+     */
+    public static final int TEXT_ALIGN_START = 1;
+
+    /**
+     * Align to the center of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element.
+     */
+    public static final int TEXT_ALIGN_CENTER = 2;
+
+    /**
+     * Align to the "end" of the {@link androidx.wear.tiles.LayoutElementBuilders.Text} element
+     * (right in LTR layouts, left in RTL layouts).
+     */
+    public static final int TEXT_ALIGN_END = 3;
+
+    /**
+     * The anchor position of an {@link androidx.wear.tiles.LayoutElementBuilders.Arc}'s elements.
+     * This is used to specify how elements added to an {@link
+     * androidx.wear.tiles.LayoutElementBuilders.Arc} should be laid out with respect to
+     * anchor_angle.
+     *
+     * <p>As an example, assume that the following diagrams are wrapped to an arc, and each
+     * represents an {@link androidx.wear.tiles.LayoutElementBuilders.Arc} element containing a
+     * single {@link androidx.wear.tiles.LayoutElementBuilders.Text} element. The {@link
+     * androidx.wear.tiles.LayoutElementBuilders.Text} element's anchor_angle is "0" for all cases.
+     *
+     * <pre>{@code
+     * ARC_ANCHOR_START:
+     * -180                                0                                    180
+     *                                     Hello World!
+     *
+     *
+     * ARC_ANCHOR_CENTER:
+     * -180                                0                                    180
+     *                                Hello World!
+     *
+     * ARC_ANCHOR_END:
+     * -180                                0                                    180
+     *                          Hello World!
+     *
+     * }</pre>
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({ARC_ANCHOR_UNDEFINED, ARC_ANCHOR_START, ARC_ANCHOR_CENTER, ARC_ANCHOR_END})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ArcAnchorType {}
+
+    /** Anchor position is undefined. */
+    public static final int ARC_ANCHOR_UNDEFINED = 0;
+
+    /**
+     * Anchor at the start of the elements. This will cause elements added to an arc to begin at the
+     * given anchor_angle, and sweep around to the right.
+     */
+    public static final int ARC_ANCHOR_START = 1;
+
+    /**
+     * Anchor at the center of the elements. This will cause the center of the whole set of elements
+     * added to an arc to be pinned at the given anchor_angle.
+     */
+    public static final int ARC_ANCHOR_CENTER = 2;
+
+    /**
+     * Anchor at the end of the elements. This will cause the set of elements inside the arc to end
+     * at the specified anchor_angle, i.e. all elements should be to the left of anchor_angle.
+     */
+    public static final int ARC_ANCHOR_END = 3;
+
+    /**
+     * How to lay out components in a {@link androidx.wear.protolayout.LayoutElementBuilders.Arc}
+     * context when they are smaller than their container. This would be similar to {@code
+     * HorizontalAlignment} in a {@link androidx.wear.protolayout.LayoutElementBuilders.Box} or
+     * {@link androidx.wear.protolayout.LayoutElementBuilders.Column}.
+     *
+     * @since 1.2
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+        ANGULAR_ALIGNMENT_UNDEFINED,
+        ANGULAR_ALIGNMENT_START,
+        ANGULAR_ALIGNMENT_CENTER,
+        ANGULAR_ALIGNMENT_END
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AngularAlignment {}
+
+    /**
+     * Angular alignment is undefined.
+     *
+     * @since 1.2
+     */
+    public static final int ANGULAR_ALIGNMENT_UNDEFINED = 0;
+
+    /**
+     * Align to the start of the container. As an example, if the container starts at 90 degrees and
+     * has 180 degrees of sweep, the element within would draw from 90 degrees, clockwise.
+     *
+     * @since 1.2
+     */
+    public static final int ANGULAR_ALIGNMENT_START = 1;
+
+    /**
+     * Align to the center of the container. As an example, if the container starts at 90 degrees,
+     * and has 180 degrees of sweep, and the contained element has 90 degrees of sweep, the element
+     * would draw between 135 and 225 degrees.
+     *
+     * @since 1.2
+     */
+    public static final int ANGULAR_ALIGNMENT_CENTER = 2;
+
+    /**
+     * Align to the end of the container. As an example, if the container starts at 90 degrees and
+     * has 180 degrees of sweep, and the contained element has 90 degrees of sweep, the element
+     * would draw between 180 and 270 degrees.
+     *
+     * @since 1.2
+     */
+    public static final int ANGULAR_ALIGNMENT_END = 3;
+
+    /** An extensible {@code HorizontalAlignment} property. */
+    public static final class HorizontalAlignmentProp {
+        private final AlignmentProto.HorizontalAlignmentProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        HorizontalAlignmentProp(
+                AlignmentProto.HorizontalAlignmentProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @HorizontalAlignment
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static HorizontalAlignmentProp fromProto(
+                @NonNull AlignmentProto.HorizontalAlignmentProp proto) {
+            return new HorizontalAlignmentProp(proto, null);
+        }
+
+        @NonNull
+        AlignmentProto.HorizontalAlignmentProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link HorizontalAlignmentProp} */
+        public static final class Builder {
+            private final AlignmentProto.HorizontalAlignmentProp.Builder mImpl =
+                    AlignmentProto.HorizontalAlignmentProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(-384830516);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@HorizontalAlignment int value) {
+                mImpl.setValue(AlignmentProto.HorizontalAlignment.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public HorizontalAlignmentProp build() {
+                return new HorizontalAlignmentProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    /** Font style for large title text. */
-    @NonNull
-    public static FontStyle.Builder title1(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 26 : 24));
+    /** An extensible {@code VerticalAlignment} property. */
+    public static final class VerticalAlignmentProp {
+        private final AlignmentProto.VerticalAlignmentProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        VerticalAlignmentProp(
+                AlignmentProto.VerticalAlignmentProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @VerticalAlignment
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static VerticalAlignmentProp fromProto(
+                @NonNull AlignmentProto.VerticalAlignmentProp proto) {
+            return new VerticalAlignmentProp(proto, null);
+        }
+
+        @NonNull
+        AlignmentProto.VerticalAlignmentProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link VerticalAlignmentProp} */
+        public static final class Builder {
+            private final AlignmentProto.VerticalAlignmentProp.Builder mImpl =
+                    AlignmentProto.VerticalAlignmentProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1443510393);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@VerticalAlignment int value) {
+                mImpl.setValue(AlignmentProto.VerticalAlignment.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public VerticalAlignmentProp build() {
+                return new VerticalAlignmentProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    /** Font style for medium title text. */
-    @NonNull
-    public static FontStyle.Builder title2(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 22 : 20));
+    /** An extensible {@code TextAlignment} property. */
+    public static final class TextAlignmentProp {
+        private final AlignmentProto.TextAlignmentProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        TextAlignmentProp(
+                AlignmentProto.TextAlignmentProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @TextAlignment
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static TextAlignmentProp fromProto(@NonNull AlignmentProto.TextAlignmentProp proto) {
+            return new TextAlignmentProp(proto, null);
+        }
+
+        @NonNull
+        AlignmentProto.TextAlignmentProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link TextAlignmentProp} */
+        public static final class Builder {
+            private final AlignmentProto.TextAlignmentProp.Builder mImpl =
+                    AlignmentProto.TextAlignmentProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(797507251);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@TextAlignment int value) {
+                mImpl.setValue(AlignmentProto.TextAlignment.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public TextAlignmentProp build() {
+                return new TextAlignmentProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    /** Font style for small title text. */
-    @NonNull
-    public static FontStyle.Builder title3(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 18 : 16));
+    /** An extensible {@code ArcAnchorType} property. */
+    public static final class ArcAnchorTypeProp {
+        private final AlignmentProto.ArcAnchorTypeProp mImpl;
+        @Nullable private final Fingerprint mFingerprint;
+
+        ArcAnchorTypeProp(
+                AlignmentProto.ArcAnchorTypeProp impl, @Nullable Fingerprint fingerprint) {
+            this.mImpl = impl;
+            this.mFingerprint = fingerprint;
+        }
+
+        /** Gets the value. Intended for testing purposes only. */
+        @ArcAnchorType
+        public int getValue() {
+            return mImpl.getValue().getNumber();
+        }
+
+        /** Get the fingerprint for this object, or null if unknown. */
+        @RestrictTo(Scope.LIBRARY_GROUP)
+        @Nullable
+        public Fingerprint getFingerprint() {
+            return mFingerprint;
+        }
+
+        @NonNull
+        static ArcAnchorTypeProp fromProto(@NonNull AlignmentProto.ArcAnchorTypeProp proto) {
+            return new ArcAnchorTypeProp(proto, null);
+        }
+
+        @NonNull
+        AlignmentProto.ArcAnchorTypeProp toProto() {
+            return mImpl;
+        }
+
+        /** Builder for {@link ArcAnchorTypeProp} */
+        public static final class Builder {
+            private final AlignmentProto.ArcAnchorTypeProp.Builder mImpl =
+                    AlignmentProto.ArcAnchorTypeProp.newBuilder();
+            private final Fingerprint mFingerprint = new Fingerprint(1193249074);
+
+            public Builder() {}
+
+            /** Sets the value. */
+            @NonNull
+            public Builder setValue(@ArcAnchorType int value) {
+                mImpl.setValue(AlignmentProto.ArcAnchorType.forNumber(value));
+                mFingerprint.recordPropertyUpdate(1, value);
+                return this;
+            }
+
+            /** Builds an instance from accumulated values. */
+            @NonNull
+            public ArcAnchorTypeProp build() {
+                return new ArcAnchorTypeProp(mImpl.build(), mFingerprint);
+            }
+        }
     }
 
-    /** Font style for large body text. */
-    @NonNull
-    public static FontStyle.Builder body1(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 18 : 16));
-    }
+    /** Font styles, currently set up to match Wear's font styling. */
+    public static class FontStyles {
+        private static final int LARGE_SCREEN_WIDTH_DP = 210;
 
-    /** Font style for medium body text. */
-    @NonNull
-    public static FontStyle.Builder body2(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
-    }
+        private FontStyles() {}
 
-    /** Font style for button text. */
-    @NonNull
-    public static FontStyle.Builder button(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setWeight(FONT_WEIGHT_BOLD)
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
-    }
+        private static boolean isLargeScreen(@NonNull DeviceParameters deviceParameters) {
+            return deviceParameters.getScreenWidthDp() >= LARGE_SCREEN_WIDTH_DP;
+        }
 
-    /** Font style for large caption text. */
-    @NonNull
-    public static FontStyle.Builder caption1(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
-    }
+        /** Font style for large display text. */
+        @NonNull
+        public static FontStyle.Builder display1(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 54 : 50));
+        }
 
-    /** Font style for medium caption text. */
-    @NonNull
-    public static FontStyle.Builder caption2(@NonNull DeviceParameters deviceParameters) {
-      return new FontStyle.Builder()
-              .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 14 : 12));
-    }
-  }
+        /** Font style for medium display text. */
+        @NonNull
+        public static FontStyle.Builder display2(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 44 : 40));
+        }
 
+        /** Font style for small display text. */
+        @NonNull
+        public static FontStyle.Builder display3(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 34 : 30));
+        }
+
+        /** Font style for large title text. */
+        @NonNull
+        public static FontStyle.Builder title1(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 26 : 24));
+        }
+
+        /** Font style for medium title text. */
+        @NonNull
+        public static FontStyle.Builder title2(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 22 : 20));
+        }
+
+        /** Font style for small title text. */
+        @NonNull
+        public static FontStyle.Builder title3(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 18 : 16));
+        }
+
+        /** Font style for large body text. */
+        @NonNull
+        public static FontStyle.Builder body1(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 18 : 16));
+        }
+
+        /** Font style for medium body text. */
+        @NonNull
+        public static FontStyle.Builder body2(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
+        }
+
+        /** Font style for button text. */
+        @NonNull
+        public static FontStyle.Builder button(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setWeight(FONT_WEIGHT_BOLD)
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
+        }
+
+        /** Font style for large caption text. */
+        @NonNull
+        public static FontStyle.Builder caption1(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 16 : 14));
+        }
+
+        /** Font style for medium caption text. */
+        @NonNull
+        public static FontStyle.Builder caption2(@NonNull DeviceParameters deviceParameters) {
+            return new FontStyle.Builder()
+                    .setSize(DimensionBuilders.sp(isLargeScreen(deviceParameters) ? 14 : 12));
+        }
+    }
 }
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ColorBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ColorBuildersTest.java
index d83ef0d..078ae25 100644
--- a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ColorBuildersTest.java
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ColorBuildersTest.java
@@ -52,7 +52,7 @@
     }
 
     @Test
-    public void borderSetColor_withoutStaticValue_throws() {
+    public void colorProp_withoutStaticValue_throws() {
         assertThrows(IllegalStateException.class, COLOR_BUILDER_WITHOUT_STATIC_VALUE::build);
     }
 }
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java
index 2f54d7b..81f3b67 100644
--- a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/DimensionBuildersTest.java
@@ -16,8 +16,13 @@
 
 package androidx.wear.protolayout;
 
+import static androidx.wear.protolayout.DimensionBuilders.dp;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertThrows;
+
+import androidx.wear.protolayout.expression.DynamicBuilders;
 import androidx.wear.protolayout.proto.DimensionProto;
 
 import org.junit.Test;
@@ -26,31 +31,94 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class DimensionBuildersTest {
+    private static final String STATE_KEY = "state-key";
+    private static final DimensionBuilders.DpProp DP_PROP =
+            new DimensionBuilders.DpProp.Builder(3.14f)
+                    .setDynamicValue(DynamicBuilders.DynamicFloat.fromState(STATE_KEY))
+                    .build();
+
+    @SuppressWarnings("deprecation")
+    private static final DimensionBuilders.DpProp.Builder DP_PROP_WITHOUT_STATIC_VALUE =
+            new DimensionBuilders.DpProp.Builder()
+                    .setDynamicValue(DynamicBuilders.DynamicFloat.fromState(STATE_KEY));
+
+    private static final DimensionBuilders.DegreesProp DEGREES_PROP =
+            new DimensionBuilders.DegreesProp.Builder(3.14f)
+                    .setDynamicValue(DynamicBuilders.DynamicFloat.fromState(STATE_KEY))
+                    .build();
+
+    @SuppressWarnings("deprecation")
+    private static final DimensionBuilders.DegreesProp.Builder DEGREES_PROP_WITHOUT_STATIC_VALUE =
+            new DimensionBuilders.DegreesProp.Builder()
+                    .setDynamicValue(DynamicBuilders.DynamicFloat.fromState(STATE_KEY));
+
+    @Test
+    public void dpPropSupportsDynamicValue() {
+        DimensionProto.DpProp dpPropProto = DP_PROP.toProto();
+
+        assertThat(dpPropProto.getValue()).isEqualTo(DP_PROP.getValue());
+        assertThat(dpPropProto.getDynamicValue().getStateSource().getSourceKey())
+                .isEqualTo(STATE_KEY);
+    }
+
+    @Test
+    public void dpProp_withoutStaticValue_throws() {
+        assertThrows(IllegalStateException.class, DP_PROP_WITHOUT_STATIC_VALUE::build);
+    }
+
+    public void degreesPropSupportsDynamicValue() {
+        DimensionProto.DegreesProp degreesPropProto = DEGREES_PROP.toProto();
+
+        assertThat(degreesPropProto.getValue()).isEqualTo(DEGREES_PROP.getValue());
+        assertThat(degreesPropProto.getDynamicValue().getStateSource().getSourceKey())
+                .isEqualTo(STATE_KEY);
+    }
+
+    @Test
+    public void degreesProp_withoutStaticValue_throws() {
+        assertThrows(IllegalStateException.class, DEGREES_PROP_WITHOUT_STATIC_VALUE::build);
+    }
 
     @Test
     public void expandedLayoutWeight() {
-        float layoutWeight = 3.14f;
+        TypeBuilders.FloatProp layoutWeight =
+                new TypeBuilders.FloatProp.Builder().setValue(3.14f).build();
         DimensionBuilders.ContainerDimension dimensionProp =
-                new DimensionBuilders.ExpandedDimensionProp.Builder().setLayoutWeight(layoutWeight)
+                new DimensionBuilders.ExpandedDimensionProp.Builder()
+                        .setLayoutWeight(layoutWeight)
                         .build();
 
         DimensionProto.ContainerDimension dimensionProto =
                 dimensionProp.toContainerDimensionProto();
         assertThat(dimensionProto.getExpandedDimension().getLayoutWeight().getValue())
-                .isWithin(.001f).of(layoutWeight);
+                .isWithin(.001f)
+                .of(layoutWeight.getValue());
     }
 
-
     @Test
     public void wrappedMinSize() {
-        int minSizeDp = 42;
+        DimensionBuilders.DpProp minSize = dp(42);
         DimensionBuilders.ContainerDimension dimensionProp =
-                new DimensionBuilders.WrappedDimensionProp.Builder().setMinimumSizeDp(minSizeDp)
+                new DimensionBuilders.WrappedDimensionProp.Builder()
+                        .setMinimumSize(minSize)
                         .build();
 
         DimensionProto.ContainerDimension dimensionProto =
                 dimensionProp.toContainerDimensionProto();
         assertThat(dimensionProto.getWrappedDimension().getMinimumSize().getValue())
-                .isEqualTo(minSizeDp);
+                .isEqualTo(minSize.getValue());
+    }
+
+    @Test
+    public void wrappedMinSize_throwsWhenSetToDynamicValue() {
+        DimensionBuilders.DpProp minSizeDynamic =
+                new DimensionBuilders.DpProp.Builder(42)
+                        .setDynamicValue(DynamicBuilders.DynamicFloat.fromState("some-state"))
+                        .build();
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->
+                        new DimensionBuilders.WrappedDimensionProp.Builder()
+                                .setMinimumSize(minSizeDynamic));
     }
 }
diff --git a/wear/tiles/tiles-material/api/current.txt b/wear/tiles/tiles-material/api/current.txt
index aecb80e..a798a8f 100644
--- a/wear/tiles/tiles-material/api/current.txt
+++ b/wear/tiles/tiles-material/api/current.txt
@@ -1,297 +1,297 @@
 // Signature format: 4.0
 package androidx.wear.tiles.material {
 
-  public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Button? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ButtonColors getButtonColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public String? getIconContent();
-    method public String? getImageContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize();
-    method public String? getTextContent();
+  @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();
   }
 
-  public static final class Button.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Button.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable);
-    method public androidx.wear.tiles.material.Button build();
-    method public androidx.wear.tiles.material.Button.Builder setButtonColors(androidx.wear.tiles.material.ButtonColors);
-    method public androidx.wear.tiles.material.Button.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Button.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String, androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setImageContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String, int);
+  @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, androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String);
+    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);
   }
 
-  public class ButtonColors {
-    ctor public ButtonColors(@ColorInt int, @ColorInt int);
-    ctor public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public static androidx.wear.tiles.material.ButtonColors primaryButtonColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ButtonColors secondaryButtonColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ButtonColors {
+    ctor @Deprecated public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor @Deprecated public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ButtonDefaults {
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp LARGE_SIZE;
-    field public static final androidx.wear.tiles.material.ButtonColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ButtonColors SECONDARY_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;
   }
 
-  public class Chip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Chip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getHeight();
-    method public int getHorizontalAlignment();
-    method public String? getIconContent();
-    method public String? getPrimaryLabelContent();
-    method public String? getSecondaryLabelContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class Chip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Chip.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.Chip build();
-    method public androidx.wear.tiles.material.Chip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.Chip.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Chip.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Chip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.Chip.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setPrimaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setSecondaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class ChipColors {
-    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
-    ctor public ChipColors(@ColorInt int, @ColorInt int);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIconColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getSecondaryContentColor();
-    method public static androidx.wear.tiles.material.ChipColors primaryChipColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ChipColors secondaryChipColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ChipColors {
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ChipDefaults {
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_SECONDARY_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;
   }
 
-  public class CircularProgressIndicator implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getEndAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getProgress();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getStartAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DpProp getStrokeWidth();
+  @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();
   }
 
-  public static final class CircularProgressIndicator.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CircularProgressIndicator.Builder();
-    method public androidx.wear.tiles.material.CircularProgressIndicator build();
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.tiles.material.ProgressIndicatorColors);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setEndAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStartAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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.tiles.material.Colors DEFAULT;
+  @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;
   }
 
-  public class CompactChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CompactChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public String getText();
+  @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();
   }
 
-  public static final class CompactChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.CompactChip build();
-    method public androidx.wear.tiles.material.CompactChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+  @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);
   }
 
-  public class ProgressIndicatorColors {
-    ctor public ProgressIndicatorColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIndicatorColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getTrackColor();
-    method public static androidx.wear.tiles.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.tiles.material.Colors);
+  @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);
   }
 
-  public class ProgressIndicatorDefaults {
-    field public static final androidx.wear.tiles.material.ProgressIndicatorColors DEFAULT_COLORS;
-    field public static final androidx.wear.tiles.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;
+  @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;
   }
 
-  public class Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Text? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getColor();
-    method public androidx.wear.tiles.LayoutElementBuilders.FontStyle getFontStyle();
-    method public float getLineHeight();
-    method public int getMaxLines();
-    method public androidx.wear.tiles.ModifiersBuilders.Modifiers getModifiers();
-    method public int getMultilineAlignment();
-    method public int getOverflow();
-    method public String getText();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public boolean isUnderline();
+  @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();
   }
 
-  public static final class Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Text.Builder(android.content.Context, String);
-    method public androidx.wear.tiles.material.Text build();
-    method public androidx.wear.tiles.material.Text.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.material.Text.Builder setItalic(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setMaxLines(@IntRange(from=1) int);
-    method public androidx.wear.tiles.material.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
-    method public androidx.wear.tiles.material.Text.Builder setMultilineAlignment(int);
-    method public androidx.wear.tiles.material.Text.Builder setOverflow(int);
-    method public androidx.wear.tiles.material.Text.Builder setTypography(int);
-    method public androidx.wear.tiles.material.Text.Builder setUnderline(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setWeight(int);
+  @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);
   }
 
-  public class TitleChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.TitleChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public int getHorizontalAlignment();
-    method public String getText();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class TitleChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.TitleChip build();
-    method public androidx.wear.tiles.material.TitleChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.TitleChip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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
+  @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 {
 
-  public class EdgeContentLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getEdgeContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  @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();
   }
 
-  public static final class EdgeContentLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public EdgeContentLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout build();
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  @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);
   }
 
-  public class LayoutDefaults {
-    field public static final androidx.wear.tiles.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 public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  @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;
   }
 
-  public class MultiButtonLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public java.util.List<androidx.wear.tiles.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
+  @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
   }
 
-  public static final class MultiButtonLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiButtonLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  @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);
   }
 
-  public class MultiSlotLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
-    method public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  @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();
   }
 
-  public static final class MultiSlotLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiSlotLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class PrimaryLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  @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();
   }
 
-  public static final class PrimaryLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public PrimaryLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout build();
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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/public_plus_experimental_current.txt b/wear/tiles/tiles-material/api/public_plus_experimental_current.txt
index aecb80e..a798a8f 100644
--- a/wear/tiles/tiles-material/api/public_plus_experimental_current.txt
+++ b/wear/tiles/tiles-material/api/public_plus_experimental_current.txt
@@ -1,297 +1,297 @@
 // Signature format: 4.0
 package androidx.wear.tiles.material {
 
-  public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Button? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ButtonColors getButtonColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public String? getIconContent();
-    method public String? getImageContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize();
-    method public String? getTextContent();
+  @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();
   }
 
-  public static final class Button.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Button.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable);
-    method public androidx.wear.tiles.material.Button build();
-    method public androidx.wear.tiles.material.Button.Builder setButtonColors(androidx.wear.tiles.material.ButtonColors);
-    method public androidx.wear.tiles.material.Button.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Button.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String, androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setImageContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String, int);
+  @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, androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String);
+    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);
   }
 
-  public class ButtonColors {
-    ctor public ButtonColors(@ColorInt int, @ColorInt int);
-    ctor public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public static androidx.wear.tiles.material.ButtonColors primaryButtonColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ButtonColors secondaryButtonColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ButtonColors {
+    ctor @Deprecated public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor @Deprecated public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ButtonDefaults {
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp LARGE_SIZE;
-    field public static final androidx.wear.tiles.material.ButtonColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ButtonColors SECONDARY_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;
   }
 
-  public class Chip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Chip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getHeight();
-    method public int getHorizontalAlignment();
-    method public String? getIconContent();
-    method public String? getPrimaryLabelContent();
-    method public String? getSecondaryLabelContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class Chip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Chip.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.Chip build();
-    method public androidx.wear.tiles.material.Chip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.Chip.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Chip.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Chip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.Chip.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setPrimaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setSecondaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class ChipColors {
-    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
-    ctor public ChipColors(@ColorInt int, @ColorInt int);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIconColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getSecondaryContentColor();
-    method public static androidx.wear.tiles.material.ChipColors primaryChipColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ChipColors secondaryChipColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ChipColors {
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ChipDefaults {
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_SECONDARY_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;
   }
 
-  public class CircularProgressIndicator implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getEndAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getProgress();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getStartAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DpProp getStrokeWidth();
+  @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();
   }
 
-  public static final class CircularProgressIndicator.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CircularProgressIndicator.Builder();
-    method public androidx.wear.tiles.material.CircularProgressIndicator build();
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.tiles.material.ProgressIndicatorColors);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setEndAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStartAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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.tiles.material.Colors DEFAULT;
+  @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;
   }
 
-  public class CompactChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CompactChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public String getText();
+  @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();
   }
 
-  public static final class CompactChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.CompactChip build();
-    method public androidx.wear.tiles.material.CompactChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+  @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);
   }
 
-  public class ProgressIndicatorColors {
-    ctor public ProgressIndicatorColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIndicatorColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getTrackColor();
-    method public static androidx.wear.tiles.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.tiles.material.Colors);
+  @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);
   }
 
-  public class ProgressIndicatorDefaults {
-    field public static final androidx.wear.tiles.material.ProgressIndicatorColors DEFAULT_COLORS;
-    field public static final androidx.wear.tiles.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;
+  @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;
   }
 
-  public class Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Text? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getColor();
-    method public androidx.wear.tiles.LayoutElementBuilders.FontStyle getFontStyle();
-    method public float getLineHeight();
-    method public int getMaxLines();
-    method public androidx.wear.tiles.ModifiersBuilders.Modifiers getModifiers();
-    method public int getMultilineAlignment();
-    method public int getOverflow();
-    method public String getText();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public boolean isUnderline();
+  @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();
   }
 
-  public static final class Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Text.Builder(android.content.Context, String);
-    method public androidx.wear.tiles.material.Text build();
-    method public androidx.wear.tiles.material.Text.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.material.Text.Builder setItalic(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setMaxLines(@IntRange(from=1) int);
-    method public androidx.wear.tiles.material.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
-    method public androidx.wear.tiles.material.Text.Builder setMultilineAlignment(int);
-    method public androidx.wear.tiles.material.Text.Builder setOverflow(int);
-    method public androidx.wear.tiles.material.Text.Builder setTypography(int);
-    method public androidx.wear.tiles.material.Text.Builder setUnderline(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setWeight(int);
+  @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);
   }
 
-  public class TitleChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.TitleChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public int getHorizontalAlignment();
-    method public String getText();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class TitleChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.TitleChip build();
-    method public androidx.wear.tiles.material.TitleChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.TitleChip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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
+  @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 {
 
-  public class EdgeContentLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getEdgeContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  @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();
   }
 
-  public static final class EdgeContentLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public EdgeContentLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout build();
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  @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);
   }
 
-  public class LayoutDefaults {
-    field public static final androidx.wear.tiles.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 public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  @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;
   }
 
-  public class MultiButtonLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public java.util.List<androidx.wear.tiles.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
+  @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
   }
 
-  public static final class MultiButtonLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiButtonLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  @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);
   }
 
-  public class MultiSlotLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
-    method public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  @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();
   }
 
-  public static final class MultiSlotLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiSlotLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class PrimaryLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  @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();
   }
 
-  public static final class PrimaryLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public PrimaryLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout build();
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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/restricted_current.txt b/wear/tiles/tiles-material/api/restricted_current.txt
index aecb80e..a798a8f 100644
--- a/wear/tiles/tiles-material/api/restricted_current.txt
+++ b/wear/tiles/tiles-material/api/restricted_current.txt
@@ -1,297 +1,297 @@
 // Signature format: 4.0
 package androidx.wear.tiles.material {
 
-  public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Button? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ButtonColors getButtonColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public String? getIconContent();
-    method public String? getImageContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize();
-    method public String? getTextContent();
+  @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();
   }
 
-  public static final class Button.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Button.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable);
-    method public androidx.wear.tiles.material.Button build();
-    method public androidx.wear.tiles.material.Button.Builder setButtonColors(androidx.wear.tiles.material.ButtonColors);
-    method public androidx.wear.tiles.material.Button.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Button.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String, androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setImageContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.Button.Builder setSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String);
-    method public androidx.wear.tiles.material.Button.Builder setTextContent(String, int);
+  @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, androidx.wear.tiles.DimensionBuilders.DpProp);
+    method @Deprecated public androidx.wear.tiles.material.Button.Builder setIconContent(String);
+    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);
   }
 
-  public class ButtonColors {
-    ctor public ButtonColors(@ColorInt int, @ColorInt int);
-    ctor public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public static androidx.wear.tiles.material.ButtonColors primaryButtonColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ButtonColors secondaryButtonColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ButtonColors {
+    ctor @Deprecated public ButtonColors(@ColorInt int, @ColorInt int);
+    ctor @Deprecated public ButtonColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ButtonDefaults {
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public static androidx.wear.tiles.DimensionBuilders.DpProp recommendedIconSize(@Dimension(unit=androidx.annotation.Dimension.DP) float);
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp DEFAULT_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp EXTRA_LARGE_SIZE;
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp LARGE_SIZE;
-    field public static final androidx.wear.tiles.material.ButtonColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ButtonColors SECONDARY_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;
   }
 
-  public class Chip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Chip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getCustomContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getHeight();
-    method public int getHorizontalAlignment();
-    method public String? getIconContent();
-    method public String? getPrimaryLabelContent();
-    method public String? getSecondaryLabelContent();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class Chip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Chip.Builder(android.content.Context, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.Chip build();
-    method public androidx.wear.tiles.material.Chip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.Chip.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.Chip.Builder setCustomContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.Chip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.Chip.Builder setIconContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setPrimaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setSecondaryLabelContent(String);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.Chip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class ChipColors {
-    ctor public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
-    ctor public ChipColors(@ColorInt int, @ColorInt int);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ChipColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getContentColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIconColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getSecondaryContentColor();
-    method public static androidx.wear.tiles.material.ChipColors primaryChipColors(androidx.wear.tiles.material.Colors);
-    method public static androidx.wear.tiles.material.ChipColors secondaryChipColors(androidx.wear.tiles.material.Colors);
+  @Deprecated public class ChipColors {
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int, @ColorInt int, @ColorInt int);
+    ctor @Deprecated public ChipColors(@ColorInt int, @ColorInt int);
+    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(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
+    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);
   }
 
-  public class ChipDefaults {
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors COMPACT_SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors SECONDARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_PRIMARY_COLORS;
-    field public static final androidx.wear.tiles.material.ChipColors TITLE_SECONDARY_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;
   }
 
-  public class CircularProgressIndicator implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CircularProgressIndicator? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ProgressIndicatorColors getCircularProgressIndicatorColors();
-    method public CharSequence? getContentDescription();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getEndAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getProgress();
-    method public androidx.wear.tiles.DimensionBuilders.DegreesProp getStartAngle();
-    method public androidx.wear.tiles.DimensionBuilders.DpProp getStrokeWidth();
+  @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();
   }
 
-  public static final class CircularProgressIndicator.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CircularProgressIndicator.Builder();
-    method public androidx.wear.tiles.material.CircularProgressIndicator build();
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setCircularProgressIndicatorColors(androidx.wear.tiles.material.ProgressIndicatorColors);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setContentDescription(CharSequence);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setEndAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setProgress(@FloatRange(from=0, to=1) float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStartAngle(float);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(androidx.wear.tiles.DimensionBuilders.DpProp);
-    method public androidx.wear.tiles.material.CircularProgressIndicator.Builder setStrokeWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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.tiles.material.Colors DEFAULT;
+  @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;
   }
 
-  public class CompactChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.CompactChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public String getText();
+  @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();
   }
 
-  public static final class CompactChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public CompactChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.CompactChip build();
-    method public androidx.wear.tiles.material.CompactChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
+  @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);
   }
 
-  public class ProgressIndicatorColors {
-    ctor public ProgressIndicatorColors(androidx.wear.tiles.ColorBuilders.ColorProp, androidx.wear.tiles.ColorBuilders.ColorProp);
-    ctor public ProgressIndicatorColors(@ColorInt int, @ColorInt int);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getIndicatorColor();
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getTrackColor();
-    method public static androidx.wear.tiles.material.ProgressIndicatorColors progressIndicatorColors(androidx.wear.tiles.material.Colors);
+  @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);
   }
 
-  public class ProgressIndicatorDefaults {
-    field public static final androidx.wear.tiles.material.ProgressIndicatorColors DEFAULT_COLORS;
-    field public static final androidx.wear.tiles.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;
+  @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;
   }
 
-  public class Text implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.Text? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.ColorBuilders.ColorProp getColor();
-    method public androidx.wear.tiles.LayoutElementBuilders.FontStyle getFontStyle();
-    method public float getLineHeight();
-    method public int getMaxLines();
-    method public androidx.wear.tiles.ModifiersBuilders.Modifiers getModifiers();
-    method public int getMultilineAlignment();
-    method public int getOverflow();
-    method public String getText();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public boolean isUnderline();
+  @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();
   }
 
-  public static final class Text.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public Text.Builder(android.content.Context, String);
-    method public androidx.wear.tiles.material.Text build();
-    method public androidx.wear.tiles.material.Text.Builder setColor(androidx.wear.tiles.ColorBuilders.ColorProp);
-    method public androidx.wear.tiles.material.Text.Builder setItalic(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setMaxLines(@IntRange(from=1) int);
-    method public androidx.wear.tiles.material.Text.Builder setModifiers(androidx.wear.tiles.ModifiersBuilders.Modifiers);
-    method public androidx.wear.tiles.material.Text.Builder setMultilineAlignment(int);
-    method public androidx.wear.tiles.material.Text.Builder setOverflow(int);
-    method public androidx.wear.tiles.material.Text.Builder setTypography(int);
-    method public androidx.wear.tiles.material.Text.Builder setUnderline(boolean);
-    method public androidx.wear.tiles.material.Text.Builder setWeight(int);
+  @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);
   }
 
-  public class TitleChip implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.TitleChip? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.ChipColors getChipColors();
-    method public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable();
-    method public int getHorizontalAlignment();
-    method public String getText();
-    method public androidx.wear.tiles.DimensionBuilders.ContainerDimension getWidth();
+  @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();
   }
 
-  public static final class TitleChip.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public TitleChip.Builder(android.content.Context, String, androidx.wear.tiles.ModifiersBuilders.Clickable, androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.TitleChip build();
-    method public androidx.wear.tiles.material.TitleChip.Builder setChipColors(androidx.wear.tiles.material.ChipColors);
-    method public androidx.wear.tiles.material.TitleChip.Builder setHorizontalAlignment(int);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(androidx.wear.tiles.DimensionBuilders.ContainerDimension);
-    method public androidx.wear.tiles.material.TitleChip.Builder setWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  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
+  @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 {
 
-  public class EdgeContentLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.EdgeContentLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getEdgeContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
+  @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();
   }
 
-  public static final class EdgeContentLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public EdgeContentLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout build();
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setEdgeContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.EdgeContentLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
+  @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);
   }
 
-  public class LayoutDefaults {
-    field public static final androidx.wear.tiles.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 public static final int MULTI_BUTTON_MAX_NUMBER = 7; // 0x7
-    field public static final androidx.wear.tiles.DimensionBuilders.DpProp MULTI_SLOT_LAYOUT_HORIZONTAL_SPACER_WIDTH;
+  @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;
   }
 
-  public class MultiButtonLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiButtonLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public java.util.List<androidx.wear.tiles.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
+  @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
   }
 
-  public static final class MultiButtonLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiButtonLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder addButtonContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiButtonLayout.Builder setFiveButtonDistribution(int);
+  @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);
   }
 
-  public class MultiSlotLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.MultiSlotLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getHorizontalSpacerWidth();
-    method public java.util.List<androidx.wear.tiles.LayoutElementBuilders.LayoutElement!> getSlotContents();
+  @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();
   }
 
-  public static final class MultiSlotLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public MultiSlotLayout.Builder();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder addSlotContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout build();
-    method public androidx.wear.tiles.material.layouts.MultiSlotLayout.Builder setHorizontalSpacerWidth(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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);
   }
 
-  public class PrimaryLayout implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
-    method public static androidx.wear.tiles.material.layouts.PrimaryLayout? fromLayoutElement(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryChipContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getPrimaryLabelTextContent();
-    method public androidx.wear.tiles.LayoutElementBuilders.LayoutElement? getSecondaryLabelTextContent();
-    method @Dimension(unit=androidx.annotation.Dimension.DP) public float getVerticalSpacerHeight();
+  @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();
   }
 
-  public static final class PrimaryLayout.Builder implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
-    ctor public PrimaryLayout.Builder(androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout build();
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryChipContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setPrimaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setSecondaryLabelTextContent(androidx.wear.tiles.LayoutElementBuilders.LayoutElement);
-    method public androidx.wear.tiles.material.layouts.PrimaryLayout.Builder setVerticalSpacerHeight(@Dimension(unit=androidx.annotation.Dimension.DP) float);
+  @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/src/androidTest/java/androidx/wear/tiles/material/TestCasesGenerator.java b/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/TestCasesGenerator.java
index 3b62f26..f42feff 100644
--- a/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/TestCasesGenerator.java
+++ b/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/TestCasesGenerator.java
@@ -21,8 +21,6 @@
 import static androidx.wear.tiles.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER;
 import static androidx.wear.tiles.LayoutElementBuilders.HORIZONTAL_ALIGN_END;
 import static androidx.wear.tiles.LayoutElementBuilders.HORIZONTAL_ALIGN_START;
-import static androidx.wear.tiles.material.ProgressIndicatorDefaults.GAP_END_ANGLE;
-import static androidx.wear.tiles.material.ProgressIndicatorDefaults.GAP_START_ANGLE;
 
 import android.content.Context;
 import android.graphics.Color;
@@ -39,6 +37,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+@SuppressWarnings("deprecation")
 public class TestCasesGenerator {
     private TestCasesGenerator() {}
 
@@ -253,8 +252,8 @@
         testCases.put(
                 "default_gap_circularprogressindicator",
                 new CircularProgressIndicator.Builder()
-                        .setStartAngle(GAP_START_ANGLE)
-                        .setEndAngle(GAP_END_ANGLE)
+                        .setStartAngle(ProgressIndicatorDefaults.GAP_START_ANGLE)
+                        .setEndAngle(ProgressIndicatorDefaults.GAP_END_ANGLE)
                         .build());
         testCases.put(
                 "default_full_90_circularprogressindicator",
@@ -263,8 +262,8 @@
                 "default_gap_90_circularprogressindicator",
                 new CircularProgressIndicator.Builder()
                         .setProgress(0.25f)
-                        .setStartAngle(GAP_START_ANGLE)
-                        .setEndAngle(GAP_END_ANGLE)
+                        .setStartAngle(ProgressIndicatorDefaults.GAP_START_ANGLE)
+                        .setEndAngle(ProgressIndicatorDefaults.GAP_END_ANGLE)
                         .build());
         testCases.put(
                 "custom_gap_45_circularprogressindicator",
diff --git a/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator.java b/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator.java
index b03caa2..1ec7f57 100644
--- a/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator.java
+++ b/wear/tiles/tiles-material/src/androidTest/java/androidx/wear/tiles/material/layouts/TestCasesGenerator.java
@@ -51,6 +51,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+@SuppressWarnings("deprecation")
 public class TestCasesGenerator {
     private TestCasesGenerator() {}
 
diff --git a/wear/tiles/tiles-material/src/main/AndroidManifest.xml b/wear/tiles/tiles-material/src/main/AndroidManifest.xml
index 037bd65..ed8a041 100644
--- a/wear/tiles/tiles-material/src/main/AndroidManifest.xml
+++ b/wear/tiles/tiles-material/src/main/AndroidManifest.xml
@@ -14,6 +14,6 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest>
 
 </manifest>
\ No newline at end of file
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Button.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Button.java
index 180f84f..966fb2a 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Button.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Button.java
@@ -37,6 +37,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.ColorBuilders.ColorProp;
 import androidx.wear.tiles.DimensionBuilders.ContainerDimension;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
@@ -52,7 +53,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.ModifiersBuilders.Semantics;
 import androidx.wear.tiles.material.Typography.TypographyName;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -86,7 +86,12 @@
  * <pre>{@code
  * Button myButton = Button.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Button} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class Button implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Box is actually a Button with text. */
     static final String METADATA_TAG_TEXT = "TXTBTN";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonColors.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonColors.java
index cee5fbd..ebf62a0 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonColors.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonColors.java
@@ -28,7 +28,12 @@
  * <p>See {@link ButtonDefaults#PRIMARY_COLORS} for the default colors used in a primary styled
  * {@link Button}. See {@link ButtonDefaults#SECONDARY_COLORS} for the default colors used in a
  * secondary styled {@link Button}.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.ButtonColors} which
+ *     provides the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ButtonColors {
     @NonNull private final ColorProp mBackgroundColor;
     @NonNull private final ColorProp mContentColor;
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonDefaults.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonDefaults.java
index 3439061..7c9398c 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonDefaults.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ButtonDefaults.java
@@ -23,7 +23,14 @@
 import androidx.annotation.NonNull;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 
-/** Contains the default values used by button Tiles components. */
+/**
+ * Contains the default values used by button Tiles components.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.ButtonDefaults} which
+ *     provides the same API and functionality.
+ */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ButtonDefaults {
     private ButtonDefaults() {}
 
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Chip.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Chip.java
index 4a00f21..18ce731 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Chip.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Chip.java
@@ -41,6 +41,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.ColorBuilders.ColorProp;
 import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
 import androidx.wear.tiles.DimensionBuilders.ContainerDimension;
@@ -62,7 +63,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Padding;
 import androidx.wear.tiles.ModifiersBuilders.Semantics;
 import androidx.wear.tiles.material.Typography.TypographyName;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -102,7 +102,12 @@
  *
  * @see  androidx.wear.tiles.material.layouts.PrimaryLayout.Builder#setContent if this Chip is used
  * inside of {@link androidx.wear.tiles.material.layouts.PrimaryLayout}.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Chip} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class Chip implements LayoutElement {
     /**
      * Tool tag for Metadata in Modifiers, so we know that Box is actually a Chip with only text.
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipColors.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipColors.java
index e739b1d..45b9d76 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipColors.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipColors.java
@@ -28,7 +28,12 @@
  * <p>See {@link ChipDefaults#PRIMARY_COLORS} for the default colors used in a primary styled {@link
  * Chip}. See {@link ChipDefaults#SECONDARY_COLORS} for the default colors used in a secondary
  * styled {@link Chip}.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.ChipColors} which
+ *     provides the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ChipColors {
     @NonNull private final ColorProp mBackgroundColor;
     @NonNull private final ColorProp mIconColor;
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipDefaults.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipDefaults.java
index df1d845..e0b6c27 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipDefaults.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ChipDefaults.java
@@ -23,7 +23,14 @@
 import androidx.annotation.RestrictTo.Scope;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 
-/** Contains the default values used by chip Tiles components. */
+/**
+ * Contains the default values used by chip Tiles components.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.ChipDefaults} which
+ *     provides the same API and functionality.
+ */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ChipDefaults {
     private ChipDefaults() {}
 
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator.java
index 771d94a..27c3d8d 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CircularProgressIndicator.java
@@ -35,6 +35,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DimensionBuilders.DegreesProp;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.LayoutElementBuilders;
@@ -47,7 +48,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.ModifiersBuilders.Padding;
 import androidx.wear.tiles.ModifiersBuilders.Semantics;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 /**
  * Tiles component {@link CircularProgressIndicator} that represents circular progress indicator
@@ -83,7 +83,13 @@
  * CircularProgressIndicator myCpi =
  *   CircularProgressIndicator.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.CircularProgressIndicator} which provides the
+ *     same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class CircularProgressIndicator implements LayoutElement {
     /**
      * Tool tag for Metadata in Modifiers, so we know that Arc is actually a
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Colors.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Colors.java
index a1efbe29..47b6f53 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Colors.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Colors.java
@@ -26,7 +26,12 @@
  * objects for all Material components.
  *
  * <p>See {@link #DEFAULT} for default color scheme.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Colors} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class Colors {
 
     /**
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CompactChip.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CompactChip.java
index 8c10c16..a2dadf4 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CompactChip.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/CompactChip.java
@@ -32,6 +32,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
 import androidx.wear.tiles.LayoutElementBuilders;
 import androidx.wear.tiles.LayoutElementBuilders.Box;
@@ -39,7 +40,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Clickable;
 import androidx.wear.tiles.ModifiersBuilders.ElementMetadata;
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 /**
  * Tiles component {@link CompactChip} that represents clickable object with the text.
@@ -70,7 +70,12 @@
  * <pre>{@code
  * CompactChip myChip = CompactChip.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.CompactChip} which
+ *     provides the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class CompactChip implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Box is actually a CompactChip. */
     static final String METADATA_TAG = "CMPCHP";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Helper.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Helper.java
index 90ac94c..edc727e 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Helper.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Helper.java
@@ -35,7 +35,11 @@
 /**
  * Helper class used for Tiles Material.
  *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Helper} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 @RestrictTo(Scope.LIBRARY_GROUP)
 public class Helper {
     private Helper() {}
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorColors.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorColors.java
index c88a9b4..d7eea6e 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorColors.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorColors.java
@@ -27,7 +27,12 @@
  *
  * <p>See {@link ProgressIndicatorDefaults#DEFAULT_COLORS} for the default colors used in a {@link
  * CircularProgressIndicator}.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.ProgressIndicatorColors}
+ *     which provides the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ProgressIndicatorColors {
     @NonNull private final ColorProp mIndicatorColor;
     @NonNull private final ColorProp mTrackColor;
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorDefaults.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorDefaults.java
index 955f829..ea4446b 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorDefaults.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/ProgressIndicatorDefaults.java
@@ -23,7 +23,15 @@
 import androidx.annotation.RestrictTo.Scope;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 
-/** Contains the default values used by {@link CircularProgressIndicator} Tiles components. */
+/**
+ * Contains the default values used by {@link CircularProgressIndicator} Tiles components.
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.CircularProgressIndicator} which provides the
+ *     same API and functionality.
+ */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class ProgressIndicatorDefaults {
     private ProgressIndicatorDefaults() {}
 
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Text.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Text.java
index b51e642..4c0bdfc 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Text.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Text.java
@@ -34,6 +34,8 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
+import androidx.wear.protolayout.proto.ModifiersProto;
 import androidx.wear.tiles.ColorBuilders.ColorProp;
 import androidx.wear.tiles.LayoutElementBuilders;
 import androidx.wear.tiles.LayoutElementBuilders.FontStyle;
@@ -44,8 +46,6 @@
 import androidx.wear.tiles.ModifiersBuilders.ElementMetadata;
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.material.Typography.TypographyName;
-import androidx.wear.protolayout.proto.LayoutElementProto;
-import androidx.wear.protolayout.proto.ModifiersProto;
 
 /**
  * Tiles component {@link Text} that represents text object holding any information.
@@ -71,7 +71,12 @@
  * <pre>{@code
  * Text myText = Text.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Text} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class Text implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Text is actually a Material Text. */
     static final String METADATA_TAG = "TXT";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/TitleChip.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/TitleChip.java
index 3c98bf4..2777589 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/TitleChip.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/TitleChip.java
@@ -32,13 +32,13 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
 import androidx.wear.tiles.DimensionBuilders.ContainerDimension;
 import androidx.wear.tiles.LayoutElementBuilders.Box;
 import androidx.wear.tiles.LayoutElementBuilders.HorizontalAlignment;
 import androidx.wear.tiles.LayoutElementBuilders.LayoutElement;
 import androidx.wear.tiles.ModifiersBuilders.Clickable;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 /**
  * Tiles component {@link TitleChip} that represents clickable object with the text.
@@ -71,7 +71,12 @@
  *
  * @see  androidx.wear.tiles.material.layouts.PrimaryLayout.Builder#setContent if this TitleChip is
  * used inside of {@link androidx.wear.tiles.material.layouts.PrimaryLayout}.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.TitleChip} which provides
+ *     the same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class TitleChip implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Box is actually a TitleChip. */
     static final String METADATA_TAG = "TTLCHP";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Typography.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Typography.java
index c972b52..faf0528 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Typography.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/Typography.java
@@ -45,7 +45,14 @@
 import java.util.HashMap;
 import java.util.Map;
 
-/** Typography styles, currently set up to match Wear's styling. */
+/**
+ * Typography styles, currently set up to match Wear's styling.
+ *
+ * @deprecated Use the new class {@link androidx.wear.protolayout.material.Typography} which
+ *     provides the same API and functionality.
+ */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class Typography {
     /** Typography for large display text. */
     public static final int TYPOGRAPHY_DISPLAY1 = 1;
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout.java
index 71582c0..e765457 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/EdgeContentLayout.java
@@ -34,6 +34,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.LayoutElementBuilders;
@@ -45,7 +46,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.ModifiersBuilders.Padding;
 import androidx.wear.tiles.material.CircularProgressIndicator;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -80,7 +80,13 @@
  * EdgeContentLayout myEcl =
  *   EdgeContentLayout.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.layouts.EdgeContentLayout} which provides the
+ *     same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class EdgeContentLayout implements LayoutElement {
     /**
      * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/LayoutDefaults.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/LayoutDefaults.java
index df5d7d0..72c060c 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/LayoutDefaults.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/LayoutDefaults.java
@@ -21,7 +21,15 @@
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.material.ButtonDefaults;
 
-/** Contains the default values used by layout templates for Tiles. */
+/**
+ * Contains the default values used by layout templates for Tiles.
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.layouts.LayoutDefaults} which provides the
+ *     same API and functionality.
+ */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class LayoutDefaults {
     private LayoutDefaults() {}
 
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout.java
index dcd0d7c..f7baab6c 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiButtonLayout.java
@@ -33,6 +33,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.LayoutElementBuilders.Box;
 import androidx.wear.tiles.LayoutElementBuilders.Column;
@@ -42,7 +43,6 @@
 import androidx.wear.tiles.ModifiersBuilders.ElementMetadata;
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.material.Button;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -76,7 +76,13 @@
  * <pre>{@code
  * MultiButtonLayout myMbl = MultiButtonLayout.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.layouts.MultiButtonLayout} which provides the
+ *     same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class MultiButtonLayout implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Box is actually a MultiButtonLayout. */
     static final String METADATA_TAG = "MBL";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout.java
index 99c13ed..3eb7d77 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/MultiSlotLayout.java
@@ -32,6 +32,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.DimensionBuilders.SpacerDimension;
 import androidx.wear.tiles.LayoutElementBuilders;
@@ -41,7 +42,6 @@
 import androidx.wear.tiles.LayoutElementBuilders.Spacer;
 import androidx.wear.tiles.ModifiersBuilders.ElementMetadata;
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -75,7 +75,13 @@
  * <pre>{@code
  * MultiSlotLayout myMsl = MultiSlotLayout.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.layouts.MultiSlotLayout} which provides the
+ *     same API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class MultiSlotLayout implements LayoutElement {
     /** Tool tag for Metadata in Modifiers, so we know that Row is actually a MultiSlotLayout. */
     static final String METADATA_TAG = "MSL";
diff --git a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout.java b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout.java
index 77bfd3c..f77cd81 100644
--- a/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout.java
+++ b/wear/tiles/tiles-material/src/main/java/androidx/wear/tiles/material/layouts/PrimaryLayout.java
@@ -46,6 +46,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.proto.LayoutElementProto;
 import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
 import androidx.wear.tiles.DimensionBuilders.DpProp;
 import androidx.wear.tiles.DimensionBuilders.SpacerDimension;
@@ -58,7 +59,6 @@
 import androidx.wear.tiles.ModifiersBuilders.Modifiers;
 import androidx.wear.tiles.ModifiersBuilders.Padding;
 import androidx.wear.tiles.material.CompactChip;
-import androidx.wear.protolayout.proto.LayoutElementProto;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -96,7 +96,13 @@
  * <pre>{@code
  * PrimaryLayout myPl = PrimaryLayout.fromLayoutElement(box.getContents().get(0));
  * }</pre>
+ *
+ * @deprecated Use the new class
+ *     {@link androidx.wear.protolayout.material.layouts.PrimaryLayout} which provides the same
+ *     API and functionality.
  */
+@Deprecated
+@SuppressWarnings("deprecation")
 public class PrimaryLayout implements LayoutElement {
     /**
      * Prefix tool tag for Metadata in Modifiers, so we know that Box is actually a PrimaryLayout.
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonColorsTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonColorsTest.java
index 08060bf..c57c525 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonColorsTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonColorsTest.java
@@ -29,6 +29,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class ButtonColorsTest {
     private static final int ARGB_BACKGROUND_COLOR = 0x12345678;
     private static final int ARGB_CONTENT_COLOR = 0x11223344;
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonTest.java
index 57facdb..b9cec02 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ButtonTest.java
@@ -48,6 +48,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class ButtonTest {
     private static final String RESOURCE_ID = "icon";
     private static final String TEXT = "ABC";
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipColorsTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipColorsTest.java
index 241e514..5e2bac5 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipColorsTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipColorsTest.java
@@ -29,6 +29,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class ChipColorsTest {
     private static final int ARGB_BACKGROUND_COLOR = 0x12345678;
     private static final int ARGB_CONTENT_COLOR = 0x11223344;
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipTest.java
index 4f1fc5f..7803fb7 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ChipTest.java
@@ -52,6 +52,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class ChipTest {
     private static final String MAIN_TEXT = "Primary text";
     private static final Clickable CLICKABLE =
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CircularProgressIndicatorTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CircularProgressIndicatorTest.java
index 172e8e5..62065c5 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CircularProgressIndicatorTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CircularProgressIndicatorTest.java
@@ -41,6 +41,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class CircularProgressIndicatorTest {
     @Test
     public void testOpenRingIndicatorDefault() {
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CompactChipTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CompactChipTest.java
index f7fe407a..2f8c71d 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CompactChipTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/CompactChipTest.java
@@ -41,6 +41,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class CompactChipTest {
     private static final String MAIN_TEXT = "Action";
     private static final Clickable CLICKABLE =
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ProgressIndicatorColorsTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ProgressIndicatorColorsTest.java
index e30aa5c..343ac72 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ProgressIndicatorColorsTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/ProgressIndicatorColorsTest.java
@@ -29,6 +29,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class ProgressIndicatorColorsTest {
     private static final int ARGB_BACKGROUND_COLOR = 0x12345678;
     private static final int ARGB_CONTENT_COLOR = 0x11223344;
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TextTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TextTest.java
index 791119d..f241b91 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TextTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TextTest.java
@@ -52,6 +52,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class TextTest {
 
     public static final int NUM_OF_FONT_STYLE_CONST = 12;
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TitleChipTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TitleChipTest.java
index e43bfb8..d2be002 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TitleChipTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/TitleChipTest.java
@@ -43,6 +43,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class TitleChipTest {
     private static final String MAIN_TEXT = "Action";
     private static final Clickable CLICKABLE =
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/Utils.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/Utils.java
index a1d44a5..d37d0eb1 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/Utils.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/Utils.java
@@ -18,6 +18,7 @@
 
 import androidx.annotation.Dimension;
 
+@SuppressWarnings("deprecation")
 public final class Utils {
     /** Returns true if the given ChipColors have the same colored content. */
     static boolean areChipColorsEqual(ChipColors colors1, ChipColors colors2) {
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest.java
index e4e413a..ce60257 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/EdgeContentLayoutTest.java
@@ -41,6 +41,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class EdgeContentLayoutTest {
     private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
     private static final DeviceParameters DEVICE_PARAMETERS =
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest.java
index ec35b24..71c33f4 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiButtonLayoutTest.java
@@ -45,6 +45,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class MultiButtonLayoutTest {
     private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
     private static final Clickable CLICKABLE =
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiSlotLayoutTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiSlotLayoutTest.java
index a2249fc..b44c6a2 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiSlotLayoutTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/MultiSlotLayoutTest.java
@@ -34,6 +34,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class MultiSlotLayoutTest {
 
     @Test
diff --git a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest.java b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest.java
index 1f749e6..f113146 100644
--- a/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest.java
+++ b/wear/tiles/tiles-material/src/test/java/androidx/wear/tiles/material/layouts/PrimaryLayoutTest.java
@@ -45,6 +45,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @DoNotInstrument
+@SuppressWarnings("deprecation")
 public class PrimaryLayoutTest {
     private static final Clickable CLICKABLE =
             new Clickable.Builder()
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
index 00a74e1..a64d494 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
@@ -883,6 +883,7 @@
         }
     }
 
+    @Ignore("b/273482617")
     @Test
     fun addWatchFaceReadyListener_alreadyReady() {
         val wallpaperService = TestExampleCanvasAnalogWatchFaceService(context, surfaceHolder)
diff --git a/work/work-runtime/api/current.txt b/work/work-runtime/api/current.txt
index 3e5a864..da29851 100644
--- a/work/work-runtime/api/current.txt
+++ b/work/work-runtime/api/current.txt
@@ -336,6 +336,8 @@
   }
 
   public final class WorkInfo {
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount);
@@ -345,7 +347,9 @@
     method public androidx.work.Constraints getConstraints();
     method public int getGeneration();
     method public java.util.UUID getId();
+    method public long getInitialDelayMillis();
     method public androidx.work.Data getOutputData();
+    method public androidx.work.WorkInfo.PeriodicityInfo? getPeriodicityInfo();
     method public androidx.work.Data getProgress();
     method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
@@ -353,13 +357,23 @@
     property public final androidx.work.Constraints constraints;
     property public final int generation;
     property public final java.util.UUID id;
+    property public final long initialDelayMillis;
     property public final androidx.work.Data outputData;
+    property public final androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo;
     property public final androidx.work.Data progress;
     property @IntRange(from=0L) public final int runAttemptCount;
     property public final androidx.work.WorkInfo.State state;
     property public final java.util.Set<java.lang.String> tags;
   }
 
+  public static final class WorkInfo.PeriodicityInfo {
+    ctor public WorkInfo.PeriodicityInfo(long repeatIntervalMillis, long flexIntervalMillis);
+    method public long getFlexIntervalMillis();
+    method public long getRepeatIntervalMillis();
+    property public final long flexIntervalMillis;
+    property public final long repeatIntervalMillis;
+  }
+
   public enum WorkInfo.State {
     method public final boolean isFinished();
     method public static androidx.work.WorkInfo.State valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
diff --git a/work/work-runtime/api/public_plus_experimental_current.txt b/work/work-runtime/api/public_plus_experimental_current.txt
index 3e5a864..da29851 100644
--- a/work/work-runtime/api/public_plus_experimental_current.txt
+++ b/work/work-runtime/api/public_plus_experimental_current.txt
@@ -336,6 +336,8 @@
   }
 
   public final class WorkInfo {
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount);
@@ -345,7 +347,9 @@
     method public androidx.work.Constraints getConstraints();
     method public int getGeneration();
     method public java.util.UUID getId();
+    method public long getInitialDelayMillis();
     method public androidx.work.Data getOutputData();
+    method public androidx.work.WorkInfo.PeriodicityInfo? getPeriodicityInfo();
     method public androidx.work.Data getProgress();
     method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
@@ -353,13 +357,23 @@
     property public final androidx.work.Constraints constraints;
     property public final int generation;
     property public final java.util.UUID id;
+    property public final long initialDelayMillis;
     property public final androidx.work.Data outputData;
+    property public final androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo;
     property public final androidx.work.Data progress;
     property @IntRange(from=0L) public final int runAttemptCount;
     property public final androidx.work.WorkInfo.State state;
     property public final java.util.Set<java.lang.String> tags;
   }
 
+  public static final class WorkInfo.PeriodicityInfo {
+    ctor public WorkInfo.PeriodicityInfo(long repeatIntervalMillis, long flexIntervalMillis);
+    method public long getFlexIntervalMillis();
+    method public long getRepeatIntervalMillis();
+    property public final long flexIntervalMillis;
+    property public final long repeatIntervalMillis;
+  }
+
   public enum WorkInfo.State {
     method public final boolean isFinished();
     method public static androidx.work.WorkInfo.State valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
diff --git a/work/work-runtime/api/restricted_current.txt b/work/work-runtime/api/restricted_current.txt
index 3e5a864..da29851 100644
--- a/work/work-runtime/api/restricted_current.txt
+++ b/work/work-runtime/api/restricted_current.txt
@@ -336,6 +336,8 @@
   }
 
   public final class WorkInfo {
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation);
     ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount);
@@ -345,7 +347,9 @@
     method public androidx.work.Constraints getConstraints();
     method public int getGeneration();
     method public java.util.UUID getId();
+    method public long getInitialDelayMillis();
     method public androidx.work.Data getOutputData();
+    method public androidx.work.WorkInfo.PeriodicityInfo? getPeriodicityInfo();
     method public androidx.work.Data getProgress();
     method @IntRange(from=0L) public int getRunAttemptCount();
     method public androidx.work.WorkInfo.State getState();
@@ -353,13 +357,23 @@
     property public final androidx.work.Constraints constraints;
     property public final int generation;
     property public final java.util.UUID id;
+    property public final long initialDelayMillis;
     property public final androidx.work.Data outputData;
+    property public final androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo;
     property public final androidx.work.Data progress;
     property @IntRange(from=0L) public final int runAttemptCount;
     property public final androidx.work.WorkInfo.State state;
     property public final java.util.Set<java.lang.String> tags;
   }
 
+  public static final class WorkInfo.PeriodicityInfo {
+    ctor public WorkInfo.PeriodicityInfo(long repeatIntervalMillis, long flexIntervalMillis);
+    method public long getFlexIntervalMillis();
+    method public long getRepeatIntervalMillis();
+    property public final long flexIntervalMillis;
+    property public final long repeatIntervalMillis;
+  }
+
   public enum WorkInfo.State {
     method public final boolean isFinished();
     method public static androidx.work.WorkInfo.State valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
diff --git a/work/work-runtime/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java b/work/work-runtime/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
index d64b7d8..bfd204c 100644
--- a/work/work-runtime/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
+++ b/work/work-runtime/src/androidTest/java/androidx/work/impl/WorkManagerImplTest.java
@@ -123,6 +123,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 
+import java.time.Duration;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -1179,7 +1180,7 @@
 
     @Test
     @MediumTest
-    public void testGetWorkInfoByIdSyncConstraints() throws Exception {
+    public void testGetWorkInfoByIdSync_constraints() throws Exception {
         Constraints constraints = new Constraints.Builder()
                 .setRequiresCharging(true)
                 .setRequiredNetworkType(CONNECTED)
@@ -1197,6 +1198,44 @@
 
     @Test
     @MediumTest
+    public void testGetWorkInfoByIdSync_oneTime_schedules() throws Exception {
+        OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class)
+                .setInitialState(SUCCEEDED)
+                .setInitialDelay(1234, TimeUnit.MILLISECONDS)
+                .build();
+        insertWorkSpecAndTags(work);
+
+        WorkInfo workInfo = mWorkManagerImpl.getWorkInfoById(work.getId()).get();
+        assertThat(workInfo.getId().toString(), is(work.getStringId()));
+        assertThat(workInfo.getInitialDelayMillis(), equalTo(1234L));
+        assertThat(workInfo.getPeriodicityInfo(), is(nullValue()));
+    }
+
+    @Test
+    @MediumTest
+    @SdkSuppress(minSdkVersion = 26)
+    public void testGetWorkInfoByIdSync_periodic_schedules() throws Exception {
+        Duration repeatInterval = Duration.ofMinutes(60);
+        Duration flexInterval = Duration.ofMinutes(30);
+
+        PeriodicWorkRequest work =
+                new PeriodicWorkRequest.Builder(TestWorker.class, repeatInterval, flexInterval)
+                        .setInitialState(SUCCEEDED)
+                        .setInitialDelay(1234, TimeUnit.MILLISECONDS)
+                        .build();
+        insertWorkSpecAndTags(work);
+
+        WorkInfo workInfo = mWorkManagerImpl.getWorkInfoById(work.getId()).get();
+        assertThat(workInfo.getId().toString(), is(work.getStringId()));
+        assertThat(workInfo.getInitialDelayMillis(), equalTo(1234L));
+        assertThat(workInfo.getPeriodicityInfo().getRepeatIntervalMillis(), equalTo(
+                repeatInterval.toMillis()));
+        assertThat(workInfo.getPeriodicityInfo().getFlexIntervalMillis(), equalTo(
+                flexInterval.toMillis()));
+    }
+
+    @Test
+    @MediumTest
     public void testGetWorkInfoByIdSync_returnsNullIfNotInDatabase()
             throws ExecutionException, InterruptedException {
 
@@ -1801,7 +1840,7 @@
             }
         };
         InstantWorkTaskExecutor workTaskExecutor = new InstantWorkTaskExecutor();
-        Processor processor = new Processor(mContext,  mConfiguration, workTaskExecutor, mDatabase);
+        Processor processor = new Processor(mContext, mConfiguration, workTaskExecutor, mDatabase);
         WorkLauncherImpl launcher = new WorkLauncherImpl(processor, workTaskExecutor);
 
         Trackers trackers = mWorkManagerImpl.getTrackers();
diff --git a/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt b/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt
index 3923f2b..3d2567a 100644
--- a/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt
+++ b/work/work-runtime/src/main/java/androidx/work/WorkInfo.kt
@@ -72,6 +72,16 @@
      * [Constraints] of this worker.
      */
     val constraints: Constraints = Constraints.NONE,
+
+    /** The initial delay for this work set in the [WorkRequest] */
+    val initialDelayMillis: Long = 0,
+
+    /**
+     * For periodic work, the period and flex duration set in the [PeriodicWorkRequest].
+     *
+     * Null if this is onetime work.
+     */
+    val periodicityInfo: PeriodicityInfo? = null,
 ) {
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
@@ -83,6 +93,8 @@
         if (state != workInfo.state) return false
         if (outputData != workInfo.outputData) return false
         if (constraints != workInfo.constraints) return false
+        if (initialDelayMillis != workInfo.initialDelayMillis) return false
+        if (periodicityInfo != workInfo.periodicityInfo) return false
         return if (tags != workInfo.tags) false else progress == workInfo.progress
     }
 
@@ -95,13 +107,17 @@
         result = 31 * result + runAttemptCount
         result = 31 * result + generation
         result = 31 * result + constraints.hashCode()
+        result = 31 * result + initialDelayMillis.hashCode()
+        result = 31 * result + periodicityInfo.hashCode()
         return result
     }
 
     override fun toString(): String {
         return ("WorkInfo{id='$id', state=$state, " +
             "outputData=$outputData, tags=$tags, progress=$progress, " +
-            "runAttemptCount=$runAttemptCount, generation=$generation, constraints=$constraints}")
+            "runAttemptCount=$runAttemptCount, generation=$generation, " +
+            "constraints=$constraints}, initialDelayMillis=$initialDelayMillis, " +
+            "periodicityInfo=$periodicityInfo")
     }
 
     /**
@@ -151,4 +167,35 @@
         val isFinished: Boolean
             get() = this == SUCCEEDED || this == FAILED || this == CANCELLED
     }
+
+    /** A periodic work's interval and flex duration */
+    class PeriodicityInfo(
+        /**
+         * The periodic work's configured repeat interval in millis, as configured in
+         * [PeriodicWorkRequest.Builder]
+         */
+        val repeatIntervalMillis: Long,
+        /**
+         * The duration in millis in which this work repeats from the end of the `repeatInterval`,
+         * as configured in [PeriodicWorkRequest.Builder].
+         */
+        val flexIntervalMillis: Long
+    ) {
+        override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (other == null || javaClass != other.javaClass) return false
+            val period = other as PeriodicityInfo
+            return period.repeatIntervalMillis == repeatIntervalMillis &&
+                period.flexIntervalMillis == flexIntervalMillis
+        }
+
+        override fun hashCode(): Int {
+            return 31 * repeatIntervalMillis.hashCode() + flexIntervalMillis.hashCode()
+        }
+
+        override fun toString(): String {
+            return "PeriodicityInfo{repeatIntervalMillis=$repeatIntervalMillis, " +
+                "flexIntervalMillis=$flexIntervalMillis}"
+        }
+    }
 }
\ No newline at end of file
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpec.kt b/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpec.kt
index 1d6a6b8..74cf921 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpec.kt
+++ b/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpec.kt
@@ -336,7 +336,7 @@
     )
 
     /**
-     * A POJO containing the ID, state, output, tags, and run attempt count of a WorkSpec.
+     * A POJO containing externally queryable info for the WorkSpec.
      */
     data class WorkInfoPojo(
         @ColumnInfo(name = "id")
@@ -357,6 +357,15 @@
         @Embedded
         val constraints: Constraints,
 
+        @ColumnInfo(name = "initial_delay")
+        val initialDelay: Long = 0,
+
+        @ColumnInfo(name = "interval_duration")
+        val intervalDuration: Long = 0,
+
+        @ColumnInfo(name = "flex_duration")
+        val flexDuration: Long = 0,
+
         @Relation(
             parentColumn = "id",
             entityColumn = "work_spec_id",
@@ -390,7 +399,13 @@
                 progress,
                 runAttemptCount,
                 generation,
-                constraints
+                constraints,
+                initialDelay,
+                if (intervalDuration == 0L) null else
+                    WorkInfo.PeriodicityInfo(
+                        intervalDuration,
+                        flexDuration
+                    )
             )
         }
     }
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpecDao.kt b/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpecDao.kt
index ac78f50..3c827af 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpecDao.kt
+++ b/work/work-runtime/src/main/java/androidx/work/impl/model/WorkSpecDao.kt
@@ -463,7 +463,7 @@
     .flowOn(dispatcher)
 
 private const val WORK_INFO_COLUMNS = "id, state, output, run_attempt_count, generation" +
-    ", $CONSTRAINTS_COLUMNS"
+    ", $CONSTRAINTS_COLUMNS, initial_delay, interval_duration, flex_duration"
 
 @Language("sql")
 private const val WORK_INFO_BY_IDS = "SELECT $WORK_INFO_COLUMNS FROM workspec WHERE id IN (:ids)"