Merge "Use fully qualified class names in class verification failure autofix" into androidx-main
diff --git a/asynclayoutinflater/asynclayoutinflater/api/current.txt b/asynclayoutinflater/asynclayoutinflater/api/current.txt
index 32c043c..46e1c0e 100644
--- a/asynclayoutinflater/asynclayoutinflater/api/current.txt
+++ b/asynclayoutinflater/asynclayoutinflater/api/current.txt
@@ -1,16 +1,9 @@
 // Signature format: 4.0
 package androidx.asynclayoutinflater.view {
 
-  public class AppCompatFactory2 implements android.view.LayoutInflater.Factory2 {
-    ctor public AppCompatFactory2();
-    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
-    method public android.view.View? onCreateView(String, android.content.Context, android.util.AttributeSet);
-  }
-
   public final class AsyncLayoutInflater {
     ctor public AsyncLayoutInflater(android.content.Context);
-    method @Deprecated @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
-    method @UiThread public void inflateWithOriginalFactory(@LayoutRes int, android.view.ViewGroup?, java.util.concurrent.Executor?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
+    method @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
   }
 
   public static interface AsyncLayoutInflater.OnInflateFinishedListener {
diff --git a/asynclayoutinflater/asynclayoutinflater/api/public_plus_experimental_current.txt b/asynclayoutinflater/asynclayoutinflater/api/public_plus_experimental_current.txt
index 32c043c..46e1c0e 100644
--- a/asynclayoutinflater/asynclayoutinflater/api/public_plus_experimental_current.txt
+++ b/asynclayoutinflater/asynclayoutinflater/api/public_plus_experimental_current.txt
@@ -1,16 +1,9 @@
 // Signature format: 4.0
 package androidx.asynclayoutinflater.view {
 
-  public class AppCompatFactory2 implements android.view.LayoutInflater.Factory2 {
-    ctor public AppCompatFactory2();
-    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
-    method public android.view.View? onCreateView(String, android.content.Context, android.util.AttributeSet);
-  }
-
   public final class AsyncLayoutInflater {
     ctor public AsyncLayoutInflater(android.content.Context);
-    method @Deprecated @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
-    method @UiThread public void inflateWithOriginalFactory(@LayoutRes int, android.view.ViewGroup?, java.util.concurrent.Executor?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
+    method @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
   }
 
   public static interface AsyncLayoutInflater.OnInflateFinishedListener {
diff --git a/asynclayoutinflater/asynclayoutinflater/api/restricted_current.txt b/asynclayoutinflater/asynclayoutinflater/api/restricted_current.txt
index 32c043c..46e1c0e 100644
--- a/asynclayoutinflater/asynclayoutinflater/api/restricted_current.txt
+++ b/asynclayoutinflater/asynclayoutinflater/api/restricted_current.txt
@@ -1,16 +1,9 @@
 // Signature format: 4.0
 package androidx.asynclayoutinflater.view {
 
-  public class AppCompatFactory2 implements android.view.LayoutInflater.Factory2 {
-    ctor public AppCompatFactory2();
-    method public android.view.View? onCreateView(android.view.View?, String, android.content.Context, android.util.AttributeSet);
-    method public android.view.View? onCreateView(String, android.content.Context, android.util.AttributeSet);
-  }
-
   public final class AsyncLayoutInflater {
     ctor public AsyncLayoutInflater(android.content.Context);
-    method @Deprecated @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
-    method @UiThread public void inflateWithOriginalFactory(@LayoutRes int, android.view.ViewGroup?, java.util.concurrent.Executor?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
+    method @UiThread public void inflate(@LayoutRes int, android.view.ViewGroup?, androidx.asynclayoutinflater.view.AsyncLayoutInflater.OnInflateFinishedListener);
   }
 
   public static interface AsyncLayoutInflater.OnInflateFinishedListener {
diff --git a/asynclayoutinflater/asynclayoutinflater/build.gradle b/asynclayoutinflater/asynclayoutinflater/build.gradle
index a559503..f11e241 100644
--- a/asynclayoutinflater/asynclayoutinflater/build.gradle
+++ b/asynclayoutinflater/asynclayoutinflater/build.gradle
@@ -8,11 +8,6 @@
 dependencies {
     api("androidx.annotation:annotation:1.1.0")
     api("androidx.core:core:1.1.0")
-    constraints {
-        implementation(project(":appcompat:appcompat")) // Optional dependency via compile-only
-    }
-    compileOnly(project(":appcompat:appcompat"))
-
     androidTestImplementation(project(":appcompat:appcompat"))
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testRunner)
@@ -31,8 +26,5 @@
 }
 
 android {
-    buildTypes.all {
-        consumerProguardFiles("proguard-rules.pro")
-    }
     namespace "androidx.asynclayoutinflater"
 }
diff --git a/asynclayoutinflater/asynclayoutinflater/proguard-rules.pro b/asynclayoutinflater/asynclayoutinflater/proguard-rules.pro
deleted file mode 100644
index 9928140..0000000
--- a/asynclayoutinflater/asynclayoutinflater/proguard-rules.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-# Ignore missing classes from optional AppCompat dependency.
--dontwarn androidx.appcompat.app.AppCompatActivity
--dontwarn androidx.appcompat.app.AppCompatCallback
--dontwarn androidx.appcompat.app.AppCompatDelegate
--dontwarn androidx.appcompat.app.AppCompatViewInflater
--dontwarn androidx.appcompat.widget.VectorEnabledTintResources
--dontwarn androidx.appcompat.R
--dontwarn android.support.v7.app.AppCompatActivity
--dontwarn android.support.v7.app.AppCompatViewInflater
--dontwarn android.support.v7.appcompat.R$styleable
--dontwarn android.support.v7.widget.VectorEnabledTintResources
\ No newline at end of file
diff --git a/asynclayoutinflater/asynclayoutinflater/src/androidTest/java/androidx/asynclayoutinflater/view/AsyncLayoutInflaterTest.java b/asynclayoutinflater/asynclayoutinflater/src/androidTest/java/androidx/asynclayoutinflater/view/AsyncLayoutInflaterTest.java
index 9adfa28..7f2a54d 100644
--- a/asynclayoutinflater/asynclayoutinflater/src/androidTest/java/androidx/asynclayoutinflater/view/AsyncLayoutInflaterTest.java
+++ b/asynclayoutinflater/asynclayoutinflater/src/androidTest/java/androidx/asynclayoutinflater/view/AsyncLayoutInflaterTest.java
@@ -15,8 +15,6 @@
  */
 package androidx.asynclayoutinflater.view;
 
-import android.os.Build;
-import android.os.Looper;
 import android.view.LayoutInflater;
 import android.view.View;
 
@@ -24,7 +22,6 @@
 import androidx.test.ext.junit.rules.ActivityScenarioRule;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
 
 import com.google.common.util.concurrent.SettableFuture;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -37,7 +34,6 @@
 
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicReference;
 
 @MediumTest
 @RunWith(AndroidJUnit4.class)
@@ -75,72 +71,4 @@
                 false);
         Assert.assertNotSame(asyncInflatedView.getClass(), inflatedView.getClass());
     }
-
-    @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP)
-    public void correctAsyncInflaterView_forButton() throws Exception {
-        SettableFuture<View> asyncInflatedViewFuture = SettableFuture.create();
-        mAsyncLayoutInflater.inflateWithOriginalFactory(R.layout.test_button, null,
-                /* callbackExecutor= */ null,
-                (view, resId, parent) -> {
-                    asyncInflatedViewFuture.set(view);
-                });
-
-        View asyncInflatedView = asyncInflatedViewFuture.get();
-        View inflatedView = LayoutInflater.from(mActivity).inflate(R.layout.test_button, null,
-                false);
-
-        Assert.assertSame(asyncInflatedView.getClass(), inflatedView.getClass());
-    }
-
-    @Test
-    public void inflateCallback_onMainThread() throws Exception {
-        AtomicReference<Thread> callbackThread = new AtomicReference<>(null);
-        SettableFuture<View> asyncInflatedViewFuture = SettableFuture.create();
-        mAsyncLayoutInflater.inflateWithOriginalFactory(R.layout.test_button, null,
-                /* callbackExecutor= */ null,
-                (view, resId, parent) -> {
-                    callbackThread.set(Thread.currentThread());
-                    asyncInflatedViewFuture.set(view);
-                });
-
-        asyncInflatedViewFuture.get();
-
-        Assert.assertSame(callbackThread.get(), Looper.getMainLooper().getThread());
-    }
-
-    @Test
-    public void inflateCallback_onBackgroundThread() throws Exception {
-        AtomicReference<Thread> callbackThread = new AtomicReference<>(null);
-        SettableFuture<View> asyncInflatedViewFuture = SettableFuture.create();
-        mAsyncLayoutInflater.inflateWithOriginalFactory(R.layout.test_button, null,
-                mBackgroundExecutor,
-                (view, resId, parent) -> {
-                    callbackThread.set(Thread.currentThread());
-                    asyncInflatedViewFuture.set(view);
-                });
-
-        asyncInflatedViewFuture.get();
-
-        // Not called on main thread.
-        Assert.assertNotSame(callbackThread.get(), Looper.getMainLooper().getThread());
-        Assert.assertEquals(callbackThread.get().getName(), BG_THREAD_NAME);
-    }
-
-    @Test
-    public void inflateCallback_onBackgroundThread_onAsyncInflationFailure() throws Exception {
-        AtomicReference<Thread> callbackThread = new AtomicReference<>(null);
-        SettableFuture<View> asyncInflatedViewFuture = SettableFuture.create();
-        mAsyncLayoutInflater.inflateWithOriginalFactory(R.layout.fail_async_text_view, null,
-                mBackgroundExecutor,
-                (view, resId, parent) -> {
-                    callbackThread.set(Thread.currentThread());
-                    asyncInflatedViewFuture.set(view);
-                });
-
-        asyncInflatedViewFuture.get();
-
-        Assert.assertNotSame(callbackThread.get(), Looper.getMainLooper().getThread());
-        Assert.assertEquals(callbackThread.get().getName(), BG_THREAD_NAME);
-    }
 }
diff --git a/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AppCompatFactory2.java b/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AppCompatFactory2.java
deleted file mode 100644
index 03c6586..0000000
--- a/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AppCompatFactory2.java
+++ /dev/null
@@ -1,86 +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.asynclayoutinflater.view;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.R;
-import androidx.appcompat.app.AppCompatViewInflater;
-import androidx.appcompat.widget.VectorEnabledTintResources;
-/**
- * Factory for inflating views in AppCompat activity. This is used when Async inflater is created
- * with AppCompat context.
- */
-public class AppCompatFactory2 implements LayoutInflater.Factory2 {
-    private static final String TAG = "AppCompatFactory2";
-    private AppCompatViewInflater mAppCompatViewInflater;
-    /**
-     * Creates view using {@link AppCompatViewInflater}.
-     */
-    @Nullable
-    @Override
-    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
-            @NonNull AttributeSet attrs) {
-        return createView(parent, name, context, attrs);
-    }
-    /**
-     * Creates view using {@link AppCompatViewInflater}.
-     */
-    @Nullable
-    @Override
-    public View onCreateView(@NonNull String name, @NonNull Context context,
-            @NonNull AttributeSet attrs) {
-        return createView(/* parent= */ null, name, context, attrs);
-    }
-    View createView(View parent, final String name, @NonNull Context context,
-            @NonNull AttributeSet attrs) {
-        if (mAppCompatViewInflater == null) {
-            TypedArray a = context.obtainStyledAttributes(R.styleable.AppCompatTheme);
-            String viewInflaterClassName = a.getString(
-                    R.styleable.AppCompatTheme_viewInflaterClass);
-            if (viewInflaterClassName == null) {
-                // Set to null (the default in all AppCompat themes). Create the base inflater
-                // (no reflection)
-                mAppCompatViewInflater = new AppCompatViewInflater();
-            } else {
-                try {
-                    Class<?> viewInflaterClass = context.getClassLoader().loadClass(
-                            viewInflaterClassName);
-                    mAppCompatViewInflater =
-                            (AppCompatViewInflater) viewInflaterClass
-                                    .getDeclaredConstructor()
-                                    .newInstance();
-                } catch (Throwable t) {
-                    Log.i(TAG, "Failed to instantiate custom view inflater " + viewInflaterClassName
-                            + ". Falling back to default.", t);
-                    mAppCompatViewInflater = new AppCompatViewInflater();
-                }
-            }
-        }
-        return mAppCompatViewInflater.createView(parent, name, context, attrs,
-                /* inheritContext= */ false,
-                /* isPreLollipop= */ false,
-                true, /* Read read app:theme as a fallback at all times for legacy reasons */
-                VectorEnabledTintResources.shouldBeUsed() /* Only tint wrap the context if
-                enabled */);
-    }
-}
diff --git a/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AsyncLayoutInflater.java b/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AsyncLayoutInflater.java
index 5d2d9be..3d3d8b2 100644
--- a/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AsyncLayoutInflater.java
+++ b/asynclayoutinflater/asynclayoutinflater/src/main/java/androidx/asynclayoutinflater/view/AsyncLayoutInflater.java
@@ -17,7 +17,6 @@
 package androidx.asynclayoutinflater.view;
 
 import android.content.Context;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -31,7 +30,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.util.Pools.SynchronizedPool;
 
 import java.util.concurrent.ArrayBlockingQueue;
@@ -69,54 +67,23 @@
  */
 public final class AsyncLayoutInflater {
     private static final String TAG = "AsyncLayoutInflater";
-    private static final boolean IS_POST_LOLLIPOP = Build.VERSION.SDK_INT >= 21;
-    private static boolean sAppCompatPresent;
-    static {
-        try {
-            Class.forName("androidx.appcompat.app.AppCompatActivity");
-            sAppCompatPresent = true;
-        } catch (ClassNotFoundException ex) {
-            sAppCompatPresent = false;
-        }
-    }
-
     LayoutInflater mInflater;
-    LayoutInflater mInflaterDeprecated;
     Handler mHandler;
     InflateThread mInflateThread;
 
     public AsyncLayoutInflater(@NonNull Context context) {
-        mInflaterDeprecated = new BasicInflater(context);
         mInflater = new BasicInflater(context);
         mHandler = new Handler(Looper.myLooper(), mHandlerCallback);
         mInflateThread = InflateThread.getInstance();
-        if (sAppCompatPresent && context instanceof AppCompatActivity && IS_POST_LOLLIPOP) {
-            mInflater.setFactory2(new AppCompatFactory2());
-        }
     }
 
     /**
      * Triggers view inflation on background thread.
-     *
-     * @deprecated may initialize incorrect class for AppCompat library. Use
-     * {@link #inflateWithOriginalFactory} instead.
      */
     @UiThread
-    @Deprecated
     public void inflate(@LayoutRes int resid, @Nullable ViewGroup parent,
             @NonNull OnInflateFinishedListener callback) {
-        inflateInternal(resid, parent, callback, mInflaterDeprecated, /* callbackExecutor= */ null);
-    }
-
-    /**
-     * Triggers inflation on a background thread. It uses an underlying
-     * inflater with same {@link LayoutInflater.Factory2} as the inflater for
-     * {@link AppCompatActivity}.
-     */
-    @UiThread
-    public void inflateWithOriginalFactory(@LayoutRes int resid, @Nullable ViewGroup parent,
-            @Nullable Executor callbackExecutor, @NonNull OnInflateFinishedListener callback) {
-        inflateInternal(resid, parent, callback, mInflater, callbackExecutor);
+        inflateInternal(resid, parent, callback, mInflater, /* callbackExecutor= */ null);
     }
 
     private void inflateInternal(@LayoutRes int resid, @Nullable ViewGroup parent,
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
index d107dd0b..ec67850 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
@@ -78,7 +78,10 @@
             baselineProfileMode = BaselineProfileMode.Disable,
             warmupIterations = iterations
         )
-        compilation.resetAndCompile(Packages.TARGET) {
+        compilation.resetAndCompile(
+            Packages.TARGET,
+            killProcessBlock = scope::killProcess
+        ) {
             executions += 1
             scope.pressHome()
             scope.startActivityAndWait()
@@ -88,8 +91,12 @@
 
     @Test
     fun compile_full() {
+        val scope = MacrobenchmarkScope(Packages.TARGET, launchWithClearTask = true)
         val compilation = CompilationMode.Full()
-        compilation.resetAndCompile(Packages.TARGET) {
+        compilation.resetAndCompile(
+            Packages.TARGET,
+            killProcessBlock = scope::killProcess
+        ) {
             fail("Should never be called for $compilation")
         }
     }
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
index 697fc15..82d069e 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
@@ -63,7 +63,13 @@
     try {
         userspaceTrace("compile $packageName") {
             compilationMode.resetAndCompile(
-                packageName = packageName
+                packageName = packageName,
+                killProcessBlock = {
+                    // When generating baseline profiles we want to default to using
+                    // killProcess if the session is rooted. This is so we can collect
+                    // baseline profiles for System Apps.
+                    scope.killProcess(useKillAll = Shell.isSessionRooted())
+                }
             ) {
                 profileBlock(scope)
             }
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
index 9a51aea..69c07cd 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
@@ -72,6 +72,7 @@
     internal fun resetAndCompile(
         packageName: String,
         usePackageReset: () -> Boolean = Shell::isSessionRooted,
+        killProcessBlock: () -> Unit,
         warmupBlock: () -> Unit
     ) {
         if (Build.VERSION.SDK_INT >= 24) {
@@ -105,8 +106,8 @@
                     }
                 }
                 // Write skip file to stop profile installer from interfering with the benchmark
-                writeProfileInstallerSkipFile(packageName)
-                compileImpl(packageName, warmupBlock)
+                writeProfileInstallerSkipFile(packageName, killProcessBlock = killProcessBlock)
+                compileImpl(packageName, killProcessBlock, warmupBlock)
             } else {
                 Log.d(TAG, "Compilation is disabled, skipping compilation of $packageName")
             }
@@ -157,7 +158,7 @@
      * Writes a skip file via a [ProfileInstallReceiver] broadcast, so profile installation
      * does not interfere with benchmarks.
      */
-    private fun writeProfileInstallerSkipFile(packageName: String) {
+    private fun writeProfileInstallerSkipFile(packageName: String, killProcessBlock: () -> Unit) {
         val result = profileInstallerSkipFileOperation(packageName, "WRITE_SKIP_FILE")
         if (result != null) {
             Log.w(
@@ -169,7 +170,7 @@
             )
         }
         Log.d(TAG, "Killing process $packageName")
-        Shell.executeCommand("am force-stop $packageName")
+        killProcessBlock()
     }
 
     /**
@@ -228,7 +229,11 @@
     }
 
     @RequiresApi(24)
-    internal abstract fun compileImpl(packageName: String, warmupBlock: () -> Unit)
+    internal abstract fun compileImpl(
+        packageName: String,
+        killProcessBlock: () -> Unit,
+        warmupBlock: () -> Unit
+    )
 
     @RequiresApi(24)
     internal abstract fun shouldReset(): Boolean
@@ -245,7 +250,11 @@
     class None : CompilationMode() {
         override fun toString(): String = "None"
 
-        override fun compileImpl(packageName: String, warmupBlock: () -> Unit) {
+        override fun compileImpl(
+            packageName: String,
+            killProcessBlock: () -> Unit,
+            warmupBlock: () -> Unit
+        ) {
             // nothing to do!
         }
 
@@ -262,7 +271,11 @@
     class Ignore : CompilationMode() {
         override fun toString(): String = "Ignore"
 
-        override fun compileImpl(packageName: String, warmupBlock: () -> Unit) {
+        override fun compileImpl(
+            packageName: String,
+            killProcessBlock: () -> Unit,
+            warmupBlock: () -> Unit
+        ) {
             // Do nothing.
         }
 
@@ -381,14 +394,18 @@
             }
         }
 
-        override fun compileImpl(packageName: String, warmupBlock: () -> Unit) {
+        override fun compileImpl(
+            packageName: String,
+            killProcessBlock: () -> Unit,
+            warmupBlock: () -> Unit
+        ) {
             if (baselineProfileMode != BaselineProfileMode.Disable) {
                 // Ignores the presence of a skip file.
                 val installErrorString = broadcastBaselineProfileInstall(packageName)
                 if (installErrorString == null) {
                     // baseline profile install success, kill process before compiling
                     Log.d(TAG, "Killing process $packageName")
-                    Shell.executeCommand("am force-stop $packageName")
+                    killProcessBlock()
                     cmdPackageCompile(packageName, "speed-profile")
                 } else {
                     if (baselineProfileMode == BaselineProfileMode.Require) {
@@ -430,7 +447,11 @@
     class Full : CompilationMode() {
         override fun toString(): String = "Full"
 
-        override fun compileImpl(packageName: String, warmupBlock: () -> Unit) {
+        override fun compileImpl(
+            packageName: String,
+            killProcessBlock: () -> Unit,
+            warmupBlock: () -> Unit
+        ) {
             if (Build.VERSION.SDK_INT >= 24) {
                 cmdPackageCompile(packageName, "speed")
             }
@@ -454,7 +475,11 @@
     object Interpreted : CompilationMode() {
         override fun toString(): String = "Interpreted"
 
-        override fun compileImpl(packageName: String, warmupBlock: () -> Unit) {
+        override fun compileImpl(
+            packageName: String,
+            killProcessBlock: () -> Unit,
+            warmupBlock: () -> Unit
+        ) {
             // Nothing to do - handled externally
         }
 
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
index 15fd52b..fbb5d40 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
@@ -136,7 +136,7 @@
     scope.killProcess()
 
     userspaceTrace("compile $packageName") {
-        compilationMode.resetAndCompile(packageName) {
+        compilationMode.resetAndCompile(packageName, killProcessBlock = scope::killProcess) {
             setupBlock(scope)
             measureBlock(scope)
         }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/dackka/GenerateMetadataTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/dackka/GenerateMetadataTask.kt
index be98b33..99964bf 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/dackka/GenerateMetadataTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/dackka/GenerateMetadataTask.kt
@@ -16,7 +16,8 @@
 
 package androidx.build.dackka
 
-import java.io.File
+import com.google.gson.Gson
+import java.io.FileWriter
 import org.gradle.api.DefaultTask
 import org.gradle.api.artifacts.component.ComponentArtifactIdentifier
 import org.gradle.api.artifacts.component.ModuleComponentIdentifier
@@ -27,7 +28,6 @@
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier
-import org.json.JSONArray
 
 @CacheableTask
 abstract class GenerateMetadataTask : DefaultTask() {
@@ -67,10 +67,9 @@
         }
 
         val jsonMapping = generateJsonMapping(entries)
-        val json = JSONArray(jsonMapping)
-
-        val outputFile = File(destinationFile.get().toString())
-        outputFile.writeText(json.toString(2))
+        val writer = FileWriter(destinationFile.get().toString())
+        Gson().toJson(jsonMapping, writer)
+        writer.close()
     }
 
     /**
diff --git a/buildSrc/shared.gradle b/buildSrc/shared.gradle
index a253d3d..7e4b0de 100644
--- a/buildSrc/shared.gradle
+++ b/buildSrc/shared.gradle
@@ -1,5 +1,3 @@
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
 apply plugin: "kotlin"
 apply from: "../kotlin-dsl-dependency.gradle"
 apply plugin: "java-gradle-plugin"
@@ -13,146 +11,49 @@
     }
 }
 
-configurations {
-    // Dependencies added to these configurations get copied into the corresponding configuration
-    // (cacheableApi gets copied into api, etc).
-    // Because we cache the resolutions of these configurations, performance is faster when
-    // artifacts are put into these configurations than when those artifacts are put into their
-    // corresponding configuration.
-    cacheableApi {
-        canBeConsumed = false // not directly used to satisfy a project dependency
-        attributes {
-            attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.class, Usage.JAVA_RUNTIME));
-            attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.class, Category.LIBRARY));
-            attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.class, LibraryElements.JAR));
-            attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.parseInt(JavaVersion.current().getMajorVersion()));
-            attribute(GradlePluginApiVersion.GRADLE_PLUGIN_API_VERSION_ATTRIBUTE, project.objects.named(GradlePluginApiVersion.class, GradleVersion.current().getVersion()));
-        }
-    }
-    cacheableImplementation {
-        canBeConsumed = false // not directly used to satisfy a project dependency
-        attributes {
-            attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.class, Usage.JAVA_RUNTIME));
-            attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.class, Category.LIBRARY));
-            attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.class, LibraryElements.JAR));
-            attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, Integer.parseInt(JavaVersion.current().getMajorVersion()));
-            attribute(GradlePluginApiVersion.GRADLE_PLUGIN_API_VERSION_ATTRIBUTE, project.objects.named(GradlePluginApiVersion.class, GradleVersion.current().getVersion()));
-        }
-        extendsFrom(project.configurations.cacheableApi)
-    }
-    cacheableRuntimeOnly {
-        canBeConsumed = false // not directly used to satisfy a project dependency
-    }
-}
-
 dependencies {
-    cacheableApi(libs.toml)
-    cacheableImplementation(libs.gson)
-    cacheableImplementation(libs.dom4j) {
+    implementation(project(":jetpad-integration"))
+
+    // Gradle APIs
+    implementation(gradleApi())
+    compileOnly(findGradleKotlinDsl())
+
+    // Plugins we use and configure
+    implementation(libs.androidGradlePluginz)
+    implementation(libs.androidToolsCommon) // for com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
+    implementation(libs.kotlinGradlePluginz)
+    implementation(libs.dokkaGradlePluginz)
+
+    // variety of json parsers
+    implementation(libs.gson)
+    implementation(libs.json) // b/241475613
+    implementation(libs.jsonSimple)
+
+    // XML parsers used in MavenUploadHelper.kt
+    implementation(libs.dom4j) {
         // Optional dependency where Ivy fails to parse the POM file.
         exclude(group:"net.java.dev.msv", module:"xsdlib")
     }
-    cacheableApi(libs.androidGradlePluginz)
-    // AGP has removes dependency on json-simple in http://b/239967984, so add explicitly
-    cacheableImplementation(libs.jsonSimple)
-    cacheableImplementation(libs.dexMemberList)
-    cacheableApi(libs.kotlinGradlePluginz)
-    cacheableImplementation(gradleApi())
-    cacheableApi(libs.dokkaGradlePluginz)
-    // needed by inspection plugin
-    cacheableImplementation(libs.protobufGradlePluginz)
-    cacheableImplementation(libs.wireGradlePluginz)
-    cacheableImplementation(libs.shadow)
+    implementation(libs.xerces)
+
+    implementation(libs.shadow) // used by BundleInsideHelper.kt
+    implementation(libs.apacheAnt) // used in AarManifestTransformerTask.kt for unziping
+    implementation(libs.toml)
+    implementation(libs.apacheCommonIo) // used in CheckApiEquivalenceTask.kt
+    implementation(libs.dexMemberList) // used in ReportLibraryMetricsTask.kt
+
+    implementation(libs.protobufGradlePluginz) // needed to compile inspection plugin
+    implementation(libs.kotlinPoet) // needed to compile material-icon-generator
+    implementation(libs.xmlpull) // needed to compile material-icon-generator
+
     // dependencies that aren't used by buildSrc directly but that we resolve here so that the
     // root project doesn't need to re-resolve them and their dependencies on every build
-    cacheableRuntimeOnly(libs.hiltAndroidGradlePluginz)
-    // Needed for hiltAndroidGradlePluginz to workaround https://github.com/google/dagger/issues/3068
-    cacheableApi(libs.javapoet)
-    // room kotlintestapp uses the ksp plugin but it does not publish a plugin marker yet
-    cacheableApi(libs.kspGradlePluginz)
-    // dependencies whose resolutions we don't need to cache
-    compileOnly(findGradleKotlinDsl()) // Only one file in this configuration, no need to cache it
-    implementation(project(":jetpad-integration")) // Doesn't have a .pom, so not slow to load
+    runtimeOnly(libs.hiltAndroidGradlePluginz)
+    runtimeOnly(libs.javapoet) // for hiltAndroidGradlePluginz to workaround https://github.com/google/dagger/issues/3068
+    runtimeOnly(libs.kspGradlePluginz)
+    runtimeOnly(libs.wireGradlePluginz)
 }
 
-// Saves configuration into destFile
-// Each line of destFile will be the absolute filepath of one of the files in configuration
-def saveConfigurationResolution(configuration, destFile) {
-    def resolvedConfiguration = configuration.resolvedConfiguration
-    def files = resolvedConfiguration.files
-    def paths = files.collect { f -> f.toString() }
-    def serialized = paths.join("\n")
-    destFile.text = serialized
-}
-
-// Parses a file into a list of Dependency objects representing a ResolvedConfiguration
-def parseConfigurationResolution(savedFile, throwOnError) {
-    def savedText = savedFile.text
-    def filenames = savedText.split("\n")
-    def valid = true
-    def dependencies = filenames.collect { filename ->
-        if (!project.file(filename).exists()) {
-            if (throwOnError) {
-                throw new GradleException("\nFile " + filename + " listed as a resolved dependency in " + savedFile + " does not exist!\n\nFor more information, see b/187075069")
-            } else {
-                valid = false
-            }
-        }
-        project.dependencies.create(project.files(filename))
-    }
-    if (!valid) {
-        return null
-    }
-    return dependencies
-}
-
-// Resolves a Configuration into a list of Dependency objects
-def resolveConfiguration(configuration) {
-    def resolvedName = configuration.name
-    def cacheDir = new File(project.rootProject.buildDir, "/" + resolvedName)
-    def inputsFile = new File(cacheDir, "/deps")
-    def outputsFile = new File(cacheDir, "/result")
-
-    def inputText = fingerprintConfiguration(configuration)
-    def parsed = null
-    if (inputsFile.exists() && inputsFile.text == inputText) {
-        // Try to parse the previously resolved configuration, but don't give up if it mentions a
-        // nonexistent file. If something has since deleted one of the referenced files, we will
-        // try to reresolve that file later
-        parsed = parseConfigurationResolution(outputsFile, false)
-    }
-    // If the configuration has changed or if any of its files have been deleted, reresolve it
-    if (parsed == null) {
-        cacheDir.mkdirs()
-        saveConfigurationResolution(configuration, outputsFile)
-        inputsFile.text = inputText
-        // confirm that the resolved configuration parses successfully
-        parsed = parseConfigurationResolution(outputsFile, true)
-    }
-    return parsed
-}
-
-// Computes a unique string from a Configuration based on its dependencies
-// This is used for up-to-date checks
-def fingerprintConfiguration(configuration) {
-    def dependencies = configuration.allDependencies
-    def dependencyTexts = dependencies.collect { dep -> dep.group + ":" + dep.name + ":" + dep.version }
-    return dependencyTexts.join("\n")
-}
-
-// Imports the contents of fromConf into toConf
-// Uses caching to often short-circuit the resolution of fromConf
-def loadConfigurationQuicklyInto(fromConf, toConf) {
-    def resolved = resolveConfiguration(fromConf)
-    resolved.each { dep ->
-        project.dependencies.add(toConf.name, dep)
-    }
-}
-
-loadConfigurationQuicklyInto(configurations.cacheableApi, configurations.api)
-loadConfigurationQuicklyInto(configurations.cacheableImplementation, configurations.implementation)
-loadConfigurationQuicklyInto(configurations.cacheableRuntimeOnly, configurations.runtimeOnly)
-
 project.tasks.withType(Jar) { task ->
     task.reproducibleFileOrder = true
     task.preserveFileTimestamps = false
diff --git a/camera/camera-core/src/main/cpp/opengl_renderer_jni.cpp b/camera/camera-core/src/main/cpp/opengl_renderer_jni.cpp
index 4e73b47..f12082d 100644
--- a/camera/camera-core/src/main/cpp/opengl_renderer_jni.cpp
+++ b/camera/camera-core/src/main/cpp/opengl_renderer_jni.cpp
@@ -409,6 +409,15 @@
         fragmentShaderSrc = env->GetStringUTFChars(jcustomFragmentShader, nullptr);
         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Custom fragment shader = %s",
                             fragmentShaderSrc);
+        // A simple check to workaround custom shader doesn't contain required variable.
+        // See b/241193761.
+        if (!strstr(fragmentShaderSrc, VAR_NAMES[0].c_str())) {
+            ThrowException(env, "java/lang/IllegalArgumentException", std::string(
+                    "Missing required variable '" + VAR_NAMES[0] +
+                    "' in the custom fragment shader").c_str());
+            env->ReleaseStringUTFChars(jcustomFragmentShader, fragmentShaderSrc);
+            return 0;
+        }
     } else {
         fragmentShaderSrc = FRAGMENT_SHADER_SRC.c_str();
     }
diff --git a/camera/integration-tests/uiwidgetstestapp/build.gradle b/camera/integration-tests/uiwidgetstestapp/build.gradle
index 2631c7c..4c8c5d1 100644
--- a/camera/integration-tests/uiwidgetstestapp/build.gradle
+++ b/camera/integration-tests/uiwidgetstestapp/build.gradle
@@ -111,4 +111,10 @@
     debugImplementation("androidx.fragment:fragment-testing:1.2.5")
     // Testing resource dependency for manifest
     debugImplementation(project(":camera:camera-testing"))
+
+    // Testing for Compose
+    // Test rules and transitive dependencies:
+    androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.1.1")
+    // Needed for createComposeRule, but not createAndroidComposeRule:
+    debugImplementation("androidx.compose.ui:ui-test-manifest:1.1.1")
 }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraAppTest.kt b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraAppTest.kt
new file mode 100644
index 0000000..1c5b3c1
--- /dev/null
+++ b/camera/integration-tests/uiwidgetstestapp/src/androidTest/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraAppTest.kt
@@ -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.camera.integration.uiwidgets.compose
+
+import android.os.Build
+import androidx.camera.integration.uiwidgets.compose.ui.navigation.ComposeCameraScreen
+import androidx.camera.view.PreviewView
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assertIsSelected
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ActivityScenario
+import androidx.test.filters.LargeTest
+import androidx.test.rule.GrantPermissionRule
+import androidx.testutils.RepeatRule
+import com.google.common.truth.Truth
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.runBlocking
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+class ComposeCameraAppTest {
+    // Provide permissions to app via ComposeCameraActivity
+    @get:Rule
+    val permissionRule: GrantPermissionRule =
+        GrantPermissionRule.grant(
+            *ComposeCameraActivity.REQUIRED_PERMISSIONS
+        )
+
+    @get: Rule
+    val androidComposeTestRule = createAndroidComposeRule<ComposeCameraActivity>()
+
+    @get: Rule
+    val repeatRule = RepeatRule()
+
+    @Before
+    fun setup() {
+        // Skip test for b/168175357
+        Assume.assumeFalse(
+            "Cuttlefish has MediaCodec dequeInput/Output buffer fails issue. Unable to test.",
+            Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 29
+        )
+
+        // Recreate the activity as it might terminate in other tests
+        androidComposeTestRule.activityRule.scenario.recreate()
+    }
+
+    // Activity launch will render ImageCaptureScreen
+    // Ensure that ImageCapture screen's PreviewView is streaming properly
+    @Test
+    @RepeatRule.Repeat(times = 10)
+    fun testPreviewViewStreamStateOnActivityLaunch() {
+        assertStreamState(
+            ComposeCameraScreen.ImageCapture,
+            PreviewView.StreamState.STREAMING,
+            androidComposeTestRule.activityRule.scenario
+        )
+    }
+
+    // Navigating from ImageCapture to VideoCapture screen
+    // Ensure that VideoCapture screen's PreviewView is streaming properly
+    @Test
+    @RepeatRule.Repeat(times = 10)
+    fun testPreviewViewStreamStateOnNavigation() {
+
+        // Get VideoCapture Navigation Tab (Node)
+        val node = androidComposeTestRule.onNode(
+            SemanticsMatcher.expectValue(
+                SemanticsProperties.Role, Role.Tab,
+            ).and(
+                SemanticsMatcher.expectValue(
+                    SemanticsProperties.ContentDescription,
+                    listOf("VideoCapture")
+                )
+            )
+        )
+
+        // Ensure that Tab is selected after we click on it
+        node.performClick().assertIsSelected()
+
+        // Assert VideoCapture's PreviewView is streaming
+        assertStreamState(
+            ComposeCameraScreen.VideoCapture,
+            PreviewView.StreamState.STREAMING,
+            androidComposeTestRule.activityRule.scenario
+        )
+    }
+
+    // Asserts that the StreamState in the ComposeCameraScreen reaches
+    // expectedState within a reasonable timeout
+    private fun assertStreamState(
+        expectedScreen: ComposeCameraScreen,
+        expectedState: PreviewView.StreamState,
+        scenario: ActivityScenario<ComposeCameraActivity>,
+    ) = runBlocking<Unit> {
+        lateinit var result: Deferred<Boolean>
+
+        scenario.onActivity { activity ->
+            // Make async Coroutine to wait the result, not block the test thread.
+            result = async {
+                activity.waitForStreamState(
+                    expectedScreen = expectedScreen,
+                    expectedState = expectedState
+                )
+            }
+        }
+
+        Truth.assertThat(result.await()).isTrue()
+    }
+
+    companion object {
+        private const val TAG = "ComposeCameraAppTest"
+    }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraActivity.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraActivity.kt
index 3837653..3b500f3 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraActivity.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ComposeCameraActivity.kt
@@ -20,13 +20,24 @@
 import android.content.pm.PackageManager
 import android.os.Build
 import android.os.Bundle
+import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.camera.integration.uiwidgets.compose.ui.ComposeCameraApp
 import androidx.camera.integration.uiwidgets.compose.ui.PermissionsUI
+import androidx.camera.integration.uiwidgets.compose.ui.navigation.ComposeCameraScreen
+import androidx.camera.view.PreviewView.StreamState
 import androidx.core.content.ContextCompat
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 
 class ComposeCameraActivity : ComponentActivity() {
+
+    // Variables for testing StreamState changes in PreviewView
+    private var expectedScreen: ComposeCameraScreen = ComposeCameraScreen.ImageCapture
+    private var expectedStreamState: StreamState = StreamState.STREAMING
+    private var latchForState: CountDownLatch = CountDownLatch(0)
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContent {
@@ -36,7 +47,7 @@
                     checkAllPermissionsGranted(it)
                 }
             ) {
-                ComposeCameraApp()
+                ComposeCameraApp(onStreamStateChange = this::onStreamStateChange)
             }
         }
     }
@@ -47,7 +58,49 @@
         }
     }
 
+    // Saves the expected ComposeCameraScreen and StreamState for testing PreviewView
+    // Once saved, this method waits to be notified of StreamState changes
+    // Used to assert that PreviewView is streaming within reasonable timeout
+    fun waitForStreamState(
+        expectedScreen: ComposeCameraScreen,
+        expectedState: StreamState
+    ): Boolean {
+        this.expectedScreen = expectedScreen
+        expectedStreamState = expectedState
+        latchForState = CountDownLatch(1)
+        return latchForState.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS)
+    }
+
+    // Callback to observe changes in PreviewView.StreamState happening in some ComposeCameraScreen
+    // Used to observe changes in StreamState when Composables render (during testing)
+    private fun onStreamStateChange(screen: ComposeCameraScreen, streamState: StreamState) {
+        // StreamState change not coming from expected screen
+        if (screen != expectedScreen) {
+            return
+        }
+
+        when (streamState) {
+            StreamState.STREAMING -> {
+                Log.d(TAG, "PreviewView.StreamState.STREAMING from ${screen.name}")
+                if (expectedStreamState == StreamState.STREAMING) {
+                    latchForState.countDown()
+                }
+            }
+            StreamState.IDLE -> {
+                Log.d(TAG, "PreviewView.StreamState.IDLE in ${screen.name}")
+                if (expectedStreamState == StreamState.IDLE) {
+                    latchForState.countDown()
+                }
+            }
+            else -> {
+                Log.e(TAG, "Wrong PreviewView.StreamState in ${screen.name}! Return IDLE")
+            }
+        }
+    }
+
     companion object {
+        private const val TAG = "ComposeCameraActivity"
+        private const val LATCH_TIMEOUT: Long = 5000
         val REQUIRED_PERMISSIONS = mutableListOf(
             Manifest.permission.CAMERA,
             Manifest.permission.RECORD_AUDIO
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/ComposeCameraApp.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/ComposeCameraApp.kt
index 026ee4d..326bf36 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/ComposeCameraApp.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/ComposeCameraApp.kt
@@ -19,6 +19,7 @@
 import androidx.camera.integration.uiwidgets.compose.ui.navigation.ComposeCameraNavHost
 import androidx.camera.integration.uiwidgets.compose.ui.navigation.ComposeCameraScreen
 import androidx.camera.integration.uiwidgets.compose.ui.screen.components.ComposeCameraScreenTabRow
+import androidx.camera.view.PreviewView
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.MaterialTheme
 import androidx.compose.material.Scaffold
@@ -27,8 +28,11 @@
 import androidx.navigation.compose.currentBackStackEntryAsState
 import androidx.navigation.compose.rememberNavController
 
+// Provides callback when StreamState changes in a ComposeCameraScreen
 @Composable
-fun ComposeCameraApp() {
+fun ComposeCameraApp(
+    onStreamStateChange: (ComposeCameraScreen, PreviewView.StreamState) -> Unit = { _, _ -> }
+) {
     MaterialTheme {
         val allScreens = ComposeCameraScreen.values().toList()
         val navController = rememberNavController()
@@ -51,7 +55,8 @@
         ) { innerPadding ->
             ComposeCameraNavHost(
                 navController = navController,
-                modifier = Modifier.padding(innerPadding)
+                modifier = Modifier.padding(innerPadding),
+                onStreamStateChange = onStreamStateChange
             )
         }
     }
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/navigation/ComposeCameraNavHost.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/navigation/ComposeCameraNavHost.kt
index 0f0927f..d91fc70 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/navigation/ComposeCameraNavHost.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/navigation/ComposeCameraNavHost.kt
@@ -18,16 +18,20 @@
 
 import androidx.camera.integration.uiwidgets.compose.ui.screen.imagecapture.ImageCaptureScreen
 import androidx.camera.integration.uiwidgets.compose.ui.screen.videocapture.VideoCaptureScreen
+import androidx.camera.view.PreviewView
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.navigation.NavHostController
 import androidx.navigation.compose.NavHost
 import androidx.navigation.compose.composable
 
+// Provides the ComposeCameraScreen needed for onStreamStateChange
+// The Screen-level Composable will provide the StreamState changes
 @Composable
 fun ComposeCameraNavHost(
     navController: NavHostController,
-    modifier: Modifier = Modifier
+    modifier: Modifier = Modifier,
+    onStreamStateChange: (ComposeCameraScreen, PreviewView.StreamState) -> Unit = { _, _ -> }
 ) {
     NavHost(
         navController = navController,
@@ -35,11 +39,25 @@
         modifier = modifier
     ) {
         composable(ComposeCameraScreen.ImageCapture.name) {
-            ImageCaptureScreen()
+            ImageCaptureScreen(
+                onStreamStateChange = { state ->
+                    onStreamStateChange(
+                        ComposeCameraScreen.ImageCapture,
+                        state
+                    )
+                }
+            )
         }
 
         composable(ComposeCameraScreen.VideoCapture.name) {
-            VideoCaptureScreen()
+            VideoCaptureScreen(
+                onStreamStateChange = { state ->
+                    onStreamStateChange(
+                        ComposeCameraScreen.VideoCapture,
+                        state
+                    )
+                }
+            )
         }
     }
 }
\ No newline at end of file
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreen.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreen.kt
index 4cf4fe8..4b4ed18 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreen.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreen.kt
@@ -17,6 +17,7 @@
 package androidx.camera.integration.uiwidgets.compose.ui.screen.imagecapture
 
 import android.graphics.Rect
+import android.util.Log
 import android.view.ViewGroup
 import androidx.camera.core.MeteringPoint
 import androidx.camera.core.Preview.SurfaceProvider
@@ -57,6 +58,9 @@
 import androidx.compose.ui.platform.LocalLifecycleOwner
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
+import androidx.lifecycle.Observer
+
+private const val TAG = "ImageCaptureScreen"
 
 // ImageCaptureScreen with QR-Code Overlay (Supports Preview + ImageCapture + ImageAnalysis)
 // Screen provides ImageCapture functionality and draws a bounding box around a detected QR Code
@@ -66,7 +70,8 @@
 @Composable
 fun ImageCaptureScreen(
     modifier: Modifier = Modifier,
-    state: ImageCaptureScreenState = rememberImageCaptureScreenState()
+    state: ImageCaptureScreenState = rememberImageCaptureScreenState(),
+    onStreamStateChange: (PreviewView.StreamState) -> Unit = {}
 ) {
     val lifecycleOwner = LocalLifecycleOwner.current
     val localContext = LocalContext.current
@@ -75,13 +80,6 @@
         state.startCamera(context = localContext, lifecycleOwner = lifecycleOwner)
     }
 
-    // Release resources when the Composable is removed from the Composition
-    DisposableEffect(Unit) {
-        onDispose {
-            state.releaseResources()
-        }
-    }
-
     ImageCaptureScreen(
         modifier = modifier,
         zoomRatio = state.zoomRatio,
@@ -97,7 +95,9 @@
         },
         onSurfaceProviderReady = state::setSurfaceProvider,
         onOutputTransformReady = state::setOutputTransform,
-        onTouch = state::startTapToFocus
+        onTouch = state::startTapToFocus,
+        onStreamStateChange = onStreamStateChange,
+        onDispose = state::releaseResources
     ) {
         // Uses overlay to draw detected QRCode in the image stream
         QRCodeOverlay(qrCodeBoundingBox = state.qrCodeBoundingBox)
@@ -121,10 +121,19 @@
     onSurfaceProviderReady: (SurfaceProvider) -> Unit,
     onOutputTransformReady: (OutputTransform) -> Unit,
     onTouch: (MeteringPoint) -> Unit,
+    onStreamStateChange: (PreviewView.StreamState) -> Unit = {},
+    onDispose: () -> Unit = {},
     content: @Composable () -> Unit = {} // overlay to display something above PreviewView
 ) {
+    val lifecycleOwner = LocalLifecycleOwner.current
     val localContext = LocalContext.current
 
+    val streamStateObserver = remember {
+        Observer<PreviewView.StreamState> { state ->
+            onStreamStateChange(state)
+        }
+    }
+
     // Saving an instance of PreviewView outside of AndroidView
     // This allows us to access properties of PreviewView (e.g. ViewPort and OutputTransform)
     // Allows us to support functionalities such as UseCaseGroup in bindToLifecycle()
@@ -151,6 +160,24 @@
         }
     }
 
+    // Attach StreamState Observer when the screen first renders
+    DisposableEffect(key1 = Unit) {
+        Log.d(TAG, "[DisposableEffect] Detaching StreamState Observers from PreviewView")
+        previewView.previewStreamState.removeObservers(lifecycleOwner)
+
+        Log.d(TAG, "[DisposableEffect] Attaching StreamState Observer to PreviewView")
+        previewView.previewStreamState.observe(lifecycleOwner, streamStateObserver)
+
+        // Detach observer when the screen is removed from the Composition
+        onDispose {
+            Log.d(TAG, "[onDispose] Detaching current StreamState Observer from PreviewView")
+            previewView.previewStreamState.removeObservers(lifecycleOwner)
+
+            // Clean up resources when PreviewView is removed from the composition
+            onDispose()
+        }
+    }
+
     // Provides OutputTransform when PreviewView is attached on the screen
     LaunchedEffect(key1 = previewView.outputTransform) {
         if (previewView.outputTransform != null) {
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreenState.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreenState.kt
index 4f77685..cd0aa98 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreenState.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/imagecapture/ImageCaptureScreenState.kt
@@ -295,7 +295,9 @@
     }
 
     // Method to release resources when the Screen is removed from the Composition
+    // We will release the ImageAnalyzer from ImageAnalysis use case and close the analyzer
     fun releaseResources() {
+        imageAnalysis.clearAnalyzer()
         barcodeScanner.close()
     }
 
diff --git a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/videocapture/VideoCaptureScreen.kt b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/videocapture/VideoCaptureScreen.kt
index acc60e6..5bb0aae 100644
--- a/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/videocapture/VideoCaptureScreen.kt
+++ b/camera/integration-tests/uiwidgetstestapp/src/main/java/androidx/camera/integration/uiwidgets/compose/ui/screen/videocapture/VideoCaptureScreen.kt
@@ -16,6 +16,7 @@
 
 package androidx.camera.integration.uiwidgets.compose.ui.screen.videocapture
 
+import android.util.Log
 import android.view.ViewGroup
 import androidx.camera.core.MeteringPoint
 import androidx.camera.core.Preview.SurfaceProvider
@@ -39,6 +40,7 @@
 import androidx.compose.material.icons.sharp.FlipCameraAndroid
 import androidx.compose.material.icons.sharp.Lens
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
@@ -48,11 +50,15 @@
 import androidx.compose.ui.platform.LocalLifecycleOwner
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
+import androidx.lifecycle.Observer
+
+private const val TAG = "VideoCaptureScreen"
 
 @Composable
 fun VideoCaptureScreen(
     modifier: Modifier = Modifier,
-    state: VideoCaptureScreenState = rememberVideoCaptureScreenState()
+    state: VideoCaptureScreenState = rememberVideoCaptureScreenState(),
+    onStreamStateChange: (PreviewView.StreamState) -> Unit = {}
 ) {
     val lifecycleOwner = LocalLifecycleOwner.current
     val localContext = LocalContext.current
@@ -74,7 +80,8 @@
             state.captureVideo(localContext)
         },
         onSurfaceProviderReady = state::setSurfaceProvider,
-        onTouch = state::startTapToFocus
+        onTouch = state::startTapToFocus,
+        onStreamStateChange = onStreamStateChange
     )
 }
 
@@ -90,10 +97,18 @@
     onFlipCameraIconClicked: () -> Unit,
     onVideoCaptureIconClicked: () -> Unit,
     onSurfaceProviderReady: (SurfaceProvider) -> Unit,
-    onTouch: (MeteringPoint) -> Unit
+    onTouch: (MeteringPoint) -> Unit,
+    onStreamStateChange: (PreviewView.StreamState) -> Unit = {}
 ) {
+    val lifecycleOwner = LocalLifecycleOwner.current
     val localContext = LocalContext.current
 
+    val streamStateObserver = remember {
+        Observer<PreviewView.StreamState> { state ->
+            onStreamStateChange(state)
+        }
+    }
+
     val previewView = remember {
         PreviewView(localContext).apply {
             layoutParams = ViewGroup.LayoutParams(
@@ -113,6 +128,21 @@
         }
     }
 
+    // Attach StreamState Observer when the screen first renders
+    DisposableEffect(key1 = Unit) {
+        Log.d(TAG, "[DisposableEffect] Detaching StreamState Observers from PreviewView")
+        previewView.previewStreamState.removeObservers(lifecycleOwner)
+
+        Log.d(TAG, "[DisposableEffect] Attaching StreamState Observer to PreviewView")
+        previewView.previewStreamState.observe(lifecycleOwner, streamStateObserver)
+
+        // Detach observer when the screen is removed from the Composition
+        onDispose {
+            Log.d(TAG, "[onDispose] Detaching current StreamState Observer from PreviewView")
+            previewView.previewStreamState.removeObservers(lifecycleOwner)
+        }
+    }
+
     Box(modifier = modifier.fillMaxSize()) {
         AndroidView(
             factory = { previewView }
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 8f2297c..34cfdbc 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -33,11 +33,11 @@
     method public final androidx.car.app.HostInfo? getHostInfo();
     method public final androidx.car.app.Session? getSession(androidx.car.app.SessionInfo);
     method @CallSuper public final android.os.IBinder onBind(android.content.Intent);
-    method @Deprecated public androidx.car.app.Session onCreateSession();
-    method public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
+    method public androidx.car.app.Session onCreateSession();
+    method @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
     method public final boolean onUnbind(android.content.Intent);
     field @Deprecated public static final String CATEGORY_CHARGING_APP = "androidx.car.app.category.CHARGING";
-    field public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
+    field @androidx.car.app.annotations.RequiresCarApi(6) public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
     field public static final String CATEGORY_NAVIGATION_APP = "androidx.car.app.category.NAVIGATION";
     field @Deprecated public static final String CATEGORY_PARKING_APP = "androidx.car.app.category.PARKING";
     field public static final String CATEGORY_POI_APP = "androidx.car.app.category.POI";
@@ -158,7 +158,7 @@
     method public void onNewIntent(android.content.Intent);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(5) public class SessionInfo {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class SessionInfo {
     ctor public SessionInfo(int, String);
     method public int getDisplayType();
     method public String getSessionId();
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index 77984e8..2062816 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -33,11 +33,11 @@
     method public final androidx.car.app.HostInfo? getHostInfo();
     method public final androidx.car.app.Session? getSession(androidx.car.app.SessionInfo);
     method @CallSuper public final android.os.IBinder onBind(android.content.Intent);
-    method @Deprecated public androidx.car.app.Session onCreateSession();
-    method public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
+    method public androidx.car.app.Session onCreateSession();
+    method @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
     method public final boolean onUnbind(android.content.Intent);
     field @Deprecated public static final String CATEGORY_CHARGING_APP = "androidx.car.app.category.CHARGING";
-    field public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
+    field @androidx.car.app.annotations.RequiresCarApi(6) public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
     field public static final String CATEGORY_NAVIGATION_APP = "androidx.car.app.category.NAVIGATION";
     field @Deprecated public static final String CATEGORY_PARKING_APP = "androidx.car.app.category.PARKING";
     field public static final String CATEGORY_POI_APP = "androidx.car.app.category.POI";
@@ -159,7 +159,7 @@
     method public void onNewIntent(android.content.Intent);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(5) public class SessionInfo {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class SessionInfo {
     ctor public SessionInfo(int, String);
     method public int getDisplayType();
     method public String getSessionId();
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 8f2297c..34cfdbc 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -33,11 +33,11 @@
     method public final androidx.car.app.HostInfo? getHostInfo();
     method public final androidx.car.app.Session? getSession(androidx.car.app.SessionInfo);
     method @CallSuper public final android.os.IBinder onBind(android.content.Intent);
-    method @Deprecated public androidx.car.app.Session onCreateSession();
-    method public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
+    method public androidx.car.app.Session onCreateSession();
+    method @androidx.car.app.annotations.RequiresCarApi(6) public androidx.car.app.Session onCreateSession(androidx.car.app.SessionInfo);
     method public final boolean onUnbind(android.content.Intent);
     field @Deprecated public static final String CATEGORY_CHARGING_APP = "androidx.car.app.category.CHARGING";
-    field public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
+    field @androidx.car.app.annotations.RequiresCarApi(6) public static final String CATEGORY_FEATURE_CLUSTER = "androidx.car.app.category.FEATURE_CLUSTER";
     field public static final String CATEGORY_NAVIGATION_APP = "androidx.car.app.category.NAVIGATION";
     field @Deprecated public static final String CATEGORY_PARKING_APP = "androidx.car.app.category.PARKING";
     field public static final String CATEGORY_POI_APP = "androidx.car.app.category.POI";
@@ -158,7 +158,7 @@
     method public void onNewIntent(android.content.Intent);
   }
 
-  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(5) public class SessionInfo {
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(6) public class SessionInfo {
     ctor public SessionInfo(int, String);
     method public int getDisplayType();
     method public String getSessionId();
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppService.java b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
index a55db0b..3da6251 100644
--- a/car/app/app/src/main/java/androidx/car/app/CarAppService.java
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
@@ -31,6 +31,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.car.app.annotations.ExperimentalCarApi;
+import androidx.car.app.annotations.RequiresCarApi;
 import androidx.car.app.validation.HostValidator;
 
 import java.io.FileDescriptor;
@@ -90,6 +91,7 @@
     /**
      * Used to declare that this app supports cluster in the manifest.
      */
+    @RequiresCarApi(6)
     public static final String CATEGORY_FEATURE_CLUSTER =
             "androidx.car.app.category.FEATURE_CLUSTER";
 
@@ -253,12 +255,8 @@
      * <p>Called by the system, do not call this method directly.
      *
      * @see CarContext#startCarApp(Intent)
-     * @deprecated this method continues to exist for backwards compatibility; however, is
-     * succeeded by {@link #onCreateSession(SessionInfo)}. Prefer to implement {@link
-     * #onCreateSession(SessionInfo)}.
      */
     @NonNull
-    @Deprecated
     public Session onCreateSession() {
         throw new RuntimeException(
                 "Please override and implement CarAppService#onCreateSession(SessionInfo).");
@@ -280,6 +278,7 @@
      */
     @NonNull
     @SuppressWarnings("deprecation")
+    @RequiresCarApi(6)
     public Session onCreateSession(@NonNull SessionInfo sessionInfo) {
         return onCreateSession();
     }
diff --git a/car/app/app/src/main/java/androidx/car/app/SessionInfo.java b/car/app/app/src/main/java/androidx/car/app/SessionInfo.java
index 3176923..ce2f647 100644
--- a/car/app/app/src/main/java/androidx/car/app/SessionInfo.java
+++ b/car/app/app/src/main/java/androidx/car/app/SessionInfo.java
@@ -36,7 +36,7 @@
 import java.util.Set;
 
 /** Information about a {@link Session}, such as the physical display and the session ID. */
-@RequiresCarApi(5)
+@RequiresCarApi(6)
 @CarProtocol
 public class SessionInfo {
     private static final char DIVIDER = '/';
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index 74fa853..9982e90 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -208,13 +208,13 @@
   }
 
   public final class ChipKt {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.material3.ChipColors colors);
-    method @androidx.compose.material3.ExperimentalMaterial3Api @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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.material3.ChipColors colors);
-    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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.material3.SelectableChipColors colors);
-    method @androidx.compose.material3.ExperimentalMaterial3Api @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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.material3.ChipColors colors);
-    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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.material3.SelectableChipColors colors);
-    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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.SelectableChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SelectableChipBorder? border, optional androidx.compose.material3.SelectableChipColors colors);
-    method @androidx.compose.material3.ExperimentalMaterial3Api @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.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.ChipElevation? elevation, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.ChipBorder? border, optional androidx.compose.material3.ChipColors colors);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @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.material3.ExperimentalMaterial3Api @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.material3.ExperimentalMaterial3Api @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.material3.ExperimentalMaterial3Api @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 {
@@ -601,12 +601,12 @@
   }
 
   public final class NavigationDrawerKt {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DismissibleDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, 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 DismissibleDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, 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 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.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ModalDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, 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 ModalDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, 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 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.material3.ExperimentalMaterial3Api @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.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PermanentDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, 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 PermanentDrawerSheet(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape drawerShape, optional long drawerContainerColor, optional long drawerContentColor, optional float drawerTonalElevation, 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 PermanentNavigationDrawer(kotlin.jvm.functions.Function0<kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.material3.ExperimentalMaterial3Api @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);
   }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Chip.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Chip.kt
index 71ae1a7..a66ff79 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Chip.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Chip.kt
@@ -87,19 +87,19 @@
  * services.
  * @param leadingIcon optional icon at the start of the chip, preceding the [label] text
  * @param trailingIcon optional icon at the end of the chip
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
+ * different states. See [AssistChipDefaults.assistChipColors].
  * @param elevation [ChipElevation] used to resolve the elevation for this chip in different states.
  * This controls the size of the shadow below the chip. Additionally, when the container color is
  * [ColorScheme.surface], this controls the amount of primary color applied as an overlay. See
  * [AssistChipDefaults.assistChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip. Pass `null` for no border.
  * See [AssistChipDefaults.assistChipBorder].
- * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
- * different states. See [AssistChipDefaults.assistChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -110,11 +110,11 @@
     enabled: Boolean = true,
     leadingIcon: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: ChipElevation? = AssistChipDefaults.assistChipElevation(),
     shape: Shape = AssistChipDefaults.shape,
+    colors: ChipColors = AssistChipDefaults.assistChipColors(),
+    elevation: ChipElevation? = AssistChipDefaults.assistChipElevation(),
     border: ChipBorder? = AssistChipDefaults.assistChipBorder(),
-    colors: ChipColors = AssistChipDefaults.assistChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) = Chip(
     modifier = modifier,
     onClick = onClick,
@@ -124,12 +124,12 @@
     labelColor = colors.labelColor(enabled).value,
     leadingIcon = leadingIcon,
     trailingIcon = trailingIcon,
-    elevation = elevation,
+    shape = shape,
     colors = colors,
+    elevation = elevation,
+    border = border?.borderStroke(enabled)?.value,
     minHeight = AssistChipDefaults.Height,
     paddingValues = AssistChipPadding,
-    shape = shape,
-    border = border?.borderStroke(enabled)?.value,
     interactionSource = interactionSource
 )
 
@@ -160,18 +160,18 @@
  * services.
  * @param leadingIcon optional icon at the start of the chip, preceding the [label] text
  * @param trailingIcon optional icon at the end of the chip
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
+ * different states. See [AssistChipDefaults.elevatedAssistChipColors].
  * @param elevation [ChipElevation] used to resolve the elevation for this chip in different states.
  * This controls the size of the shadow below the chip. Additionally, when the container color is
  * [ColorScheme.surface], this controls the amount of primary color applied as an overlay. See
  * [AssistChipDefaults.elevatedAssistChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip
- * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
- * different states. See [AssistChipDefaults.elevatedAssistChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -182,11 +182,11 @@
     enabled: Boolean = true,
     leadingIcon: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: ChipElevation? = AssistChipDefaults.elevatedAssistChipElevation(),
     shape: Shape = AssistChipDefaults.shape,
+    colors: ChipColors = AssistChipDefaults.elevatedAssistChipColors(),
+    elevation: ChipElevation? = AssistChipDefaults.elevatedAssistChipElevation(),
     border: ChipBorder? = null,
-    colors: ChipColors = AssistChipDefaults.elevatedAssistChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
 ) = Chip(
     modifier = modifier,
     onClick = onClick,
@@ -240,19 +240,19 @@
  * [selected] is true, this icon may visually indicate that the chip is selected (for example, via a
  * checkmark icon).
  * @param trailingIcon optional icon at the end of the chip
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [SelectableChipColors] that will be used to resolve the colors used for this chip
+ * in different states. See [FilterChipDefaults.filterChipColors].
  * @param elevation [SelectableChipElevation] used to resolve the elevation for this chip in
  * different states. This controls the size of the shadow below the chip. Additionally, when the
  * container color is [ColorScheme.surface], this controls the amount of primary color applied as an
  * overlay. See [FilterChipDefaults.filterChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip. Pass `null` for no border.
  * See [FilterChipDefaults.filterChipBorder].
- * @param colors [SelectableChipColors] that will be used to resolve the colors used for this chip
- * in different states. See [FilterChipDefaults.filterChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -264,11 +264,11 @@
     enabled: Boolean = true,
     leadingIcon: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: SelectableChipElevation? = FilterChipDefaults.filterChipElevation(),
     shape: Shape = FilterChipDefaults.shape,
+    colors: SelectableChipColors = FilterChipDefaults.filterChipColors(),
+    elevation: SelectableChipElevation? = FilterChipDefaults.filterChipElevation(),
     border: SelectableChipBorder? = FilterChipDefaults.filterChipBorder(),
-    colors: SelectableChipColors = FilterChipDefaults.filterChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
 ) = SelectableChip(
     selected = selected,
     modifier = modifier,
@@ -320,19 +320,19 @@
  * [selected] is true, this icon may visually indicate that the chip is selected (for example, via a
  * checkmark icon).
  * @param trailingIcon optional icon at the end of the chip
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [SelectableChipColors] that will be used to resolve the colors used for this chip
+ * in different states. See [FilterChipDefaults.elevatedFilterChipColors].
  * @param elevation [SelectableChipElevation] used to resolve the elevation for this chip in
  * different states. This controls the size of the shadow below the chip. Additionally, when the
  * container color is [ColorScheme.surface], this controls the amount of primary color applied as an
  * overlay. See [FilterChipDefaults.filterChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip. Pass `null` for no border.
  * See [FilterChipDefaults.filterChipBorder].
- * @param colors [SelectableChipColors] that will be used to resolve the colors used for this chip
- * in different states. See [FilterChipDefaults.elevatedFilterChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -344,11 +344,11 @@
     enabled: Boolean = true,
     leadingIcon: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: SelectableChipElevation? = FilterChipDefaults.elevatedFilterChipElevation(),
     shape: Shape = FilterChipDefaults.shape,
+    colors: SelectableChipColors = FilterChipDefaults.elevatedFilterChipColors(),
+    elevation: SelectableChipElevation? = FilterChipDefaults.elevatedFilterChipElevation(),
     border: SelectableChipBorder? = null,
-    colors: SelectableChipColors = FilterChipDefaults.elevatedFilterChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
 ) = SelectableChip(
     selected = selected,
     modifier = modifier,
@@ -404,19 +404,19 @@
  * @param leadingIcon optional icon at the start of the chip, preceding the [label] text
  * @param avatar optional avatar at the start of the chip, preceding the [label] text
  * @param trailingIcon optional icon at the end of the chip
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
+ * different states. See [InputChipDefaults.inputChipColors].
  * @param elevation [ChipElevation] used to resolve the elevation for this chip in different states.
  * This controls the size of the shadow below the chip. Additionally, when the container color is
  * [ColorScheme.surface], this controls the amount of primary color applied as an overlay. See
  * [InputChipDefaults.inputChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip. Pass `null` for no border.
  * See [InputChipDefaults.inputChipBorder].
- * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
- * different states. See [InputChipDefaults.inputChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -429,11 +429,11 @@
     leadingIcon: @Composable (() -> Unit)? = null,
     avatar: @Composable (() -> Unit)? = null,
     trailingIcon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: SelectableChipElevation? = InputChipDefaults.inputChipElevation(),
     shape: Shape = InputChipDefaults.shape,
+    colors: SelectableChipColors = InputChipDefaults.inputChipColors(),
+    elevation: SelectableChipElevation? = InputChipDefaults.inputChipElevation(),
     border: SelectableChipBorder? = InputChipDefaults.inputChipBorder(),
-    colors: SelectableChipColors = InputChipDefaults.inputChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) {
     // If given, place the avatar in an InputChipTokens.AvatarShape shape before passing it into the
     // Chip function.
@@ -464,16 +464,16 @@
         leadingIcon = leadingIcon,
         avatar = shapedAvatar,
         trailingIcon = trailingIcon,
-        elevation = elevation,
+        shape = shape,
         colors = colors,
+        elevation = elevation,
+        border = border?.borderStroke(enabled, selected)?.value,
         minHeight = InputChipDefaults.Height,
         paddingValues = inputChipPadding(
             hasAvatar = shapedAvatar != null,
             hasLeadingIcon = leadingIcon != null,
             hasTrailingIcon = trailingIcon != null
         ),
-        shape = shape,
-        border = border?.borderStroke(enabled, selected)?.value,
         interactionSource = interactionSource
     )
 }
@@ -503,19 +503,19 @@
  * respond to user input, and it will appear visually disabled and disabled to accessibility
  * services.
  * @param icon optional icon at the start of the chip, preceding the [label] text
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
+ * different states. See [SuggestionChipDefaults.suggestionChipColors].
  * @param elevation [ChipElevation] used to resolve the elevation for this chip in different states.
  * This controls the size of the shadow below the chip. Additionally, when the container color is
  * [ColorScheme.surface], this controls the amount of primary color applied as an overlay. See
  * [SuggestionChipDefaults.suggestionChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip. Pass `null` for no border.
  * See [SuggestionChipDefaults.suggestionChipBorder].
- * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
- * different states. See [SuggestionChipDefaults.suggestionChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -525,11 +525,11 @@
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
     icon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: ChipElevation? = SuggestionChipDefaults.suggestionChipElevation(),
     shape: Shape = SuggestionChipDefaults.shape,
+    colors: ChipColors = SuggestionChipDefaults.suggestionChipColors(),
+    elevation: ChipElevation? = SuggestionChipDefaults.suggestionChipElevation(),
     border: ChipBorder? = SuggestionChipDefaults.suggestionChipBorder(),
-    colors: ChipColors = SuggestionChipDefaults.suggestionChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) = Chip(
     modifier = modifier,
     onClick = onClick,
@@ -539,12 +539,12 @@
     labelColor = colors.labelColor(enabled).value,
     leadingIcon = icon,
     trailingIcon = null,
-    elevation = elevation,
+    shape = shape,
     colors = colors,
+    elevation = elevation,
+    border = border?.borderStroke(enabled)?.value,
     minHeight = SuggestionChipDefaults.Height,
     paddingValues = SuggestionChipPadding,
-    shape = shape,
-    border = border?.borderStroke(enabled)?.value,
     interactionSource = interactionSource
 )
 
@@ -573,18 +573,18 @@
  * respond to user input, and it will appear visually disabled and disabled to accessibility
  * services.
  * @param icon optional icon at the start of the chip, preceding the [label] text
- * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
- * for this chip. You can create and pass in your own `remember`ed instance to observe
- * [Interaction]s and customize the appearance / behavior of this chip in different states.
+ * @param shape defines the shape of this chip's container, border (when [border] is not null), and
+ * shadow (when using [elevation])
+ * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
  * @param elevation [ChipElevation] used to resolve the elevation for this chip in different states.
  * This controls the size of the shadow below the chip. Additionally, when the container color is
  * [ColorScheme.surface], this controls the amount of primary color applied as an overlay. See
  * [Surface] and [SuggestionChipDefaults.elevatedSuggestionChipElevation].
- * @param shape defines the shape of this chip's container, border (when [border] is not null), and
- * shadow (when using [elevation])
  * @param border the border to draw around the container of this chip
- * @param colors [ChipColors] that will be used to resolve the colors used for this chip in
  * different states. See [SuggestionChipDefaults.elevatedSuggestionChipColors].
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this chip. You can create and pass in your own `remember`ed instance to observe
+ * [Interaction]s and customize the appearance / behavior of this chip in different states.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -594,11 +594,11 @@
     modifier: Modifier = Modifier,
     enabled: Boolean = true,
     icon: @Composable (() -> Unit)? = null,
-    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
-    elevation: ChipElevation? = SuggestionChipDefaults.elevatedSuggestionChipElevation(),
     shape: Shape = SuggestionChipDefaults.shape,
+    colors: ChipColors = SuggestionChipDefaults.elevatedSuggestionChipColors(),
+    elevation: ChipElevation? = SuggestionChipDefaults.elevatedSuggestionChipElevation(),
     border: ChipBorder? = null,
-    colors: ChipColors = SuggestionChipDefaults.elevatedSuggestionChipColors()
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
 ) = Chip(
     modifier = modifier,
     onClick = onClick,
@@ -1637,12 +1637,12 @@
     labelColor: Color,
     leadingIcon: @Composable (() -> Unit)?,
     trailingIcon: @Composable (() -> Unit)?,
-    elevation: ChipElevation?,
+    shape: Shape,
     colors: ChipColors,
+    elevation: ChipElevation?,
+    border: BorderStroke?,
     minHeight: Dp,
     paddingValues: PaddingValues,
-    shape: Shape,
-    border: BorderStroke?,
     interactionSource: MutableInteractionSource,
 ) {
     Surface(
@@ -1683,12 +1683,12 @@
     leadingIcon: @Composable (() -> Unit)?,
     avatar: @Composable (() -> Unit)?,
     trailingIcon: @Composable (() -> Unit)?,
-    elevation: SelectableChipElevation?,
+    shape: Shape,
     colors: SelectableChipColors,
+    elevation: SelectableChipElevation?,
+    border: BorderStroke?,
     minHeight: Dp,
     paddingValues: PaddingValues,
-    shape: Shape,
-    border: BorderStroke?,
     interactionSource: MutableInteractionSource
 ) {
     // TODO(b/229794614): Animate transition between unselected and selected.
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/NavigationDrawer.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/NavigationDrawer.kt
index 0fea002..d1f14be 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/NavigationDrawer.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/NavigationDrawer.kt
@@ -438,14 +438,14 @@
  *
  * @param modifier the [Modifier] to be applied to this drawer's content
  * @param drawerShape defines the shape of this drawer's container
- * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
- * primary color overlay is applied on top of the container. A higher tonal elevation value will
- * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param drawerContainerColor the color used for the background of this drawer. Use
  * [Color.Transparent] to have no color.
  * @param drawerContentColor the preferred color for content inside this drawer. Defaults to either
  * the matching content color for [drawerContainerColor], or to the current [LocalContentColor] if
  * [drawerContainerColor] is not a color from the theme.
+ * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
+ * primary color overlay is applied on top of the container. A higher tonal elevation value will
+ * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param content content inside of a modal navigation drawer
  */
 @ExperimentalMaterial3Api
@@ -453,17 +453,17 @@
 fun ModalDrawerSheet(
     modifier: Modifier = Modifier,
     drawerShape: Shape = DrawerDefaults.shape,
-    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
     drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
     drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
     content: @Composable ColumnScope.() -> Unit
 ) {
     DrawerSheet(
         modifier,
         drawerShape,
-        drawerTonalElevation,
         drawerContainerColor,
         drawerContentColor,
+        drawerTonalElevation,
         content
     )
 }
@@ -473,14 +473,14 @@
  *
  * @param modifier the [Modifier] to be applied to this drawer's content
  * @param drawerShape defines the shape of this drawer's container
- * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
- * primary color overlay is applied on top of the container. A higher tonal elevation value will
- * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param drawerContainerColor the color used for the background of this drawer. Use
  * [Color.Transparent] to have no color.
  * @param drawerContentColor the preferred color for content inside this drawer. Defaults to either
  * the matching content color for [drawerContainerColor], or to the current [LocalContentColor] if
  * [drawerContainerColor] is not a color from the theme.
+ * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
+ * primary color overlay is applied on top of the container. A higher tonal elevation value will
+ * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param content content inside of a dismissible navigation drawer
  */
 @ExperimentalMaterial3Api
@@ -488,17 +488,17 @@
 fun DismissibleDrawerSheet(
     modifier: Modifier = Modifier,
     drawerShape: Shape = RectangleShape,
-    drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation,
     drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
     drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation,
     content: @Composable ColumnScope.() -> Unit
 ) {
     DrawerSheet(
         modifier,
         drawerShape,
-        drawerTonalElevation,
         drawerContainerColor,
         drawerContentColor,
+        drawerTonalElevation,
         content
     )
 }
@@ -508,14 +508,14 @@
  *
  * @param modifier the [Modifier] to be applied to this drawer's content
  * @param drawerShape defines the shape of this drawer's container
- * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
- * primary color overlay is applied on top of the container. A higher tonal elevation value will
- * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param drawerContainerColor the color used for the background of this drawer. Use
  * [Color.Transparent] to have no color.
  * @param drawerContentColor the preferred color for content inside this drawer. Defaults to either
  * the matching content color for [drawerContainerColor], or to the current [LocalContentColor] if
  * [drawerContainerColor] is not a color from the theme.
+ * @param drawerTonalElevation when [drawerContainerColor] is [ColorScheme.surface], a translucent
+ * primary color overlay is applied on top of the container. A higher tonal elevation value will
+ * result in a darker color in light theme and lighter color in dark theme. See also: [Surface].
  * @param content content inside a permanent navigation drawer
  */
 @ExperimentalMaterial3Api
@@ -523,9 +523,9 @@
 fun PermanentDrawerSheet(
     modifier: Modifier = Modifier,
     drawerShape: Shape = RectangleShape,
-    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
     drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
     drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
     content: @Composable ColumnScope.() -> Unit
 ) {
     val navigationMenu = getString(Strings.NavigationMenu)
@@ -534,9 +534,9 @@
             paneTitle = navigationMenu
         },
         drawerShape,
-        drawerTonalElevation,
         drawerContainerColor,
         drawerContentColor,
+        drawerTonalElevation,
         content
     )
 }
@@ -546,9 +546,9 @@
 private fun DrawerSheet(
     modifier: Modifier = Modifier,
     drawerShape: Shape = RectangleShape,
-    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
     drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
     drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
     content: @Composable ColumnScope.() -> Unit
 ) {
     Surface(
diff --git a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
index 89882d6..3b428b0 100644
--- a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
+++ b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
@@ -21,6 +21,7 @@
 import android.os.Bundle
 import androidx.compose.animation.core.InternalAnimationApi
 import androidx.compose.ui.tooling.animation.PreviewAnimationClock
+import androidx.compose.ui.tooling.animation.UnsupportedComposeAnimation
 import androidx.compose.ui.tooling.data.UiToolingDataApi
 import androidx.compose.ui.tooling.test.R
 import androidx.test.filters.LargeTest
@@ -155,7 +156,7 @@
 
     @Test
     fun animatedContentIsSubscribed() {
-        checkUnsupportedIsSubscribed("AnimatedContentPreview", listOf("AnimatedContent"))
+        checkAnimationsAreSubscribed("AnimatedContentPreview", listOf("AnimatedContent"))
     }
 
     @Test
@@ -170,7 +171,7 @@
 
     @Test
     fun animateXAsStateIsSubscribed() {
-        checkUnsupportedIsSubscribed(
+        checkAnimationsAreSubscribed(
             "AnimateAsStatePreview",
             listOf("animateValueAsState", "animateValueAsState")
         )
@@ -178,7 +179,7 @@
 
     @Test
     fun animateContentSizeIsSubscribed() {
-        checkUnsupportedIsSubscribed("AnimateContentSizePreview", listOf("animateContentSize"))
+        checkAnimationsAreSubscribed("AnimateContentSizePreview", listOf("animateContentSize"))
     }
 
     @Test
@@ -188,20 +189,35 @@
 
     @Test
     fun targetBasedAnimationIsSubscribed() {
-        checkUnsupportedIsSubscribed("TargetBasedAnimationPreview", listOf("TargetBasedAnimation"))
+        checkAnimationsAreSubscribed("TargetBasedAnimationPreview", listOf("TargetBasedAnimation"))
     }
 
     @Test
     fun decayAnimationIsSubscribed() {
-        checkUnsupportedIsSubscribed("DecayAnimationPreview", listOf("DecayAnimation"))
+        checkAnimationsAreSubscribed("DecayAnimationPreview", listOf("DecayAnimation"))
     }
 
     @Test
     fun infiniteTransitionIsSubscribed() {
-        checkUnsupportedIsSubscribed("InfiniteTransitionPreview", listOf("InfiniteTransition"))
+        checkAnimationsAreSubscribed("InfiniteTransitionPreview", listOf("InfiniteTransition"))
     }
 
-    private fun checkUnsupportedIsSubscribed(preview: String, labels: List<String>) {
+    @Test
+    fun unsupportedAreNotSubscribedWhenEnumIsNotAvailable() {
+        UnsupportedComposeAnimation.testOverrideAvailability(false)
+        checkAnimationsAreSubscribed(
+            "AllAnimations",
+            emptyList(),
+            listOf("String", "checkBoxAnim")
+        )
+        UnsupportedComposeAnimation.testOverrideAvailability(true)
+    }
+
+    private fun checkAnimationsAreSubscribed(
+        preview: String,
+        unsupported: List<String>,
+        transitions: List<String> = emptyList()
+    ) {
         val clock = PreviewAnimationClock()
 
         activityTestRule.runOnUiThread {
@@ -212,9 +228,11 @@
             composeViewAdapter.clock = clock
             assertFalse(composeViewAdapter.hasAnimations())
             assertTrue(clock.trackedTransitions.isEmpty())
+            assertTrue(clock.trackedUnsupported.isEmpty())
+            assertTrue(clock.trackedAnimatedVisibility.isEmpty())
         }
 
-        waitFor("Composable to have animations", 1, TimeUnit.SECONDS) {
+        waitFor("Composable to have animations", 2, TimeUnit.SECONDS) {
             // Handle the case where onLayout was called too soon. Calling requestLayout will
             // make sure onLayout will be called again.
             composeViewAdapter.requestLayout()
@@ -222,8 +240,8 @@
         }
 
         activityTestRule.runOnUiThread {
-            assertEquals(labels, clock.trackedUnsupported.map { it.label }.sortedBy { it })
-            assertEquals(0, clock.trackedTransitions.size)
+            assertEquals(unsupported, clock.trackedUnsupported.map { it.label }.sortedBy { it })
+            assertEquals(transitions, clock.trackedTransitions.map { it.label }.sortedBy { it })
             assertEquals(0, clock.trackedAnimatedVisibility.size)
         }
     }
diff --git a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/TestAnimationPreview.kt b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/TestAnimationPreview.kt
index 408d822..e322def 100644
--- a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/TestAnimationPreview.kt
+++ b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/TestAnimationPreview.kt
@@ -89,6 +89,19 @@
     }
 }
 
+@Preview(name = "All unsupported and transition animations")
+@Composable
+fun AllAnimations() {
+    AnimatedContentPreview()
+    CheckBox()
+    AnimateAsStatePreview()
+    CrossFadePreview()
+    AnimateContentSizePreview()
+    TargetBasedAnimationPreview()
+    DecayAnimationPreview()
+    InfiniteTransitionPreview()
+}
+
 @OptIn(ExperimentalAnimationApi::class)
 @Preview(name = "AnimatedContent")
 @Composable
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
index fe71638..c200a5f 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
@@ -73,6 +73,7 @@
 import androidx.compose.animation.core.DecayAnimation
 import androidx.compose.animation.core.InfiniteTransition
 import androidx.compose.animation.core.TargetBasedAnimation
+import androidx.compose.ui.tooling.animation.UnsupportedComposeAnimation
 import kotlin.reflect.KClass
 import kotlin.reflect.safeCast
 
@@ -435,10 +436,14 @@
         val animatedVisibilitySearch = AnimatedVisibilitySearch {
             clock.trackAnimatedVisibility(it as Transition<Any>, ::requestLayout)
         }
-
-        val search = listOf(
+        // All supported animations.
+        val supportedSearch = setOf(
             transitionSearch,
             animatedVisibilitySearch,
+        )
+
+        // All unsupported animations, if API is available.
+        val extraSearch = if (UnsupportedComposeAnimation.apiAvailable) setOf(
             animatedContentSearch,
             AnimateXAsStateSearch { clock.trackAnimateXAsState(it as Animatable<*, *>) },
             AnimateContentSizeSearch { clock.trackAnimateContentSize(it) },
@@ -451,14 +456,21 @@
             RememberSearch(InfiniteTransition::class) {
                 clock.trackInfiniteTransition(it as InfiniteTransition)
             }
-        )
+        ) else emptyList()
+
+        // Animations to track in PreviewAnimationClock.
+        val setToTrack = supportedSearch + extraSearch
+
+        // Animations to search. animatedContentSearch is included even if it's not going to be
+        // tracked as it should be excluded from transitionSearch.
+        val setToSearch = setToTrack + setOf(animatedContentSearch)
 
         // Check all the slot tables, since some animations might not be present in the same
         // table as the one containing the `@Composable` being previewed, e.g. when they're
         // defined using sub-composition.
         slotTrees.forEach { tree ->
             val treeWithLocation = tree.findAll { it.location != null }
-            search.forEach { it.parse(treeWithLocation) }
+            setToSearch.forEach { it.parse(treeWithLocation) }
 
             // Remove all AnimatedVisibility parent transitions from the transitions list,
             // otherwise we'd duplicate them in the Android Studio Animation Preview because we
@@ -470,11 +482,11 @@
             transitionSearch.animations.removeAll(animatedContentSearch.animations)
         }
 
-        hasAnimations = search.any { it.hasAnimations() }
+        hasAnimations = setToTrack.any { it.hasAnimations() }
 
         // Make the `PreviewAnimationClock` track all the transitions found.
         if (::clock.isInitialized) {
-            search.forEach { it.track() }
+            setToTrack.forEach { it.track() }
         }
     }
 
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/ComposeAnimationParser.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/ComposeAnimationParser.kt
index abc83a1..f5cc293 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/ComposeAnimationParser.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/ComposeAnimationParser.kt
@@ -20,6 +20,7 @@
 import androidx.compose.animation.core.Transition
 import androidx.compose.animation.tooling.ComposeAnimation
 import androidx.compose.animation.tooling.ComposeAnimationType
+import org.jetbrains.annotations.TestOnly
 
 // TODO(b/160126628): support other animation types, e.g. single animated value
 /**
@@ -73,12 +74,32 @@
 /**
  * [ComposeAnimation] of type [ComposeAnimationType.UNSUPPORTED].
  */
-internal class UnsupportedComposeAnimation(
+internal class UnsupportedComposeAnimation private constructor(
     override val label: String?
 ) : ComposeAnimation {
     override val type = ComposeAnimationType.UNSUPPORTED
     override val animationObject: Any = 0
     override val states = emptySet<Int>()
+
+    companion object {
+        /**
+         * [ComposeAnimationType] from ANIMATABLE to UNSUPPORTED are not available in previous
+         * versions of the library. To avoid creating non-existing enum,
+         * [UnsupportedComposeAnimation] should only be instantiated if [ComposeAnimationType] API
+         * for UNSUPPORTED enum is available.
+         */
+        var apiAvailable = enumValues<ComposeAnimationType>().any { it.name == "UNSUPPORTED" }
+            private set
+
+        fun create(label: String?) =
+            if (apiAvailable) UnsupportedComposeAnimation(label) else null
+
+        /** This method is for testing only. */
+        @TestOnly
+        fun testOverrideAvailability(override: Boolean) {
+            apiAvailable = override
+        }
+    }
 }
 
 /**
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/PreviewAnimationClock.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/PreviewAnimationClock.kt
index 4329d4f..a33b646 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/PreviewAnimationClock.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/PreviewAnimationClock.kt
@@ -119,6 +119,7 @@
         private val lock = Any()
 
         fun trackAnimation(animation: T, label: String) {
+            if (!UnsupportedComposeAnimation.apiAvailable) return
             synchronized(lock) {
                 if (animations.contains(animation)) {
                     if (DEBUG) {
@@ -133,9 +134,10 @@
                 Log.d(TAG, "Animation $animation is now tracked")
             }
 
-            val composeAnimation = UnsupportedComposeAnimation(label)
-            trackedUnsupported.add(composeAnimation)
-            notifySubscribe(composeAnimation)
+            UnsupportedComposeAnimation.create(label)?.let {
+                trackedUnsupported.add(it)
+                notifySubscribe(it)
+            }
         }
 
         fun clear() {
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index d01baf1..13f51f0 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -46,7 +46,7 @@
         api(project(":compose:ui:ui-graphics"))
         api(project(":compose:ui:ui-text"))
         api(project(":compose:ui:ui-unit"))
-        api(project(":annotation:annotation"))
+        api("androidx.annotation:annotation:1.5.0-alpha01")
 
         // This has stub APIs for access to legacy Android APIs, so we don't want
         // any dependency on this module.
diff --git a/compose/ui/ui/src/androidMain/res/values-af/strings.xml b/compose/ui/ui/src/androidMain/res/values-af/strings.xml
index bec1e20..9307353 100644
--- a/compose/ui/ui/src/androidMain/res/values-af/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-af/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Gedeeltelik gemerk"</string>
     <string name="on" msgid="8655164131929253426">"Aan"</string>
     <string name="off" msgid="875452955155264703">"Af"</string>
     <string name="selected" msgid="6043586758067023">"Gekies"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-am/strings.xml b/compose/ui/ui/src/androidMain/res/values-am/strings.xml
index d4e13c5..afabf32 100644
--- a/compose/ui/ui/src/androidMain/res/values-am/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-am/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"በከፊል የተፈተሸ"</string>
     <string name="on" msgid="8655164131929253426">"በርቷል"</string>
     <string name="off" msgid="875452955155264703">"ጠፍቷል"</string>
     <string name="selected" msgid="6043586758067023">"ተመርጧል"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ar/strings.xml b/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
index e8e446d..0170f4f 100644
--- a/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"تم وضع علامة في المربّع بشكل جزئي"</string>
     <string name="on" msgid="8655164131929253426">"مفعّل"</string>
     <string name="off" msgid="875452955155264703">"غير مفعّل"</string>
     <string name="selected" msgid="6043586758067023">"محدّد"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-as/strings.xml b/compose/ui/ui/src/androidMain/res/values-as/strings.xml
index e7bdb96..fd3d3d4 100644
--- a/compose/ui/ui/src/androidMain/res/values-as/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-as/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"আংশিকভাৱে পৰীক্ষা কৰা হৈছে"</string>
     <string name="on" msgid="8655164131929253426">"অন কৰা আছে"</string>
     <string name="off" msgid="875452955155264703">"অফ আছে"</string>
     <string name="selected" msgid="6043586758067023">"বাছনি কৰা হৈছে"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml b/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
index 24ce253..61a85cc 100644
--- a/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Delimično označeno"</string>
     <string name="on" msgid="8655164131929253426">"Uključeno"</string>
     <string name="off" msgid="875452955155264703">"Isključeno"</string>
     <string name="selected" msgid="6043586758067023">"Izabrano"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-be/strings.xml b/compose/ui/ui/src/androidMain/res/values-be/strings.xml
index d8ba140..98e1f8c 100644
--- a/compose/ui/ui/src/androidMain/res/values-be/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-be/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Выбрана часткова"</string>
     <string name="on" msgid="8655164131929253426">"Уключана"</string>
     <string name="off" msgid="875452955155264703">"Выключана"</string>
     <string name="selected" msgid="6043586758067023">"Выбрана"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-bg/strings.xml b/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
index 4d8841d..67e38ca 100644
--- a/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Частично отметнато"</string>
     <string name="on" msgid="8655164131929253426">"Вкл."</string>
     <string name="off" msgid="875452955155264703">"Изкл."</string>
     <string name="selected" msgid="6043586758067023">"Избрано"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-bn/strings.xml b/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
index 1ba969f..dffc528 100644
--- a/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"কয়েকটি বিকল্প বেছে নেওয়া হয়েছে"</string>
     <string name="on" msgid="8655164131929253426">"চালু আছে"</string>
     <string name="off" msgid="875452955155264703">"বন্ধ আছে"</string>
     <string name="selected" msgid="6043586758067023">"বেছে নেওয়া হয়েছে"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-bs/strings.xml b/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
index f940559..9f847eb 100644
--- a/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Djelimično označeno"</string>
     <string name="on" msgid="8655164131929253426">"Uključeno"</string>
     <string name="off" msgid="875452955155264703">"Isključeno"</string>
     <string name="selected" msgid="6043586758067023">"Odabrano"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ca/strings.xml b/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
index 4d001db..2971e2d 100644
--- a/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Marcat parcialment"</string>
     <string name="on" msgid="8655164131929253426">"Activat"</string>
     <string name="off" msgid="875452955155264703">"Desactivat"</string>
     <string name="selected" msgid="6043586758067023">"Seleccionat"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-cs/strings.xml b/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
index d02f4f8..4b7be76 100644
--- a/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Částečně zaškrtnuto"</string>
     <string name="on" msgid="8655164131929253426">"Zapnuto"</string>
     <string name="off" msgid="875452955155264703">"Vypnuto"</string>
     <string name="selected" msgid="6043586758067023">"Vybráno"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-da/strings.xml b/compose/ui/ui/src/androidMain/res/values-da/strings.xml
index f9d0a98..74d814d 100644
--- a/compose/ui/ui/src/androidMain/res/values-da/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-da/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Delvist markeret"</string>
     <string name="on" msgid="8655164131929253426">"Til"</string>
     <string name="off" msgid="875452955155264703">"Fra"</string>
     <string name="selected" msgid="6043586758067023">"Valgt"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-de/strings.xml b/compose/ui/ui/src/androidMain/res/values-de/strings.xml
index 7a0e339..756ecac 100644
--- a/compose/ui/ui/src/androidMain/res/values-de/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-de/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Teilweise aktiviert"</string>
     <string name="on" msgid="8655164131929253426">"An"</string>
     <string name="off" msgid="875452955155264703">"Aus"</string>
     <string name="selected" msgid="6043586758067023">"Ausgewählt"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml b/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
index 2d63515..d310d00 100644
--- a/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Verificado parcialmente"</string>
     <string name="on" msgid="8655164131929253426">"Sí"</string>
     <string name="off" msgid="875452955155264703">"No"</string>
     <string name="selected" msgid="6043586758067023">"Seleccionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-es/strings.xml b/compose/ui/ui/src/androidMain/res/values-es/strings.xml
index 5dfa6df..29f0179 100644
--- a/compose/ui/ui/src/androidMain/res/values-es/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-es/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Marcado parcialmente"</string>
     <string name="on" msgid="8655164131929253426">"Activado"</string>
     <string name="off" msgid="875452955155264703">"Desactivado"</string>
     <string name="selected" msgid="6043586758067023">"Seleccionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-et/strings.xml b/compose/ui/ui/src/androidMain/res/values-et/strings.xml
index 6855b96..2dca078 100644
--- a/compose/ui/ui/src/androidMain/res/values-et/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-et/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Osaliselt märgitud"</string>
     <string name="on" msgid="8655164131929253426">"Sees"</string>
     <string name="off" msgid="875452955155264703">"Väljas"</string>
     <string name="selected" msgid="6043586758067023">"Valitud"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-eu/strings.xml b/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
index 6858d16..55be3eb 100644
--- a/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Erdi-markatuta"</string>
     <string name="on" msgid="8655164131929253426">"Aktibatuta"</string>
     <string name="off" msgid="875452955155264703">"Desaktibatuta"</string>
     <string name="selected" msgid="6043586758067023">"Hautatuta"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-fa/strings.xml b/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
index a670069..3f782d5 100644
--- a/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"برخی موارد علامت‌گذاری شده است"</string>
     <string name="on" msgid="8655164131929253426">"روشن"</string>
     <string name="off" msgid="875452955155264703">"خاموش"</string>
     <string name="selected" msgid="6043586758067023">"انتخاب شد"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-fi/strings.xml b/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
index a2946a5..636843a 100644
--- a/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Osittain tarkistettu"</string>
     <string name="on" msgid="8655164131929253426">"Päällä"</string>
     <string name="off" msgid="875452955155264703">"Pois"</string>
     <string name="selected" msgid="6043586758067023">"Valittu"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml b/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
index c52e9d5..9fbbc12 100644
--- a/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Partiellement vérifié"</string>
     <string name="on" msgid="8655164131929253426">"Activé"</string>
     <string name="off" msgid="875452955155264703">"Désactivé"</string>
     <string name="selected" msgid="6043586758067023">"Sélectionné"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-fr/strings.xml b/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
index de53dd7..83442c7 100644
--- a/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Partiellement coché"</string>
     <string name="on" msgid="8655164131929253426">"Activé"</string>
     <string name="off" msgid="875452955155264703">"Désactivé"</string>
     <string name="selected" msgid="6043586758067023">"Sélectionné"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-gl/strings.xml b/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
index 795a358..393fe3c 100644
--- a/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Marcada parcialmente"</string>
     <string name="on" msgid="8655164131929253426">"Activado"</string>
     <string name="off" msgid="875452955155264703">"Desactivado"</string>
     <string name="selected" msgid="6043586758067023">"Seleccionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-gu/strings.xml b/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
index c9bb052..bf68b3e 100644
--- a/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"આંશિક રીતે ચેક કરેલા વિકલ્પો"</string>
     <string name="on" msgid="8655164131929253426">"ચાલુ છે"</string>
     <string name="off" msgid="875452955155264703">"બંધ છે"</string>
     <string name="selected" msgid="6043586758067023">"પસંદગી કરી"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-hi/strings.xml b/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
index 5d7d0b2..a9abd97 100644
--- a/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"कुछ विकल्पों को चुना गया"</string>
     <string name="on" msgid="8655164131929253426">"चालू है"</string>
     <string name="off" msgid="875452955155264703">"बंद है"</string>
     <string name="selected" msgid="6043586758067023">"चुना गया"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-hr/strings.xml b/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
index 82e083c..89cb2a9 100644
--- a/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Djelomično potvrđeno"</string>
     <string name="on" msgid="8655164131929253426">"Uključeno"</string>
     <string name="off" msgid="875452955155264703">"Isključeno"</string>
     <string name="selected" msgid="6043586758067023">"Odabrano"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-hu/strings.xml b/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
index bc13636..2747ec8 100644
--- a/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Részlegesen ellenőrizve"</string>
     <string name="on" msgid="8655164131929253426">"Be"</string>
     <string name="off" msgid="875452955155264703">"Ki"</string>
     <string name="selected" msgid="6043586758067023">"Kijelölve"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-hy/strings.xml b/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
index cdc836c..5e57c00 100644
--- a/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Մասնակի նշված"</string>
     <string name="on" msgid="8655164131929253426">"Միացված է"</string>
     <string name="off" msgid="875452955155264703">"Անջատված է"</string>
     <string name="selected" msgid="6043586758067023">"Ընտրված է"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-in/strings.xml b/compose/ui/ui/src/androidMain/res/values-in/strings.xml
index a47444c..47357b8 100644
--- a/compose/ui/ui/src/androidMain/res/values-in/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-in/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Diperiksa sebagian"</string>
     <string name="on" msgid="8655164131929253426">"Aktif"</string>
     <string name="off" msgid="875452955155264703">"Nonaktif"</string>
     <string name="selected" msgid="6043586758067023">"Dipilih"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-is/strings.xml b/compose/ui/ui/src/androidMain/res/values-is/strings.xml
index b7f7b05..e46b177 100644
--- a/compose/ui/ui/src/androidMain/res/values-is/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-is/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Hakað við að hluta til"</string>
     <string name="on" msgid="8655164131929253426">"Kveikt"</string>
     <string name="off" msgid="875452955155264703">"Slökkt"</string>
     <string name="selected" msgid="6043586758067023">"Valið"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-it/strings.xml b/compose/ui/ui/src/androidMain/res/values-it/strings.xml
index 414acd8..0cd3192 100644
--- a/compose/ui/ui/src/androidMain/res/values-it/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-it/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Elemento parzialmente selezionato"</string>
     <string name="on" msgid="8655164131929253426">"On"</string>
     <string name="off" msgid="875452955155264703">"Off"</string>
     <string name="selected" msgid="6043586758067023">"Elemento selezionato"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-iw/strings.xml b/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
index 2cdab54..a2b4851 100644
--- a/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"מסומנת חלקית"</string>
     <string name="on" msgid="8655164131929253426">"פועל"</string>
     <string name="off" msgid="875452955155264703">"כבוי"</string>
     <string name="selected" msgid="6043586758067023">"נבחר"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ja/strings.xml b/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
index 24c7609..be60e61 100644
--- a/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"一部 ON"</string>
     <string name="on" msgid="8655164131929253426">"オン"</string>
     <string name="off" msgid="875452955155264703">"オフ"</string>
     <string name="selected" msgid="6043586758067023">"選択済み"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ka/strings.xml b/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
index 7875bad..5eb8939 100644
--- a/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ნაწილობრივ შემოწმებულია"</string>
     <string name="on" msgid="8655164131929253426">"ჩართული"</string>
     <string name="off" msgid="875452955155264703">"გამორთული"</string>
     <string name="selected" msgid="6043586758067023">"არჩეული"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-kk/strings.xml b/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
index f30b035..82a029b 100644
--- a/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Жартылай белгіленді."</string>
     <string name="on" msgid="8655164131929253426">"Қосулы"</string>
     <string name="off" msgid="875452955155264703">"Өшірулі"</string>
     <string name="selected" msgid="6043586758067023">"Таңдалды"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-km/strings.xml b/compose/ui/ui/src/androidMain/res/values-km/strings.xml
index 58b175d..8e580fc 100644
--- a/compose/ui/ui/src/androidMain/res/values-km/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-km/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"បានធីកខ្លះ"</string>
     <string name="on" msgid="8655164131929253426">"បើក"</string>
     <string name="off" msgid="875452955155264703">"បិទ"</string>
     <string name="selected" msgid="6043586758067023">"បានជ្រើសរើស"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-kn/strings.xml b/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
index 8850e24..0b655e7 100644
--- a/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ಭಾಗಶಃ ಪರೀಕ್ಷಿಸಲಾಗಿದೆ"</string>
     <string name="on" msgid="8655164131929253426">"ಆನ್ ಆಗಿದೆ"</string>
     <string name="off" msgid="875452955155264703">"ಆಫ್ ಆಗಿದೆ"</string>
     <string name="selected" msgid="6043586758067023">"ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ko/strings.xml b/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
index 875fec1..bc50254 100644
--- a/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"일부 선택됨"</string>
     <string name="on" msgid="8655164131929253426">"켜짐"</string>
     <string name="off" msgid="875452955155264703">"꺼짐"</string>
     <string name="selected" msgid="6043586758067023">"선택됨"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ky/strings.xml b/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
index 739a6b3..9cde977 100644
--- a/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Жарым-жартылай текшерилди"</string>
     <string name="on" msgid="8655164131929253426">"Күйүк"</string>
     <string name="off" msgid="875452955155264703">"Өчүк"</string>
     <string name="selected" msgid="6043586758067023">"Тандалды"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-lo/strings.xml b/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
index 0935bf6..79b9834 100644
--- a/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ກວດສອບບາງສ່ວນແລ້ວ"</string>
     <string name="on" msgid="8655164131929253426">"ເປີດ"</string>
     <string name="off" msgid="875452955155264703">"ປິດ"</string>
     <string name="selected" msgid="6043586758067023">"ເລືອກແລ້ວ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-lt/strings.xml b/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
index 1e0f248..3e28091 100644
--- a/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Iš dalies pažymėta"</string>
     <string name="on" msgid="8655164131929253426">"Įjungta"</string>
     <string name="off" msgid="875452955155264703">"Išjungta"</string>
     <string name="selected" msgid="6043586758067023">"Pasirinkta"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-lv/strings.xml b/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
index 8c533528..3b92218 100644
--- a/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Daļēji atzīmēta"</string>
     <string name="on" msgid="8655164131929253426">"Ieslēgts"</string>
     <string name="off" msgid="875452955155264703">"Izslēgts"</string>
     <string name="selected" msgid="6043586758067023">"Atlasīts"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-mk/strings.xml b/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
index 0c5ed6e..79eb9b2 100644
--- a/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Делумно проверено"</string>
     <string name="on" msgid="8655164131929253426">"Вклучено"</string>
     <string name="off" msgid="875452955155264703">"Исклучено"</string>
     <string name="selected" msgid="6043586758067023">"Избрано"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ml/strings.xml b/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
index f4d88e8..0ad1342 100644
--- a/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ഭാഗികമായി ചെക്ക് മാർക്കിട്ടു"</string>
     <string name="on" msgid="8655164131929253426">"ഓണാണ്"</string>
     <string name="off" msgid="875452955155264703">"ഓഫാണ്"</string>
     <string name="selected" msgid="6043586758067023">"തിരഞ്ഞെടുത്തു"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-mn/strings.xml b/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
index ca6f341..7908393 100644
--- a/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Хэсэгчлэн тэмдэглэсэн"</string>
     <string name="on" msgid="8655164131929253426">"Асаалттай"</string>
     <string name="off" msgid="875452955155264703">"Унтраалттай"</string>
     <string name="selected" msgid="6043586758067023">"Сонгосон"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-mr/strings.xml b/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
index 73cf75d..8075612 100644
--- a/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"अंशतः तपासले"</string>
     <string name="on" msgid="8655164131929253426">"सुरू आहे"</string>
     <string name="off" msgid="875452955155264703">"बंद आहे"</string>
     <string name="selected" msgid="6043586758067023">"निवडला"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ms/strings.xml b/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
index 7a99bb2..2106240 100644
--- a/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Sebahagiannya ditandai"</string>
     <string name="on" msgid="8655164131929253426">"Hidup"</string>
     <string name="off" msgid="875452955155264703">"Mati"</string>
     <string name="selected" msgid="6043586758067023">"Dipilih"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-my/strings.xml b/compose/ui/ui/src/androidMain/res/values-my/strings.xml
index ba757fb..378fdec 100644
--- a/compose/ui/ui/src/androidMain/res/values-my/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-my/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"တစ်ဝက်တစ်ပျက် စစ်ဆေးထားသည်"</string>
     <string name="on" msgid="8655164131929253426">"ဖွင့်"</string>
     <string name="off" msgid="875452955155264703">"ပိတ်"</string>
     <string name="selected" msgid="6043586758067023">"ရွေးထားသည်"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-nb/strings.xml b/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
index 6c5bc69..635894a0 100644
--- a/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Delvis avmerket"</string>
     <string name="on" msgid="8655164131929253426">"På"</string>
     <string name="off" msgid="875452955155264703">"Av"</string>
     <string name="selected" msgid="6043586758067023">"Valgt"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ne/strings.xml b/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
index cb332e7..1cda72d 100644
--- a/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"आंशिक रूपमा जाँच गरिएको"</string>
     <string name="on" msgid="8655164131929253426">"अन छ"</string>
     <string name="off" msgid="875452955155264703">"अफ छ"</string>
     <string name="selected" msgid="6043586758067023">"चयन गरिएको छ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-nl/strings.xml b/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
index d1428af..3ebc974 100644
--- a/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Gedeeltelijk aangevinkt"</string>
     <string name="on" msgid="8655164131929253426">"Aan"</string>
     <string name="off" msgid="875452955155264703">"Uit"</string>
     <string name="selected" msgid="6043586758067023">"Geselecteerd"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-or/strings.xml b/compose/ui/ui/src/androidMain/res/values-or/strings.xml
index 0d82f58..39ddb0d 100644
--- a/compose/ui/ui/src/androidMain/res/values-or/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-or/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ଆଶିଂକ ଭାବେ ଯାଞ୍ଚ କରାଯାଇଛି"</string>
     <string name="on" msgid="8655164131929253426">"ଚାଲୁ ଅଛି"</string>
     <string name="off" msgid="875452955155264703">"ବନ୍ଦ ଅଛି"</string>
     <string name="selected" msgid="6043586758067023">"ଚୟନିତ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-pa/strings.xml b/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
index c1e3b7d..6e7256a 100644
--- a/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"ਅੰਸ਼ਕ ਤੌਰ ਤੇ ਜਾਂਚ ਕੀਤੀ ਗਈ"</string>
     <string name="on" msgid="8655164131929253426">"ਚਾਲੂ ਹੈ"</string>
     <string name="off" msgid="875452955155264703">"ਬੰਦ ਹੈ"</string>
     <string name="selected" msgid="6043586758067023">"ਚੁਣੀ ਗਈ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-pl/strings.xml b/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
index 75aa49e..4167c3e 100644
--- a/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Częściowo zaznaczone"</string>
     <string name="on" msgid="8655164131929253426">"Włączono"</string>
     <string name="off" msgid="875452955155264703">"Wyłączono"</string>
     <string name="selected" msgid="6043586758067023">"Wybrano"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
index d0607fd..2b2737c 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Parcialmente selecionada"</string>
     <string name="on" msgid="8655164131929253426">"Ativado"</string>
     <string name="off" msgid="875452955155264703">"Desativado"</string>
     <string name="selected" msgid="6043586758067023">"Selecionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
index 14c7c04..d27d78d 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Parcialmente selecionada"</string>
     <string name="on" msgid="8655164131929253426">"Ativado"</string>
     <string name="off" msgid="875452955155264703">"Desativado"</string>
     <string name="selected" msgid="6043586758067023">"Selecionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
index d0607fd..2b2737c 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Parcialmente selecionada"</string>
     <string name="on" msgid="8655164131929253426">"Ativado"</string>
     <string name="off" msgid="875452955155264703">"Desativado"</string>
     <string name="selected" msgid="6043586758067023">"Selecionado"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ro/strings.xml b/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
index 38108f8..6e8e9d6 100644
--- a/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Bifată parțial"</string>
     <string name="on" msgid="8655164131929253426">"Activat"</string>
     <string name="off" msgid="875452955155264703">"Dezactivat"</string>
     <string name="selected" msgid="6043586758067023">"Selectat"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ru/strings.xml b/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
index 1928e3f..0e23ca7 100644
--- a/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Отмечено частично"</string>
     <string name="on" msgid="8655164131929253426">"Включено"</string>
     <string name="off" msgid="875452955155264703">"Отключено"</string>
     <string name="selected" msgid="6043586758067023">"Выбрано"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-si/strings.xml b/compose/ui/ui/src/androidMain/res/values-si/strings.xml
index 13ffe02..1cbdac1 100644
--- a/compose/ui/ui/src/androidMain/res/values-si/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-si/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"අඩ වශයෙන් ලකුණු කළ"</string>
     <string name="on" msgid="8655164131929253426">"ක්‍රියාත්මකයි"</string>
     <string name="off" msgid="875452955155264703">"ක්‍රියාවිරහිතයි"</string>
     <string name="selected" msgid="6043586758067023">"තෝරන ලදි"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sk/strings.xml b/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
index c068e63..ebef855 100644
--- a/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Čiastočne začiarknuté"</string>
     <string name="on" msgid="8655164131929253426">"Zapnuté"</string>
     <string name="off" msgid="875452955155264703">"Vypnuté"</string>
     <string name="selected" msgid="6043586758067023">"Vybrané"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sl/strings.xml b/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
index 067183a..72bd314 100644
--- a/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Delno potrjeno"</string>
     <string name="on" msgid="8655164131929253426">"Vklopljeno"</string>
     <string name="off" msgid="875452955155264703">"Izklopljeno"</string>
     <string name="selected" msgid="6043586758067023">"Izbrano"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sq/strings.xml b/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
index 0f3cf23..7abc00b 100644
--- a/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Pjesërisht e shënuar"</string>
     <string name="on" msgid="8655164131929253426">"Aktiv"</string>
     <string name="off" msgid="875452955155264703">"Joaktiv"</string>
     <string name="selected" msgid="6043586758067023">"Zgjedhur"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sr/strings.xml b/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
index f761f7e..71ab0b4 100644
--- a/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Делимично означено"</string>
     <string name="on" msgid="8655164131929253426">"Укључено"</string>
     <string name="off" msgid="875452955155264703">"Искључено"</string>
     <string name="selected" msgid="6043586758067023">"Изабрано"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sv/strings.xml b/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
index 8843eba..775deb3 100644
--- a/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Delvis markerad"</string>
     <string name="on" msgid="8655164131929253426">"På"</string>
     <string name="off" msgid="875452955155264703">"Av"</string>
     <string name="selected" msgid="6043586758067023">"Valt"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-sw/strings.xml b/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
index 9a960fe..6e72ed8 100644
--- a/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Imekaguliwa kwa kiasi fulani"</string>
     <string name="on" msgid="8655164131929253426">"Imewashwa"</string>
     <string name="off" msgid="875452955155264703">"Imezimwa"</string>
     <string name="selected" msgid="6043586758067023">"Umechagua"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ta/strings.xml b/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
index b8e6df2..b5af40e 100644
--- a/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"சில மட்டுமே தேர்ந்தெடுக்கப்பட்டுள்ளன"</string>
     <string name="on" msgid="8655164131929253426">"இயக்கப்பட்டுள்ளது"</string>
     <string name="off" msgid="875452955155264703">"முடக்கப்பட்டுள்ளது"</string>
     <string name="selected" msgid="6043586758067023">"தேர்ந்தெடுக்கப்பட்டுள்ளது"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-te/strings.xml b/compose/ui/ui/src/androidMain/res/values-te/strings.xml
index 7f1588e..c7a73ea 100644
--- a/compose/ui/ui/src/androidMain/res/values-te/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-te/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"పాక్షికంగా ఎంచుకోబడింది"</string>
     <string name="on" msgid="8655164131929253426">"ఆన్‌లో ఉంది"</string>
     <string name="off" msgid="875452955155264703">"ఆఫ్‌లో ఉంది"</string>
     <string name="selected" msgid="6043586758067023">"ఎంచుకోబడింది"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-th/strings.xml b/compose/ui/ui/src/androidMain/res/values-th/strings.xml
index 3d9e8cb..9ed9c01 100644
--- a/compose/ui/ui/src/androidMain/res/values-th/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-th/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"เลือกบางส่วน"</string>
     <string name="on" msgid="8655164131929253426">"เปิด"</string>
     <string name="off" msgid="875452955155264703">"ปิด"</string>
     <string name="selected" msgid="6043586758067023">"เลือกไว้"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-tl/strings.xml b/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
index 489df2b..f270d0f 100644
--- a/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Bahagyang may check"</string>
     <string name="on" msgid="8655164131929253426">"Naka-on"</string>
     <string name="off" msgid="875452955155264703">"Naka-off"</string>
     <string name="selected" msgid="6043586758067023">"Napili"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-tr/strings.xml b/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
index d51a068..047a5e7 100644
--- a/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Kısmi olarak kontrol edildi"</string>
     <string name="on" msgid="8655164131929253426">"Açık"</string>
     <string name="off" msgid="875452955155264703">"Kapalı"</string>
     <string name="selected" msgid="6043586758067023">"Seçili"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-uk/strings.xml b/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
index d7656ee..86ac2d9 100644
--- a/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Частково вибрано"</string>
     <string name="on" msgid="8655164131929253426">"Увімкнено"</string>
     <string name="off" msgid="875452955155264703">"Вимкнено"</string>
     <string name="selected" msgid="6043586758067023">"Вибрано"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-ur/strings.xml b/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
index fcb05a7..29c81e4 100644
--- a/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"جزوی طور پر چیک کردہ"</string>
     <string name="on" msgid="8655164131929253426">"آن ہے"</string>
     <string name="off" msgid="875452955155264703">"آف ہے"</string>
     <string name="selected" msgid="6043586758067023">"منتخب کردہ"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-uz/strings.xml b/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
index 2ec8ad47..de15793 100644
--- a/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Qisman belgilandi"</string>
     <string name="on" msgid="8655164131929253426">"Yoniq"</string>
     <string name="off" msgid="875452955155264703">"Oʻchiq"</string>
     <string name="selected" msgid="6043586758067023">"Tanlangan"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-vi/strings.xml b/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
index a95de5d..84a7a82 100644
--- a/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Đã kiểm tra một phần"</string>
     <string name="on" msgid="8655164131929253426">"Đang bật"</string>
     <string name="off" msgid="875452955155264703">"Đang tắt"</string>
     <string name="selected" msgid="6043586758067023">"Đã chọn"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
index 64da085..ced331e 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"部分选中"</string>
     <string name="on" msgid="8655164131929253426">"已开启"</string>
     <string name="off" msgid="875452955155264703">"已关闭"</string>
     <string name="selected" msgid="6043586758067023">"已选择"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
index f3153ed..53784a3 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"部分剔咗"</string>
     <string name="on" msgid="8655164131929253426">"開"</string>
     <string name="off" msgid="875452955155264703">"閂"</string>
     <string name="selected" msgid="6043586758067023">"揀咗"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
index 4b3e173..cd21630 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"部分檢查"</string>
     <string name="on" msgid="8655164131929253426">"已開啟"</string>
     <string name="off" msgid="875452955155264703">"已關閉"</string>
     <string name="selected" msgid="6043586758067023">"已選取"</string>
diff --git a/compose/ui/ui/src/androidMain/res/values-zu/strings.xml b/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
index 0394f97..afe39be 100644
--- a/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
@@ -17,8 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for indeterminate (7933458017204019916) -->
-    <skip />
+    <string name="indeterminate" msgid="7933458017204019916">"Kuhlolwe kancane"</string>
     <string name="on" msgid="8655164131929253426">"Vuliwe"</string>
     <string name="off" msgid="875452955155264703">"Valiwe"</string>
     <string name="selected" msgid="6043586758067023">"Okukhethiwe"</string>
diff --git a/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/SimpleActor.kt b/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/SimpleActor.kt
index 8da6bf5..7894e59 100644
--- a/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/SimpleActor.kt
+++ b/datastore/datastore-core/src/commonMain/kotlin/androidx/datastore/core/SimpleActor.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
diff --git a/datastore/datastore-multiprocess/build.gradle b/datastore/datastore-multiprocess/build.gradle
index 30b35a7..3d340db 100644
--- a/datastore/datastore-multiprocess/build.gradle
+++ b/datastore/datastore-multiprocess/build.gradle
@@ -19,6 +19,8 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("com.google.protobuf")
+    id("java-test-fixtures")
     id("org.jetbrains.kotlin.android")
 }
 
@@ -30,15 +32,36 @@
 
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.kotlinCoroutinesTest)
+    androidTestImplementation(libs.protobufLite)
     androidTestImplementation(libs.truth)
     androidTestImplementation(project(":internal-testutils-truth"))
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.testCore)
     androidTestImplementation(project(":datastore:datastore-core"))
-    androidTestImplementation(project(":datastore:datastore-proto"))
+}
+
+protobuf {
+    protoc {
+        artifact = libs.protobufCompiler.get()
+    }
+    // Generates the java proto-lite code for the protos in this project. See
+    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
+    // for more information.
+    generateProtoTasks {
+        all().each { task ->
+            task.builtins {
+                java {
+                    option "lite"
+                }
+            }
+        }
+    }
 }
 
 android {
+    defaultConfig {
+        minSdkVersion 19
+    }
     externalNativeBuild {
         cmake {
             path "src/main/cpp/CMakeLists.txt"
diff --git a/datastore/datastore-multiprocess/src/androidTest/AndroidManifest.xml b/datastore/datastore-multiprocess/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..6b9bbc2
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <application>
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$SimpleUpdateService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":SimpleUpdateService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateWriterService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":ConcurrentReadUpdateWriterService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateReaderService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":ConcurrentReadUpdateReaderService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":InterleavedUpdateDataService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataWithReadService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":InterleavedUpdateDataWithReadService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$CancelledUpdateDataService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":CancelledUpdateDataService" />
+        <service
+            android:name="androidx.datastore.multiprocess.MultiProcessDataStoreMultiProcessTest$InterleavedHandlerUpdateDataService"
+            android:enabled="true"
+            android:exported="false"
+            android:process=":InterleavedHandlerUpdateDataService" />
+    </application>
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+</manifest>
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/DirectTestService.kt b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/DirectTestService.kt
new file mode 100644
index 0000000..733f9eb
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/DirectTestService.kt
@@ -0,0 +1,279 @@
+/*
+ * 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.datastore.multiprocess
+
+import android.app.Service
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.os.Handler
+import android.os.IBinder
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import android.os.RemoteException
+import androidx.testing.TestMessageProto.FooProto
+import com.google.common.collect.ImmutableList
+import java.io.Serializable
+import java.util.concurrent.CountDownLatch
+
+private val THROWABLE_BUNDLE_KEY: String = "throwable"
+
+internal class Latch {
+    private var signaled: Boolean = false
+
+    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    fun signal() {
+        synchronized(this) {
+            signaled = true
+            (this as java.lang.Object).notify()
+        }
+    }
+
+    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    fun awaitSignal() {
+        synchronized(this) {
+            while (!signaled) {
+                try {
+                    (this as java.lang.Object).wait()
+                } catch (_: InterruptedException) {
+                    // Ignore.
+                }
+            }
+            signaled = false
+        }
+    }
+}
+
+abstract class DirectTestService() : Service() {
+    private val SERVICE_CLASS = this::class.java
+
+    @Suppress("DEPRECATION")
+    private val messenger: Messenger = Messenger(Handler(HandlerCallback()))
+    private val resume: Latch = Latch()
+    private val done: Latch = Latch()
+    private lateinit var testData: Bundle
+    private lateinit var thread: Thread
+    private lateinit var testFailure: Throwable
+
+    // It should be setup in `beforeTest`
+    internal lateinit var store: MultiProcessDataStore<FooProto>
+
+    override fun onBind(intent: Intent): IBinder {
+        return messenger.getBinder()
+    }
+
+    override fun onCreate() {
+        // No-op
+    }
+
+    override fun onDestroy() {
+        // No-op
+    }
+
+    protected abstract fun beforeTest(testData: Bundle)
+
+    protected abstract fun runTest()
+
+    protected fun waitForSignal() {
+        done.signal()
+        resume.awaitSignal()
+    }
+
+    private fun handle(msg: Message) {
+        if (!this::thread.isInitialized) {
+            testData = msg.getData()
+            thread = Thread(Runner())
+            thread.start()
+        } else {
+            resume.signal()
+        }
+        done.awaitSignal()
+        try {
+            val response: Message = Message.obtain()
+            if (this::testFailure.isInitialized) {
+                val data = Bundle()
+                data.putSerializable(THROWABLE_BUNDLE_KEY, testFailure as Serializable)
+                response.setData(data)
+            }
+            msg.replyTo.send(response)
+        } catch (ex: RemoteException) {
+            throw RuntimeException("Test service failed to ack message", ex)
+        }
+    }
+
+    private inner class HandlerCallback : Handler.Callback {
+        override fun handleMessage(msg: Message): Boolean {
+            handle(msg)
+            return true
+        }
+    }
+
+    private inner class Runner : Runnable {
+        override fun run() {
+            try {
+                beforeTest(testData)
+                waitForSignal()
+                runTest()
+            } catch (t: Throwable) {
+                testFailure = t
+            } finally {
+                done.signal()
+            }
+        }
+    }
+}
+
+class BlockingServiceConnection(
+    private val context: Context,
+    private val serviceIntent: Intent
+) :
+    ServiceConnection {
+    private lateinit var isConnected: CountDownLatch
+    private var service: Messenger? = null
+    private var remoteException: Throwable? = null
+
+    override fun onServiceConnected(className: ComponentName, serviceBinder: IBinder) {
+        service = Messenger(serviceBinder)
+        isConnected.countDown()
+    }
+
+    override fun onServiceDisconnected(className: ComponentName) {
+        service = null
+    }
+
+    fun isServiceConnected(): Boolean {
+        return service != null
+    }
+
+    @Suppress("DEPRECATION")
+    fun connect(connectedLatch: CountDownLatch) {
+        isConnected = connectedLatch
+        val serviceExists: Boolean =
+            context.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE)
+
+        if (!serviceExists) {
+            val targetPackage: String = serviceIntent.getComponent()!!.getPackageName()
+            val targetService: String = serviceIntent.getComponent()!!.getClassName()
+
+            try {
+                context.getPackageManager().getPackageInfo(targetPackage, 0)
+            } catch (e: PackageManager.NameNotFoundException) {
+                throw IllegalStateException("Package not installed [$targetPackage]", e)
+            }
+            throw IllegalStateException("Package installed but service not found [$targetService]")
+        }
+    }
+
+    fun signal(msgData: Bundle?, isDelivered: CountDownLatch) {
+        val blockingHandler: BlockingHandler = BlockingHandler(Looper.getMainLooper(), isDelivered)
+        val msg: Message = Message.obtain()
+        msg.replyTo = Messenger(blockingHandler)
+        msgData?.let { msg.setData(it) }
+        try {
+            service?.send(msg)
+        } catch (e: RemoteException) {
+            throw RuntimeException("Remote service failed", e)
+        }
+    }
+
+    fun propagateRemoteExceptionIfPresent() {
+        if (remoteException != null) {
+            throw RuntimeException(remoteException!!)
+        }
+    }
+
+    private inner class BlockingHandler constructor(
+        private val looper: Looper,
+        private val isDelivered: CountDownLatch
+    ) :
+        Handler(looper) {
+
+        @Suppress("DEPRECATION")
+        override fun handleMessage(msg: Message) {
+            remoteException = msg.getData().getSerializable(THROWABLE_BUNDLE_KEY) as Throwable?
+            isDelivered.countDown()
+        }
+    }
+}
+
+internal fun setUpService(
+    context: Context,
+    service: Class<out Service>,
+    testData: Bundle
+): BlockingServiceConnection {
+    val serviceIntent = Intent(context, service)
+    return setUpServicesInternal(context, ImmutableList.of(serviceIntent), testData)[0]
+}
+
+internal fun setUpServices(
+    context: Context,
+    services: List<Class<out Service>>,
+    testData: Bundle
+): List<BlockingServiceConnection> {
+    val serviceIntents: MutableList<Intent> = ArrayList()
+    for (service in services) {
+        serviceIntents.add(Intent(context, service))
+    }
+    return setUpServicesInternal(context, serviceIntents, testData)
+}
+
+private fun setUpServicesInternal(
+    context: Context,
+    serviceIntents: List<Intent>,
+    testData: Bundle
+): List<BlockingServiceConnection> {
+    val connections: MutableList<BlockingServiceConnection> = ArrayList()
+    for (serviceIntent in serviceIntents) {
+        val connection = BlockingServiceConnection(context, serviceIntent)
+        connections.add(connection)
+    }
+    val connectLatch = CountDownLatch(connections.size)
+    for (connection in connections) {
+        connection.connect(connectLatch)
+    }
+    connectLatch.await()
+
+    // Send initial test data
+    val signalLatch = CountDownLatch(connections.size)
+    for (connection in connections) {
+        connection.signal(testData, signalLatch)
+    }
+    signalLatch.await()
+    for (connection in connections) {
+        connection.propagateRemoteExceptionIfPresent()
+    }
+    return connections
+}
+
+internal fun signalService(connection: BlockingServiceConnection) {
+    return signalServices(ImmutableList.of(connection))
+}
+
+internal fun signalServices(connections: List<BlockingServiceConnection>) {
+    val latch = CountDownLatch(connections.size)
+    for (connection in connections) {
+        connection.signal( /* msgData= */null, latch)
+    }
+    latch.await()
+    for (connection in connections) {
+        connection.propagateRemoteExceptionIfPresent()
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreMultiProcessTest.kt b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreMultiProcessTest.kt
new file mode 100644
index 0000000..f7fbb83
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreMultiProcessTest.kt
@@ -0,0 +1,478 @@
+/*
+ * 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.datastore.multiprocess
+
+import android.content.Context
+import android.os.Bundle
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.Serializer
+import androidx.datastore.multiprocess.handlers.NoOpCorruptionHandler
+import androidx.test.core.app.ApplicationProvider
+import androidx.testing.TestMessageProto.FooProto
+import com.google.common.truth.Truth.assertThat
+import com.google.protobuf.ExtensionRegistryLite
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.OutputStreamWriter
+import kotlin.jvm.Throws
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.async
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.newSingleThreadContext
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+private const val PATH_BUNDLE_KEY: String = "path"
+private val PROTO_SERIALIZER: Serializer<FooProto> = ProtoSerializer<FooProto>(
+    FooProto.getDefaultInstance(),
+    ExtensionRegistryLite.getEmptyRegistry()
+)
+private const val TEST_TEXT: String = "abc"
+internal val WRITE_TEXT: (FooProto) -> FooProto = { f: FooProto ->
+    f.toBuilder().setText(TEST_TEXT).build()
+}
+private val WRITE_BOOLEAN: (FooProto) -> FooProto = { f: FooProto ->
+    f.toBuilder().setBoolean(true).build()
+}
+private val INCREMENT_INTEGER: (FooProto) -> FooProto = { f: FooProto ->
+    f.toBuilder().setInteger(f.getInteger() + 1).build()
+}
+
+private val DEFAULT_FOO: FooProto = FooProto.getDefaultInstance()
+private val FOO_WITH_TEXT: FooProto =
+    FooProto.newBuilder().setText(TEST_TEXT).build()
+private val FOO_WITH_TEXT_AND_BOOLEAN: FooProto =
+    FooProto.newBuilder().setText(TEST_TEXT).setBoolean(true).build()
+
+@ExperimentalCoroutinesApi
+private fun createDataStore(
+    bundle: Bundle,
+    scope: TestScope,
+    corruptionHandler: CorruptionHandler<FooProto> = NoOpCorruptionHandler<FooProto>()
+): MultiProcessDataStore<FooProto> {
+    return MultiProcessDataStore<FooProto>(
+        { File(bundle.getString(PATH_BUNDLE_KEY)!!) },
+        PROTO_SERIALIZER,
+        scope = scope,
+        corruptionHandler = corruptionHandler
+    )
+}
+
+@OptIn(DelicateCoroutinesApi::class)
+@ExperimentalCoroutinesApi
+@RunWith(JUnit4::class)
+class MultiProcessDataStoreMultiProcessTest {
+    @get:Rule
+    val tempFolder = TemporaryFolder()
+
+    private lateinit var testFile: File
+    private lateinit var dataStoreScope: TestScope
+
+    private val TAG = "MPDS test"
+
+    private val protoSerializer: Serializer<FooProto> = ProtoSerializer<FooProto>(
+        FooProto.getDefaultInstance(),
+        ExtensionRegistryLite.getEmptyRegistry()
+    )
+    private val mainContext: Context = ApplicationProvider.getApplicationContext()
+
+    private fun createDataStoreBundle(path: String): Bundle {
+        val data = Bundle()
+        data.putString(PATH_BUNDLE_KEY, path)
+        return data
+    }
+
+    internal fun createDataStore(
+        bundle: Bundle,
+        scope: TestScope
+    ): MultiProcessDataStore<FooProto> {
+        return MultiProcessDataStore<FooProto>(
+            { File(bundle.getString(PATH_BUNDLE_KEY)!!) },
+            protoSerializer,
+            scope = scope
+        )
+    }
+
+    @Before
+    fun setUp() {
+        testFile = tempFolder.newFile()
+        dataStoreScope = TestScope(UnconfinedTestDispatcher() + Job())
+    }
+
+    @Test
+    fun testSimpleUpdateData() = runTest {
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, SimpleUpdateService::class.java, testData)
+
+        assertThat(dataStore.data.first()).isEqualTo(DEFAULT_FOO)
+
+        // Other proc commits TEST_TEXT update
+        signalService(connection)
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+    }
+
+    class SimpleUpdateService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                it.let { WRITE_TEXT(it) }
+            }
+        }
+    }
+
+    @Test
+    fun testConcurrentReadUpdate() = runTest {
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope)
+        val writerConnection: BlockingServiceConnection =
+            setUpService(mainContext, ConcurrentReadUpdateWriterService::class.java, testData)
+
+        // Start with TEST_TEXT
+        dataStore.updateData { f: FooProto -> WRITE_TEXT(f) }
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+
+        // Writer process starts (but does not yet commit) "true"
+        signalService(writerConnection)
+
+        // We can continue reading datastore while the writer process is mid-write
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+
+        // New processes that start in the meantime can also read
+        val readerConnection: BlockingServiceConnection =
+            setUpService(mainContext, ConcurrentReadUpdateReaderService::class.java, testData)
+        signalService(readerConnection)
+
+        // The other process finishes writing "true"; we (and other readers) should pick up the new data
+        signalService(writerConnection)
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
+        signalService(readerConnection)
+    }
+
+    class ConcurrentReadUpdateWriterService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                waitForSignal()
+                it.let { WRITE_BOOLEAN(it) }
+            }
+        }
+    }
+
+    class ConcurrentReadUpdateReaderService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            assertThat(store.data.first()).isEqualTo(FOO_WITH_TEXT)
+            waitForSignal()
+            assertThat(store.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
+        }
+    }
+
+    @Test
+    fun testInterleavedUpdateData() = runTest(UnconfinedTestDispatcher()) {
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, InterleavedUpdateDataService::class.java, testData)
+
+        // Other proc starts TEST_TEXT update, then waits for signal
+        signalService(connection)
+
+        // We start "true" update, then wait for condition
+        val condition = CompletableDeferred<Unit>()
+        val write = async(newSingleThreadContext("blockedWriter")) {
+            dataStore.updateData {
+                condition.await()
+                it.let { WRITE_BOOLEAN(it) }
+            }
+        }
+
+        // Allow the other proc's update to run to completion, then allow ours to run to completion
+        val unblockOurUpdate = async {
+            delay(100)
+            signalService(connection)
+            condition.complete(Unit)
+        }
+
+        unblockOurUpdate.await()
+        write.await()
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
+    }
+
+    class InterleavedUpdateDataService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                waitForSignal()
+                it.let { WRITE_TEXT(it) }
+            }
+        }
+    }
+
+    @Test
+    fun testInterleavedUpdateDataWithLocalRead() = runTest(UnconfinedTestDispatcher()) {
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, InterleavedUpdateDataWithReadService::class.java, testData)
+
+        // Invalidate any local cache
+        assertThat(dataStore.data.first()).isEqualTo(DEFAULT_FOO)
+        signalService(connection)
+
+        // Queue and start local write
+        val writeStarted = CompletableDeferred<Unit>()
+        val finishWrite = CompletableDeferred<Unit>()
+
+        val write = async {
+            dataStore.updateData {
+                writeStarted.complete(Unit)
+                finishWrite.await()
+                FOO_WITH_TEXT
+            }
+        }
+        writeStarted.await()
+
+        // Queue remote write
+        signalService(connection)
+
+        // Local uncached read; this should see data initially written remotely.
+        assertThat(dataStore.data.first()).isEqualTo(FooProto.newBuilder().setInteger(1).build())
+
+        // Unblock writes; the local write is delayed to ensure the remote write remains blocked.
+        val remoteWrite = async(newSingleThreadContext("blockedWriter")) {
+            signalService(connection)
+        }
+
+        val localWrite = async(newSingleThreadContext("unblockLocalWrite")) {
+            delay(500)
+            finishWrite.complete(Unit)
+            write.await()
+        }
+
+        localWrite.await()
+        remoteWrite.await()
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
+    }
+
+    class InterleavedUpdateDataWithReadService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                it.let { INCREMENT_INTEGER(it) }
+            }
+
+            waitForSignal()
+
+            val write = async {
+                store.updateData {
+                    it.let { WRITE_BOOLEAN(it) }
+                }
+            }
+            waitForSignal()
+            write.await()
+        }
+    }
+
+    @Test
+    fun testUpdateDataExceptionUnblocksOtherProcessFromWriting() = runTest {
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, CancelledUpdateDataService::class.java, testData)
+
+        val blockWrite = CompletableDeferred<Unit>()
+        val waitForWrite = CompletableDeferred<Unit>()
+
+        val write = async {
+            try {
+                dataStore.updateData {
+                    blockWrite.await()
+                    throw IOException("Something went wrong")
+                }
+            } catch (e: IOException) {
+                waitForWrite.complete(Unit)
+            }
+        }
+
+        assertThat(write.isActive).isTrue()
+        assertThat(write.isCompleted).isFalse()
+
+        blockWrite.complete(Unit)
+        waitForWrite.await()
+
+        assertThat(write.isActive).isFalse()
+        assertThat(write.isCompleted).isTrue()
+
+        signalService(connection)
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+    }
+
+    class CancelledUpdateDataService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            store = createDataStore(testData, scope)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                it.let { WRITE_TEXT(it) }
+            }
+        }
+    }
+
+    @Test
+    fun testUpdateDataCancellationUnblocksOtherProcessFromWriting() = runTest(
+        UnconfinedTestDispatcher()
+    ) {
+        val localScope = TestScope(UnconfinedTestDispatcher() + Job())
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, localScope)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, CancelledUpdateDataService::class.java, testData)
+
+        val blockWrite = CompletableDeferred<Unit>()
+
+        val write = localScope.async {
+            dataStore.updateData {
+                blockWrite.await()
+                it.let { WRITE_BOOLEAN(it) }
+            }
+        }
+
+        assertThat(write.isActive).isTrue()
+        assertThat(write.isCompleted).isFalse()
+
+        // dataStore.updateData cancelled immediately
+        localScope.coroutineContext.cancelChildren()
+
+        assertThat(write.isActive).isFalse()
+        assertThat(write.isCompleted).isTrue()
+
+        signalService(connection)
+
+        // able to read the new value written from the other process
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+    }
+
+    @Test
+    fun testReadUpdateCorrupt() = runTest {
+        FileOutputStream(testFile).use {
+            OutputStreamWriter(it).write("garbage")
+        }
+        val testData: Bundle = createDataStoreBundle(testFile.absolutePath)
+        val connection: BlockingServiceConnection =
+            setUpService(mainContext, InterleavedHandlerUpdateDataService::class.java, testData)
+        val corruptionHandler = ReplaceFileCorruptionHandler<FooProto> {
+            signalService(connection)
+            FOO_WITH_TEXT_AND_BOOLEAN
+        }
+        val dataStore: MultiProcessDataStore<FooProto> =
+            createDataStore(testData, dataStoreScope, corruptionHandler)
+
+        // Other proc starts TEST_TEXT then waits for signal within handler
+        signalService(connection)
+
+        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
+    }
+
+    class InterleavedHandlerUpdateDataService(
+        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
+    ) : DirectTestService() {
+        override fun beforeTest(testData: Bundle) {
+            val corruptionHandler: CorruptionHandler<FooProto> =
+                ReplaceFileCorruptionHandler<FooProto> {
+                    waitForSignal()
+                    DEFAULT_FOO
+                }
+            store = createDataStore(testData, scope, corruptionHandler)
+        }
+
+        override fun runTest() = runBlocking<Unit> {
+            store.updateData {
+                it.let { WRITE_TEXT(it) }
+            }
+        }
+    }
+
+    /**
+     * A corruption handler that attempts to replace the on-disk data with data from produceNewData.
+     *
+     * TODO(zhiyuanwang): replace with androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
+     */
+    private class ReplaceFileCorruptionHandler<T>(
+        private val produceNewData: (CorruptionException) -> T
+    ) : CorruptionHandler<T> {
+
+        @Throws(IOException::class)
+        override suspend fun handleCorruption(ex: CorruptionException): T {
+            return produceNewData(ex)
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreTest.kt b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreTest.kt
new file mode 100644
index 0000000..666863e
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/MultiProcessDataStoreTest.kt
@@ -0,0 +1,998 @@
+/*
+ * 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.datastore.multiprocess
+
+import android.os.StrictMode
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.DataStore
+import androidx.datastore.core.Serializer
+import androidx.datastore.multiprocess.handlers.NoOpCorruptionHandler
+import androidx.test.filters.LargeTest
+import androidx.testutils.assertThrows
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicInteger
+import kotlin.coroutines.AbstractCoroutineContextElement
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.flow.toList
+import kotlinx.coroutines.job
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.newSingleThreadContext
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.withContext
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/**
+ * A testing class based on duplicate from "SingleProcessDataStoreTest" that only tests the features
+ * in a single process use case. More tests are added for StrictMode.
+ */
+@OptIn(DelicateCoroutinesApi::class)
+@ExperimentalCoroutinesApi
+@LargeTest
+@RunWith(JUnit4::class)
+class MultiProcessDataStoreTest {
+    @get:Rule
+    val tempFolder = TemporaryFolder()
+
+    private lateinit var store: DataStore<Byte>
+    private lateinit var testingSerializer: TestingSerializer
+    private lateinit var testFile: File
+    private lateinit var dataStoreScope: TestScope
+
+    private fun newDataStore(
+        file: File = testFile,
+        serializer: Serializer<Byte> = testingSerializer,
+        scope: CoroutineScope = dataStoreScope,
+        initTasksList: List<suspend (api: InitializerApi<Byte>) -> Unit> = listOf(),
+        corruptionHandler: CorruptionHandler<Byte> = NoOpCorruptionHandler<Byte>()
+    ): DataStore<Byte> {
+        return MultiProcessDataStore(
+            { file },
+            serializer = serializer,
+            scope = scope,
+            initTasksList = initTasksList,
+            corruptionHandler = corruptionHandler
+        )
+    }
+
+    @Before
+    fun setUp() {
+        testingSerializer = TestingSerializer()
+        testFile = tempFolder.newFile()
+        dataStoreScope = TestScope(UnconfinedTestDispatcher() + Job())
+        store =
+            MultiProcessDataStore<Byte>(
+                { testFile },
+                testingSerializer,
+                scope = dataStoreScope
+            )
+    }
+
+    @Test
+    fun testReadNewMessage() = runTest {
+        assertThat(store.data.first()).isEqualTo(0)
+    }
+
+    @Test
+    fun testReadWithNewInstance() = runTest {
+        coroutineScope {
+            val newStore = newDataStore(testFile, scope = this)
+            newStore.updateData { 1 }
+        }
+        coroutineScope {
+            val newStore = newDataStore(testFile, scope = this)
+            assertThat(newStore.data.first()).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testReadUnreadableFile() = runTest {
+        testFile.setReadable(false)
+        val result = runCatching {
+            store.data.first()
+        }
+
+        assertThat(result.exceptionOrNull()).isInstanceOf(IOException::class.java)
+        assertThat(result.exceptionOrNull()).hasMessageThat().contains("Permission denied")
+    }
+
+    @Test
+    fun testReadAfterTransientBadRead() = runTest {
+        testFile.setReadable(false)
+
+        assertThrows<IOException> { store.data.first() }.hasMessageThat()
+            .contains("Permission denied")
+
+        testFile.setReadable(true)
+        assertThat(store.data.first()).isEqualTo(0)
+    }
+
+    @Test
+    fun testScopeCancelledWithActiveFlow() = runTest {
+        val storeScope = CoroutineScope(Job())
+        val dataStore = newDataStore(scope = storeScope)
+        val collection = async {
+            dataStore.data.take(2).collect {
+                // Do nothing, this will wait on another element which will never arrive
+            }
+        }
+
+        storeScope.cancel()
+        collection.join()
+
+        assertThat(collection.isCompleted).isTrue()
+        assertThat(collection.isActive).isFalse()
+    }
+
+    @Test
+    fun testWriteAndRead() = runTest {
+        store.updateData { 1 }
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testWritesDontBlockReadsInSameProcess() = runTest {
+        val transformStarted = CompletableDeferred<Unit>()
+        val continueTransform = CompletableDeferred<Unit>()
+
+        val slowUpdate = async {
+            store.updateData {
+                transformStarted.complete(Unit)
+                continueTransform.await()
+                it.inc()
+            }
+        }
+        // Wait for the transform to begin.
+        transformStarted.await()
+
+        // Read is not blocked.
+        assertThat(store.data.first()).isEqualTo(0)
+
+        continueTransform.complete(Unit)
+        slowUpdate.await()
+
+        // After update completes, update runs, and read shows new data.
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testWriteMultiple() = runTest {
+        store.updateData { 2 }
+
+        assertThat(store.data.first()).isEqualTo(2)
+
+        store.updateData { it.dec() }
+
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testReadAfterTransientBadWrite() = runTest {
+        val file = tempFolder.newFile()
+        coroutineScope {
+            val store = newDataStore(file, scope = this)
+            store.updateData { 1 }
+            testingSerializer.failingWrite = true
+            assertThrows<IOException> { store.updateData { 2 } }
+        }
+
+        coroutineScope {
+            val newStore = newDataStore(file, scope = this)
+            assertThat(newStore.data.first()).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testWriteToNonExistentDir() = runTest {
+        val fileInNonExistentDir =
+            File(tempFolder.newFolder(), "/this/does/not/exist/foo.tst")
+        coroutineScope {
+            val newStore = newDataStore(fileInNonExistentDir, scope = this)
+
+            newStore.updateData { 1 }
+
+            assertThat(newStore.data.first()).isEqualTo(1)
+        }
+
+        coroutineScope {
+            val newStore = newDataStore(fileInNonExistentDir, scope = this)
+            assertThat(newStore.data.first()).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testReadFromNonExistentFile() = runTest {
+        val nonExistentFile = tempFolder.newFile()
+        assertThat(nonExistentFile.delete()).isTrue()
+        val newStore = newDataStore(nonExistentFile)
+        assertThat(newStore.data.first()).isEqualTo(0)
+    }
+
+    @Test
+    fun testWriteToDirFails() = runTest {
+        val directoryFile =
+            File(tempFolder.newFolder(), "/this/is/a/directory")
+        directoryFile.mkdirs()
+        assertThat(directoryFile.isDirectory).isTrue()
+
+        val newStore = newDataStore(directoryFile)
+        assertThrows<IOException> { newStore.data.first() }
+    }
+
+    @Test
+    fun testExceptionWhenCreatingFilePropagates() = runTest {
+        var failFileProducer = true
+
+        val fileProducer = {
+            if (failFileProducer) {
+                throw IOException("Exception when producing file")
+            }
+            testFile
+        }
+
+        val newStore = MultiProcessDataStore(
+            fileProducer,
+            serializer = testingSerializer,
+            scope = dataStoreScope,
+            initTasksList = listOf()
+        )
+
+        assertThrows<IOException> { newStore.data.first() }.hasMessageThat().isEqualTo(
+            "Exception when producing file"
+        )
+
+        failFileProducer = false
+
+        assertThat(newStore.data.first()).isEqualTo(0)
+    }
+
+    @Test
+    fun testWriteTransformCancellation() = runTest {
+        val transform = CompletableDeferred<Byte>()
+
+        val write = async { store.updateData { transform.await() } }
+
+        assertThat(write.isCompleted).isFalse()
+
+        transform.cancel()
+
+        assertThrows<CancellationException> { write.await() }
+
+        // Check that the datastore's scope is still active:
+
+        assertThat(store.updateData { it.inc().inc() }).isEqualTo(2)
+    }
+
+    @Test
+    fun testWriteAfterTransientBadRead() = runTest {
+        testingSerializer.failingRead = true
+
+        assertThrows<IOException> { store.data.first() }
+
+        testingSerializer.failingRead = false
+
+        store.updateData { 1 }
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testWriteWithBadReadFails() = runTest {
+        testingSerializer.failingRead = true
+
+        assertThrows<IOException> { store.updateData { 1 } }
+    }
+
+    @Test
+    fun testCancellingDataStoreScopePropagatesToWrites() = runBlocking<Unit> {
+        val scope = CoroutineScope(Job())
+
+        val dataStore = newDataStore(scope = scope)
+
+        val latch = CompletableDeferred<Unit>()
+
+        val slowUpdate = async {
+            dataStore.updateData {
+                latch.await()
+                it.inc()
+            }
+        }
+
+        val notStartedUpdate = async {
+            dataStore.updateData {
+                it.inc()
+            }
+        }
+
+        scope.cancel()
+
+        assertThrows<CancellationException> { slowUpdate.await() }
+
+        assertThrows<CancellationException> { notStartedUpdate.await() }
+
+        assertThrows<CancellationException> { dataStore.updateData { 123 } }
+    }
+
+    @Test
+    fun testCancellingCallerScopePropagatesToWrites() = runBlocking<Unit> {
+        val dsScope = CoroutineScope(Job())
+        val callerScope = CoroutineScope(Job())
+
+        val dataStore = newDataStore(scope = dsScope)
+
+        val latch = CompletableDeferred<Unit>()
+
+        // The ordering of the following are not guaranteed but I think they won't be flaky with
+        // Dispatchers.Unconfined
+        val awaitingCancellation = callerScope.async(Dispatchers.Unconfined) {
+            dataStore.updateData { awaitCancellation() }
+        }
+
+        dsScope.launch(Dispatchers.Unconfined) {
+            dataStore.updateData {
+                latch.await()
+                it.inc()
+            }
+        }
+
+        val notStarted = callerScope.async(Dispatchers.Unconfined) {
+            dataStore.updateData { it.inc() }
+        }
+
+        callerScope.coroutineContext.job.cancelAndJoin()
+
+        assertThat(awaitingCancellation.isCancelled).isTrue()
+        assertThat(notStarted.isCancelled).isTrue()
+    }
+
+    @Test
+    fun testCanWriteFromInitTask() = runTest {
+        store = newDataStore(initTasksList = listOf { api -> api.updateData { 1 } })
+
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testInitTaskFailsFirstTimeDueToReadFail() = runTest {
+        store = newDataStore(initTasksList = listOf { api -> api.updateData { 1 } })
+
+        testingSerializer.failingRead = true
+        assertThrows<IOException> { store.updateData { 2 } }
+
+        testingSerializer.failingRead = false
+        store.updateData { it.inc().inc() }
+
+        assertThat(store.data.first()).isEqualTo(3)
+    }
+
+    @Test
+    fun testInitTaskFailsFirstTimeDueToException() = runTest {
+        val failInit = AtomicBoolean(true)
+        store = newDataStore(
+            initTasksList = listOf { _ ->
+                if (failInit.get()) {
+                    throw IOException("I was asked to fail init")
+                }
+            }
+        )
+        assertThrows<IOException> { store.updateData { 5 } }
+
+        failInit.set(false)
+
+        store.updateData { it.inc() }
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testInitTaskOnlyRunsOnce() = runTest {
+        val count = AtomicInteger()
+        val newStore = newDataStore(
+            testFile,
+            initTasksList = listOf { _ ->
+                count.incrementAndGet()
+            }
+        )
+
+        repeat(10) {
+            newStore.updateData { it.inc() }
+            newStore.data.first()
+        }
+
+        assertThat(count.get()).isEqualTo(1)
+    }
+
+    @Test
+    fun testWriteDuringInit() = runTest {
+        val continueInit = CompletableDeferred<Unit>()
+
+        store = newDataStore(
+            initTasksList = listOf { api ->
+                continueInit.await()
+                api.updateData { 1 }
+            }
+        )
+
+        val update = async {
+            store.updateData { b ->
+                assertThat(b).isEqualTo(1)
+                b
+            }
+        }
+
+        continueInit.complete(Unit)
+        update.await()
+
+        assertThat(store.data.first()).isEqualTo(1)
+    }
+
+    @Test
+    fun testCancelDuringInit() = runTest {
+        val continueInit = CompletableDeferred<Unit>()
+
+        store = newDataStore(
+            initTasksList = listOf { api ->
+                continueInit.await()
+                api.updateData { 1 }
+            }
+        )
+
+        val update = async {
+            store.updateData { it }
+        }
+
+        val read = async {
+            store.data.first()
+        }
+
+        update.cancel()
+        read.cancel()
+        continueInit.complete(Unit)
+
+        assertThrows<CancellationException> { update.await() }
+        assertThrows<CancellationException> { read.await() }
+
+        store.updateData { it.inc().inc() }
+
+        assertThat(store.data.first()).isEqualTo(3)
+    }
+
+    @Test
+    fun testConcurrentUpdatesInit() = runTest {
+        val continueUpdate = CompletableDeferred<Unit>()
+
+        val concurrentUpdateInitializer: suspend (InitializerApi<Byte>) -> Unit = { api ->
+            val update1 = async {
+                api.updateData {
+                    continueUpdate.await()
+                    it.inc().inc()
+                }
+            }
+            api.updateData {
+                it.inc()
+            }
+            update1.await()
+        }
+
+        store = newDataStore(initTasksList = listOf(concurrentUpdateInitializer))
+        val getData = async { store.data.first() }
+        continueUpdate.complete(Unit)
+
+        assertThat(getData.await()).isEqualTo(3)
+    }
+
+    @Test
+    fun testInitUpdateBlockRead() = runTest {
+        val continueInit = CompletableDeferred<Unit>()
+        val continueUpdate = CompletableDeferred<Unit>()
+
+        val updateInitializer: suspend (InitializerApi<Byte>) -> Unit = { api ->
+            api.updateData {
+                continueInit.await()
+                it.inc()
+            }
+        }
+
+        store = newDataStore(initTasksList = listOf(updateInitializer))
+        val getData = async { store.data.first() }
+        val updateData = async {
+            store.updateData {
+                continueUpdate.await()
+                it.inc()
+            }
+        }
+
+        assertThat(getData.isCompleted).isFalse()
+        assertThat(getData.isActive).isTrue()
+
+        continueInit.complete(Unit)
+        assertThat(getData.await()).isEqualTo(1)
+
+        assertThat(updateData.isCompleted).isFalse()
+        assertThat(updateData.isActive).isTrue()
+
+        continueUpdate.complete(Unit)
+        assertThat(updateData.await()).isEqualTo(2)
+        assertThat(store.data.first()).isEqualTo(2)
+    }
+
+    @Test
+    fun testUpdateSuccessfullyCommittedInit() = runTest {
+        var otherStorage: Byte = 123
+
+        val initializer: suspend (InitializerApi<Byte>) -> Unit = { api ->
+            api.updateData {
+                otherStorage
+            }
+            // Similar to cleanUp():
+            otherStorage = 0
+        }
+
+        val store = newDataStore(initTasksList = listOf(initializer))
+
+        testingSerializer.failingWrite = true
+        assertThrows<IOException> { store.data.first() }
+
+        testingSerializer.failingWrite = false
+        assertThat(store.data.first()).isEqualTo(123)
+    }
+
+    @Test
+    fun testInitApiUpdateThrowsAfterInitTasksComplete() = runTest {
+        var savedApi: InitializerApi<Byte>? = null
+
+        val initializer: suspend (InitializerApi<Byte>) -> Unit = { api ->
+            savedApi = api
+        }
+
+        val store = newDataStore(initTasksList = listOf(initializer))
+
+        assertThat(store.data.first()).isEqualTo(0)
+
+        assertThrows<IllegalStateException> { savedApi?.updateData { 123 } }
+    }
+
+    @Test
+    fun testFlowReceivesUpdates() = runTest {
+        val collectedBytes = mutableListOf<Byte>()
+
+        val flowCollectionJob = async {
+            store.data.take(8).toList(collectedBytes)
+        }
+
+        repeat(7) {
+            store.updateData { it.inc() }
+        }
+
+        flowCollectionJob.join()
+
+        assertThat(collectedBytes).isEqualTo(mutableListOf<Byte>(0, 1, 2, 3, 4, 5, 6, 7))
+    }
+
+    @Test
+    fun testMultipleFlowsReceiveData() = runTest {
+        val flowOf8 = store.data.take(8)
+
+        val bytesFromFirstCollect = mutableListOf<Byte>()
+        val bytesFromSecondCollect = mutableListOf<Byte>()
+
+        val flowCollection1 = async {
+            flowOf8.toList(bytesFromFirstCollect)
+        }
+
+        val flowCollection2 = async {
+            flowOf8.toList(bytesFromSecondCollect)
+        }
+
+        repeat(7) {
+            store.updateData { it.inc() }
+        }
+
+        flowCollection1.join()
+        flowCollection2.join()
+
+        assertThat(bytesFromFirstCollect).isEqualTo(mutableListOf<Byte>(0, 1, 2, 3, 4, 5, 6, 7))
+        assertThat(bytesFromSecondCollect).isEqualTo(mutableListOf<Byte>(0, 1, 2, 3, 4, 5, 6, 7))
+    }
+
+    @Test
+    fun testExceptionInFlowDoesNotBreakUpstream() = runTest {
+        val flowOf8 = store.data.take(8)
+
+        val collectedBytes = mutableListOf<Byte>()
+
+        val failedFlowCollection = async {
+            assertThrows<Exception> {
+                flowOf8.collect {
+                    throw Exception("Failure while collecting")
+                }
+            }.hasMessageThat().contains("Failure while collecting")
+        }
+
+        val successfulFlowCollection = async {
+            flowOf8.take(8).toList(collectedBytes)
+        }
+
+        repeat(7) {
+            store.updateData { it.inc() }
+        }
+
+        successfulFlowCollection.join()
+        failedFlowCollection.await()
+
+        assertThat(collectedBytes).isEqualTo(mutableListOf<Byte>(0, 1, 2, 3, 4, 5, 6, 7))
+    }
+
+    @Test
+    fun testSlowConsumerDoesntBlockOtherConsumers() = runTest {
+        val flowOf8 = store.data.take(8)
+
+        val collectedBytes = mutableListOf<Byte>()
+
+        val flowCollection2 = async {
+            flowOf8.toList(collectedBytes)
+        }
+
+        val blockedCollection = async {
+            flowOf8.collect {
+                flowCollection2.await()
+            }
+        }
+
+        repeat(15) {
+            store.updateData { it.inc() }
+        }
+
+        flowCollection2.await()
+        assertThat(collectedBytes).isEqualTo(mutableListOf<Byte>(0, 1, 2, 3, 4, 5, 6, 7))
+
+        blockedCollection.await()
+    }
+
+    @Test
+    fun testHandlerNotCalledGoodData() = runTest {
+        coroutineScope {
+            newDataStore(testFile, scope = this).updateData { 1 }
+        }
+
+        coroutineScope {
+            val testingHandler: TestingCorruptionHandler = TestingCorruptionHandler()
+            val newStore = newDataStore(corruptionHandler = testingHandler, file = testFile)
+
+            newStore.updateData { 2 }
+            newStore.data.first()
+
+            assertThat(testingHandler.numCalls).isEqualTo(0)
+        }
+    }
+
+    @Test
+    fun handlerNotCalledNonCorruption() = runTest {
+        coroutineScope {
+            newDataStore(testFile, scope = this).updateData { 1 }
+        }
+
+        coroutineScope {
+            val testingHandler = TestingCorruptionHandler()
+            testingSerializer.failingRead = true
+            val newStore = newDataStore(corruptionHandler = testingHandler, file = testFile)
+
+            assertThrows<IOException> { newStore.updateData { 2 } }
+            assertThrows<IOException> { newStore.data.first() }
+
+            assertThat(testingHandler.numCalls).isEqualTo(0)
+        }
+    }
+
+    @Test
+    fun testHandlerCalledCorruptDataRead() = runTest {
+        coroutineScope {
+            val newStore = newDataStore(testFile, scope = this)
+            newStore.updateData { 1 } // Pre-seed the data so the file exists.
+        }
+
+        coroutineScope {
+            val testingHandler: TestingCorruptionHandler = TestingCorruptionHandler()
+            testingSerializer.failReadWithCorruptionException = true
+            val newStore = newDataStore(corruptionHandler = testingHandler, file = testFile)
+
+            assertThrows<IOException> { newStore.data.first() }.hasMessageThat().contains(
+                "Handler thrown exception."
+            )
+
+            assertThat(testingHandler.numCalls).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testHandlerCalledCorruptDataWrite() = runTest {
+        coroutineScope {
+            val newStore = newDataStore(file = testFile, scope = this)
+            newStore.updateData { 1 }
+        }
+
+        coroutineScope {
+            val testingHandler: TestingCorruptionHandler = TestingCorruptionHandler()
+            testingSerializer.failReadWithCorruptionException = true
+            val newStore = newDataStore(corruptionHandler = testingHandler, file = testFile)
+
+            assertThrows<IOException> { newStore.updateData { 1 } }.hasMessageThat().contains(
+                "Handler thrown exception."
+            )
+
+            assertThat(testingHandler.numCalls).isEqualTo(1)
+        }
+    }
+
+    @Test
+    fun testHandlerReplaceData() = runTest {
+        coroutineScope {
+            newDataStore(file = testFile, scope = this).updateData { 1 }
+        }
+
+        coroutineScope {
+            val testingHandler: TestingCorruptionHandler =
+                TestingCorruptionHandler(replaceWith = 10)
+            testingSerializer.failReadWithCorruptionException = true
+            val newStore = newDataStore(
+                corruptionHandler = testingHandler, file = testFile,
+                scope = this
+            )
+
+            assertThat(newStore.data.first()).isEqualTo(10)
+        }
+    }
+
+    @Test
+    fun testMutatingDataStoreFails() = runTest {
+
+        val dataStore = MultiProcessDataStore(
+            { testFile },
+            ByteWrapper.ByteWrapperSerializer(),
+            scope = dataStoreScope,
+        )
+
+        assertThrows<IllegalStateException> {
+            dataStore.updateData { input: ByteWrapper ->
+                // mutating our wrapper causes us to fail
+                input.byte = 123.toByte()
+                input
+            }
+        }
+    }
+
+    @Test
+    fun testDefaultValueUsedWhenNoDataOnDisk() = runTest {
+        val dataStore = MultiProcessDataStore(
+            { testFile },
+            TestingSerializer(defaultValue = 99),
+            scope = dataStoreScope
+        )
+
+        assertThat(testFile.delete()).isTrue()
+
+        assertThat(dataStore.data.first()).isEqualTo(99)
+    }
+
+    @Test
+    fun testTransformRunInCallersContext() = runBlocking<Unit> {
+        suspend fun getContext(): CoroutineContext {
+            return kotlin.coroutines.coroutineContext
+        }
+
+        withContext(TestElement("123")) {
+            store.updateData {
+                val context = getContext()
+                assertThat(context[TestElement.Key]!!.name).isEqualTo("123")
+                it.inc()
+            }
+        }
+    }
+
+    private class TestElement(
+        val name: String
+    ) : AbstractCoroutineContextElement(Key) {
+        companion object Key : CoroutineContext.Key<TestElement>
+    }
+
+    @Test
+    fun testCancelInflightWrite() = runBlocking<Unit> {
+        val myScope =
+            CoroutineScope(Job() + Executors.newSingleThreadExecutor().asCoroutineDispatcher())
+
+        val updateStarted = CompletableDeferred<Unit>()
+        myScope.launch {
+            store.updateData {
+                updateStarted.complete(Unit)
+                awaitCancellation()
+            }
+        }
+        updateStarted.await()
+        myScope.coroutineContext[Job]!!.cancelAndJoin()
+    }
+
+    @Test
+    fun testWrite_afterCanceledWrite_succeeds() = runBlocking<Unit> {
+        val myScope =
+            CoroutineScope(Job() + Executors.newSingleThreadExecutor().asCoroutineDispatcher())
+
+        val cancelNow = CompletableDeferred<Unit>()
+
+        myScope.launch {
+            store.updateData {
+                cancelNow.complete(Unit)
+                awaitCancellation()
+            }
+        }
+
+        cancelNow.await()
+        myScope.coroutineContext[Job]!!.cancelAndJoin()
+
+        store.updateData { 123 }
+    }
+
+    @Test
+    fun testWrite_fromOtherScope_doesntGetCancelledFromDifferentScope() = runBlocking<Unit> {
+
+        val otherScope = CoroutineScope(Job())
+
+        val callerScope = CoroutineScope(Job())
+
+        val firstUpdateStarted = CompletableDeferred<Unit>()
+        val finishFirstUpdate = CompletableDeferred<Byte>()
+
+        val firstUpdate = otherScope.async(Dispatchers.Unconfined) {
+            store.updateData {
+                firstUpdateStarted.complete(Unit)
+                finishFirstUpdate.await()
+            }
+        }
+
+        callerScope.launch(Dispatchers.Unconfined) {
+            store.updateData {
+                awaitCancellation()
+            }
+        }
+
+        firstUpdateStarted.await()
+        callerScope.coroutineContext.job.cancelAndJoin()
+        finishFirstUpdate.complete(1)
+        firstUpdate.await()
+
+        // It's still usable:
+        assertThat(store.updateData { it.inc() }).isEqualTo(2)
+    }
+
+    @Test
+    fun testCreateDuplicateActiveDataStore() = runTest {
+        val file = tempFolder.newFile()
+        val dataStore = newDataStore(file = file, scope = CoroutineScope(Job()))
+
+        dataStore.data.first()
+
+        val duplicateDataStore = newDataStore(file = file, scope = CoroutineScope(Job()))
+
+        assertThrows<IllegalStateException> {
+            duplicateDataStore.data.first()
+        }
+    }
+
+    @Test
+    fun testCreateDataStore_withSameFileAsInactiveDataStore() = runTest {
+        val file = tempFolder.newFile()
+        val scope1 = CoroutineScope(Job())
+        val dataStore1 = newDataStore(file = file, scope = scope1)
+
+        dataStore1.data.first()
+
+        scope1.coroutineContext.job.cancelAndJoin()
+
+        val dataStore2 = newDataStore(file = file, scope = CoroutineScope(Job()))
+
+        // This shouldn't throw an exception bc the scope1 has been cancelled.
+        dataStore2.data.first()
+    }
+
+    @Test
+    fun testCreateDataStoreAndRead_withStrictMode() = runTest {
+        StrictMode.setThreadPolicy(
+            StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().penaltyDeath()
+                .build()
+        )
+        val dataStore =
+            newDataStore(file = testFile, scope = CoroutineScope(newSingleThreadContext("test")))
+        assertThat(dataStore.data.first()).isEqualTo(0)
+        StrictMode.allowThreadDiskReads()
+        StrictMode.allowThreadDiskWrites()
+    }
+
+    @Test
+    fun testCreateDataStoreAndUpdate_withStrictMode() = runTest {
+        StrictMode.setThreadPolicy(
+            StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().penaltyDeath()
+                .build()
+        )
+        val dataStore =
+            newDataStore(file = testFile, scope = CoroutineScope(newSingleThreadContext("test")))
+        dataStore.updateData { it.inc() }
+        assertThat(dataStore.data.first()).isEqualTo(1)
+        StrictMode.allowThreadDiskReads()
+        StrictMode.allowThreadDiskWrites()
+    }
+
+    // Mutable wrapper around a byte
+    data class ByteWrapper(var byte: Byte) {
+        internal class ByteWrapperSerializer() : Serializer<ByteWrapper> {
+            private val delegate = TestingSerializer()
+
+            override val defaultValue = ByteWrapper(delegate.defaultValue)
+
+            override suspend fun readFrom(input: InputStream): ByteWrapper {
+                return ByteWrapper(delegate.readFrom(input))
+            }
+
+            override suspend fun writeTo(t: ByteWrapper, output: OutputStream) {
+                delegate.writeTo(t.byte, output)
+            }
+        }
+    }
+
+    private class TestingCorruptionHandler(
+        private val replaceWith: Byte? = null
+    ) : CorruptionHandler<Byte> {
+
+        @Volatile
+        var numCalls = 0
+
+        override suspend fun handleCorruption(ex: CorruptionException): Byte {
+            numCalls++
+
+            replaceWith?.let {
+                return it
+            }
+
+            throw IOException("Handler thrown exception.")
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/ProtoSerializer.kt b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/ProtoSerializer.kt
new file mode 100644
index 0000000..3a6f92a
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/ProtoSerializer.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.datastore.multiprocess
+
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.Serializer
+import com.google.protobuf.ExtensionRegistryLite
+import com.google.protobuf.InvalidProtocolBufferException
+import com.google.protobuf.MessageLite
+import java.io.InputStream
+import java.io.OutputStream
+
+/** Serializer for using DataStore with protos. */
+internal class ProtoSerializer<T : MessageLite>(
+    /** The default proto of this type, obtained via {@code T.getDefaultInstance()} */
+    override val defaultValue: T,
+    /**
+     *  Set the extensionRegistryLite to use when deserializing T. If no extension registry is
+     *  necessary, use {@code ExtensionRegistryLite.getEmptyRegistry()}.
+     */
+    private val extensionRegistryLite: ExtensionRegistryLite
+) : Serializer<T> {
+
+    @Suppress("UNCHECKED_CAST")
+    override suspend fun readFrom(input: InputStream): T {
+        try {
+            return defaultValue.parserForType.parseFrom(input, extensionRegistryLite) as T
+        } catch (invalidProtocolBufferException: InvalidProtocolBufferException) {
+            throw CorruptionException(
+                "Cannot read proto.", invalidProtocolBufferException
+            )
+        }
+    }
+
+    override suspend fun writeTo(t: T, output: OutputStream) {
+        t.writeTo(output)
+    }
+}
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/TestingSerializer.kt b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/TestingSerializer.kt
new file mode 100644
index 0000000..86d7763
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/androidTest/java/androidx/datastore/multiprocess/TestingSerializer.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.datastore.multiprocess
+
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.Serializer
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+
+internal class TestingSerializer(
+    @Volatile var failReadWithCorruptionException: Boolean = false,
+    @Volatile var failingRead: Boolean = false,
+    @Volatile var failingWrite: Boolean = false,
+    override val defaultValue: Byte = 0
+) : Serializer<Byte> {
+    override suspend fun readFrom(input: InputStream): Byte {
+        if (failReadWithCorruptionException) {
+            throw CorruptionException(
+                "CorruptionException",
+                IOException()
+            )
+        }
+
+        if (failingRead) {
+            throw IOException("I was asked to fail on reads")
+        }
+
+        val read = input.read()
+        if (read == -1) {
+            return 0
+        }
+        return read.toByte()
+    }
+
+    override suspend fun writeTo(t: Byte, output: OutputStream) {
+        if (failingWrite) {
+            throw IOException("I was asked to fail on writes")
+        }
+        output.write(t.toInt())
+    }
+}
\ No newline at end of file
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt b/datastore/datastore-multiprocess/src/androidTest/proto/test.proto
similarity index 61%
copy from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt
copy to datastore/datastore-multiprocess/src/androidTest/proto/test.proto
index 19e2105..0ad7b69 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt
+++ b/datastore/datastore-multiprocess/src/androidTest/proto/test.proto
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy
+// Protos for use in tests
+syntax = "proto2";
 
-import androidx.compose.runtime.MonotonicFrameClock
-import java.util.concurrent.atomic.AtomicLong
+package androidx.testing;
 
-class AutoTestFrameClock : MonotonicFrameClock {
-    private val time = AtomicLong(0)
+option java_package = "androidx.testing";
+option java_outer_classname = "TestMessageProto";
 
-    override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R {
-        return onFrame(time.getAndAdd(16_000_000))
-    }
-}
\ No newline at end of file
+message FooProto {
+  optional string text = 1;
+  optional bool boolean = 2;
+  optional int32 integer = 3;
+  optional bytes bytes = 4;
+}
diff --git a/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/MultiProcessDataStore.kt b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/MultiProcessDataStore.kt
index 51e4717..07cc6edc 100644
--- a/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/MultiProcessDataStore.kt
+++ b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/MultiProcessDataStore.kt
@@ -16,6 +16,7 @@
 
 package androidx.datastore.multiprocess
 
+import android.os.FileObserver
 import androidx.annotation.GuardedBy
 import androidx.datastore.core.CorruptionException
 import androidx.datastore.core.DataStore
@@ -26,6 +27,7 @@
 import java.io.FileNotFoundException
 import java.io.FileOutputStream
 import java.io.IOException
+import java.util.concurrent.Semaphore
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.coroutineContext
 import kotlinx.coroutines.completeWith
@@ -47,8 +49,6 @@
 /**
  * Multi process implementation of DataStore. It is multi-process safe.
  */
-// TODO(zhiyuanwang): copied straight from {@link androidx.datastore.core.SingleProcessDataStore},
-// replace with the real multi process implementation
 internal class MultiProcessDataStore<T>(
     private val produceFile: () -> File,
     private val serializer: Serializer<T>,
@@ -63,7 +63,6 @@
     private val corruptionHandler: CorruptionHandler<T> = NoOpCorruptionHandler<T>(),
     private val scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
 ) : DataStore<T> {
-
     override val data: Flow<T> = flow {
         /**
          * If downstream flow is UnInitialized, no data has been read yet, we need to trigger a new
@@ -73,7 +72,9 @@
          * data. We need to trigger a new read then start emitting values once we have seen a new
          * value (or exception).
          *
-         * If downstream flow has Data, we should just start emitting from downstream flow.
+         * If downstream flow has Data, we should start emitting from downstream flow as long as its
+         * version is not stale compared to the version read from the shared counter when we enter
+         * the flow.
          *
          * If Downstream flow is Final, the scope has been cancelled so the data store is no
          * longer usable. We should just propagate this exception.
@@ -82,20 +83,25 @@
          * Final. ReadException can transition to another ReadException, Data or Final.
          * Data can transition to another Data or Final. Final will not change.
          */
-
+        // TODO(b/241290444): avoid coroutine switching by loading native lib during initialization
+        val latestVersionAtRead = withContext(scope.coroutineContext) { sharedCounter.getValue() }
         val currentDownStreamFlowState = downstreamFlow.value
 
-        if (currentDownStreamFlowState !is Data) {
-            // We need to send a read request because we don't have data yet.
-            actor.offer(Message.Read(currentDownStreamFlowState))
+        if ((currentDownStreamFlowState !is Data) ||
+            (currentDownStreamFlowState.version < latestVersionAtRead)
+        ) {
+            // We need to send a read request because we don't have data yet / cached data is stale.
+            readActor.offer(Message.Read(currentDownStreamFlowState))
         }
 
         emitAll(
             downstreamFlow.dropWhile {
-                if (currentDownStreamFlowState is Data<T> ||
-                    currentDownStreamFlowState is Final<T>
-                ) {
-                    // We don't need to drop any Data or Final values.
+                if (currentDownStreamFlowState is Data<T>) {
+                    // we need to drop until initTasks are completed and set to null, and data
+                    // version >= the current version when entering flow
+                    (it !is Data) || (it.version < latestVersionAtRead)
+                } else if (currentDownStreamFlowState is Final<T>) {
+                    // We don't need to drop Final values.
                     false
                 } else {
                     // we need to drop the last seen state since it was either an exception or
@@ -109,9 +115,7 @@
                     is Final<T> -> throw it.finalException
                     is Data<T> -> it.value
                     is UnInitialized -> error(
-                        "This is a bug in DataStore. Please file a bug at: " +
-                            "https://issuetracker.google.com/issues/new?" +
-                            "component=907884&template=1466542"
+                        BUG_MESSAGE
                     )
                 }
             }
@@ -119,33 +123,48 @@
     }
 
     override suspend fun updateData(transform: suspend (t: T) -> T): T {
-        /**
-         * The states here are the same as the states for reads. Additionally we send an ack that
-         * the actor *must* respond to (even if it is cancelled).
-         */
         val ack = CompletableDeferred<T>()
         val currentDownStreamFlowState = downstreamFlow.value
 
         val updateMsg =
             Message.Update(transform, ack, currentDownStreamFlowState, coroutineContext)
 
-        actor.offer(updateMsg)
+        writeActor.offer(updateMsg)
 
         return ack.await()
     }
 
     private val SCRATCH_SUFFIX = ".tmp"
+    private val LOCK_SUFFIX = ".lock"
+    private val VERSION_SUFFIX = ".version"
+    private val BUG_MESSAGE = "This is a bug in DataStore. Please file a bug at: " +
+        "https://issuetracker.google.com/issues/new?component=907884&template=1466542"
+    private val INVALID_VERSION = -1
+    private var initTasks: List<suspend (api: InitializerApi<T>) -> Unit>? =
+        initTasksList.toList()
+    private val sharedCounter: SharedCounter by lazy {
+        SharedCounter.loadLib()
+        // TODO(b/241471375): remove the enableMlock option here
+        SharedCounter.create(/* enableMlock = */ false) {
+            val versionFile = fileWithSuffix(VERSION_SUFFIX)
+            versionFile.createIfNotExists()
+            versionFile
+        }
+    }
+    private val threadLockSemaphore = Semaphore(1)
 
-    private val file: File by lazy {
+    // file is protected rather than private to avoid requiring synthetic accessor for its usage in
+    // the definition of FileObserver
+    protected val file: File by lazy {
         val file = produceFile()
 
         file.absolutePath.let {
             synchronized(activeFilesLock) {
                 check(!activeFiles.contains(it)) {
-                    "There are multiple DataStores active for the same file: $file. You should " +
-                        "either maintain your DataStore as a singleton or confirm that there is " +
-                        "no two DataStore's active on the same file (by confirming that the scope" +
-                        " is cancelled)."
+                    "There are multiple DataStores in the same process active for the same file: " +
+                        "$file. You should either maintain your DataStore as a singleton or " +
+                        "confirm that there is no two DataStore's active on the same file in the " +
+                        "same process(by confirming that the scope is cancelled)."
                 }
                 activeFiles.add(it)
             }
@@ -154,37 +173,29 @@
         file
     }
 
+    private val lockFile: File by lazy {
+        val lockFile = fileWithSuffix(LOCK_SUFFIX)
+        lockFile.createIfNotExists()
+        lockFile
+    }
+
+    private val fileObserver: FileObserver by lazy {
+        @Suppress("DEPRECATION")
+        object : FileObserver(file.canonicalFile.parent!!, FileObserver.MOVED_TO) {
+            // It will be triggered by same-process-write as well. Shared memory version check will
+            // prevent it from reading again. parameter `path` is relative to the observed directory
+            override fun onEvent(event: Int, path: String?) {
+                if ((downstreamFlow.value !is Final) && (path!! == file.name)) {
+                    readActor.offer(Message.Read(downstreamFlow.value))
+                }
+            }
+        }
+    }
+
     @Suppress("UNCHECKED_CAST")
     private val downstreamFlow = MutableStateFlow(UnInitialized as State<T>)
 
-    private var initTasks: List<suspend (api: InitializerApi<T>) -> Unit>? =
-        initTasksList.toList()
-
-    /** The actions for the actor. */
-    private sealed class Message<T> {
-        abstract val lastState: State<T>?
-
-        /**
-         * Represents a read operation. If the data is already cached, this is a no-op. If data
-         * has not been cached, it triggers a new read to the specified dataChannel.
-         */
-        class Read<T>(
-            override val lastState: State<T>?
-        ) : Message<T>()
-
-        /** Represents an update operation. */
-        class Update<T>(
-            val transform: suspend (t: T) -> T,
-            /**
-             * Used to signal (un)successful completion of the update to the caller.
-             */
-            val ack: CompletableDeferred<T>,
-            override val lastState: State<T>?,
-            val callerContext: CoroutineContext
-        ) : Message<T>()
-    }
-
-    private val actor = SimpleActor<Message<T>>(
+    private val writeActor = SimpleActor<Message.Update<T>>(
         scope = scope,
         onComplete = {
             it?.let {
@@ -198,32 +209,31 @@
             }
         },
         onUndeliveredElement = { msg, ex ->
-            if (msg is Message.Update) {
-                // TODO(rohitsat): should we instead use scope.ensureActive() to get the original
-                //  cancellation cause? Should we instead have something like
-                //  UndeliveredElementException?
-                msg.ack.completeExceptionally(
-                    ex ?: CancellationException(
-                        "DataStore scope was cancelled before updateData could complete"
-                    )
+            msg.ack.completeExceptionally(
+                ex ?: CancellationException(
+                    "DataStore scope was cancelled before updateData could complete"
                 )
-            }
+            )
         }
     ) { msg ->
-        when (msg) {
-            is Message.Read -> {
-                handleRead(msg)
-            }
-            is Message.Update -> {
-                handleUpdate(msg)
-            }
-        }
+        handleUpdate(msg)
+    }
+
+    private val readActor = SimpleActor<Message.Read<T>>(
+        scope = scope,
+        onComplete = {
+            // no more reads so stop listening to file changes
+            fileObserver.stopWatching()
+        },
+        onUndeliveredElement = { _, _ -> }
+    ) { msg ->
+        handleRead(msg)
     }
 
     private suspend fun handleRead(read: Message.Read<T>) {
         when (val currentState = downstreamFlow.value) {
             is Data -> {
-                // We already have data so just return...
+                readData()
             }
             is ReadException -> {
                 if (currentState === read.lastState) {
@@ -241,15 +251,13 @@
     }
 
     private suspend fun handleUpdate(update: Message.Update<T>) {
-        // All branches of this *must* complete ack either successfully or exceptionally.
-        // We must *not* throw an exception, just propagate it to the ack.
         update.ack.completeWith(
             runCatching {
-
+                var result: T
                 when (val currentState = downstreamFlow.value) {
                     is Data -> {
                         // We are already initialized, we just need to perform the update
-                        transformAndWrite(update.transform, update.callerContext)
+                        result = transformAndWrite(update.transform, update.callerContext)
                     }
                     is ReadException, is UnInitialized -> {
                         if (currentState === update.lastState) {
@@ -257,7 +265,7 @@
                             readAndInitOrPropagateAndThrowFailure()
 
                             // We've successfully read, now we need to perform the update
-                            transformAndWrite(update.transform, update.callerContext)
+                            result = transformAndWrite(update.transform, update.callerContext)
                         } else {
                             // Someone else beat us to read but also failed. We just need to
                             // signal the writer that is waiting on ack.
@@ -269,6 +277,7 @@
 
                     is Final -> throw currentState.finalException // won't happen
                 }
+                result
             }
         )
     }
@@ -290,55 +299,94 @@
         }
     }
 
+    // It handles the read when data needs to be initialized.
     private suspend fun readAndInit() {
-        // This should only be called if we don't already have cached data.
-        check(downstreamFlow.value == UnInitialized || downstreamFlow.value is ReadException)
+        initTaskLock.withLock() {
+            // This should only be called if we don't already have cached data.
+            if (downstreamFlow.value != UnInitialized && downstreamFlow.value !is ReadException) {
+                // downstreamFlow.value is Data or Final, no need to readAndInit. As there are two
+                // actors, we return here instead of throwing exception to properly handle the race
+                // condition where one actor call `readAndInit()` after the other has completed
+                // successfully.
+                return
+            }
 
-        val updateLock = Mutex()
-        var initData = readDataOrHandleCorruption()
+            var initData: Data<T>
+            if ((initTasks == null) || initTasks!!.isEmpty()) {
+                initData = readDataOrHandleCorruption(hasWriteFileLock = false)
+            } else {
+                initData = getWriteFileLock {
+                    val updateLock = Mutex()
+                    var initializationComplete: Boolean = false
+                    var currentData = readDataOrHandleCorruption(hasWriteFileLock = true).value
 
-        var initializationComplete: Boolean = false
+                    val api = object : InitializerApi<T> {
+                        override suspend fun updateData(transform: suspend (t: T) -> T): T {
+                            return updateLock.withLock() {
+                                check(!initializationComplete) {
+                                    "InitializerApi.updateData should not be called after " +
+                                        "initialization is complete."
+                                }
 
-        // TODO(b/151635324): Consider using Context Element to throw an error on re-entrance.
-        val api = object : InitializerApi<T> {
-            override suspend fun updateData(transform: suspend (t: T) -> T): T {
-                return updateLock.withLock() {
-                    if (initializationComplete) {
-                        throw IllegalStateException(
-                            "InitializerApi.updateData should not be " +
-                                "called after initialization is complete."
-                        )
+                                val newData = transform(currentData)
+                                if (newData != currentData) {
+                                    writeData(newData, updateCache = false)
+                                    currentData = newData
+                                }
+
+                                currentData
+                            }
+                        }
                     }
 
-                    val newData = transform(initData)
-                    if (newData != initData) {
-                        writeData(newData)
-                        initData = newData
+                    initTasks?.forEach { it(api) }
+                    // Init tasks have run successfully, we don't need them anymore.
+                    initTasks = null
+                    updateLock.withLock {
+                        initializationComplete = true
                     }
 
-                    initData
+                    // only to make compiler happy
+                    currentData
                 }
             }
+            downstreamFlow.value = initData
+            fileObserver.startWatching()
         }
-
-        initTasks?.forEach { it(api) }
-        initTasks = null // Init tasks have run successfully, we don't need them anymore.
-        updateLock.withLock {
-            initializationComplete = true
-        }
-
-        downstreamFlow.value = Data(initData, initData.hashCode(), /* unused */ version = 0)
     }
 
-    private suspend fun readDataOrHandleCorruption(): T {
+    // Only be called from `readAndInit`. State is UnInitialized or ReadException.
+    private suspend fun readDataOrHandleCorruption(hasWriteFileLock: Boolean): Data<T> {
         try {
-            return readData()
+            if (hasWriteFileLock) {
+                val data = readDataFromFileOrDefault()
+                return Data(data, data.hashCode(), version = sharedCounter.getValue())
+            } else {
+                return tryGetReadFileLock {
+                    val data = readDataFromFileOrDefault()
+                    val version = if (it) sharedCounter.getValue() else INVALID_VERSION
+                    Data(
+                        data,
+                        data.hashCode(),
+                        version
+                    )
+                }
+            }
         } catch (ex: CorruptionException) {
-
             val newData: T = corruptionHandler.handleCorruption(ex)
+            var version: Int = INVALID_VERSION // should be overridden if write successfully
 
             try {
-                writeData(newData)
+                // TODO(b/241286493): acquire the write lock and confirm the data is still corrupted
+                // before overwriting to avoid race condition
+                if (hasWriteFileLock) {
+                    version = writeData(newData)
+                } else {
+                    getWriteFileLock {
+                        version = writeData(newData)
+                        newData
+                    }
+                }
             } catch (writeEx: IOException) {
                 // If we fail to write the handled data, add the new exception as a suppressed
                 // exception.
@@ -347,14 +395,39 @@
             }
 
             // If we reach this point, we've successfully replaced the data on disk with newData.
-            return newData
+            return Data(newData, newData.hashCode(), version)
         }
     }
 
+    // It handles the read when the current state is Data
     private suspend fun readData(): T {
+        // Check if the cached version matches with shared memory counter
+        val currentState = downstreamFlow.value
+        val version = sharedCounter.getValue()
+        val cachedVersion = if (currentState is Data) currentState.version else INVALID_VERSION
+
+        // Return cached value if cached version is latest
+        if (currentState is Data && version == cachedVersion) {
+            return currentState.value
+        }
+        val data = tryGetReadFileLock {
+            val result = readDataFromFileOrDefault()
+            Data(
+                result,
+                result.hashCode(),
+                if (it) sharedCounter.getValue() else INVALID_VERSION
+            )
+        }
+        downstreamFlow.value = data
+        return data.value
+    }
+
+    // Caller is responsible for (try to) getting file lock. It reads from the file directly without
+    // checking shared counter version and returns serializer default value if file is not found.
+    private suspend fun readDataFromFileOrDefault(): T {
         try {
-            FileInputStream(file).use { stream ->
-                return serializer.readFrom(stream)
+            return FileInputStream(file).use { stream ->
+                serializer.readFrom(stream)
             }
         } catch (ex: FileNotFoundException) {
             if (file.exists()) {
@@ -364,36 +437,25 @@
         }
     }
 
-    // downstreamFlow.value must be successfully set to data before calling this
     private suspend fun transformAndWrite(
         transform: suspend (t: T) -> T,
         callerContext: CoroutineContext
-    ): T {
-        // value is not null or an exception because we must have the value set by now so this cast
-        // is safe.
-        val curDataAndHash = downstreamFlow.value as Data<T>
-        curDataAndHash.checkHashCode()
-
-        val curData = curDataAndHash.value
+    ): T = getWriteFileLock {
+        val curData = readDataFromFileOrDefault()
+        val curDataAndHash = Data(curData, curData.hashCode(), /* unused */ version = 0)
         val newData = withContext(callerContext) { transform(curData) }
 
         // Check that curData has not changed...
         curDataAndHash.checkHashCode()
 
-        return if (curData == newData) {
-            curData
-        } else {
+        if (curData != newData) {
             writeData(newData)
-            downstreamFlow.value = Data(newData, newData.hashCode(), /* unused */ version = 0)
-            newData
         }
-    }
+        newData
+    }.value
 
-    /**
-     * Internal only to prevent creation of synthetic accessor function. Do not call this from
-     * outside this class.
-     */
-    internal suspend fun writeData(newData: T) {
+    // Write data to disk and return the corresponding version if succeed.
+    internal suspend fun writeData(newData: T, updateCache: Boolean = true): Int {
         file.createParentDirectories()
 
         val scratchFile = File(file.absolutePath + SCRATCH_SUFFIX)
@@ -402,9 +464,11 @@
                 serializer.writeTo(newData, UncloseableOutputStream(stream))
                 stream.fd.sync()
                 // TODO(b/151635324): fsync the directory, otherwise a badly timed crash could
-                //  result in reverting to a previous state.
+                // result in reverting to a previous state.
             }
 
+            val newVersion = sharedCounter.incrementAndGetValue()
+
             if (!scratchFile.renameTo(file)) {
                 throw IOException(
                     "Unable to rename $scratchFile." +
@@ -413,6 +477,12 @@
                         "datastore for this file."
                 )
             }
+
+            if (updateCache) {
+                downstreamFlow.value = Data(newData, newData.hashCode(), newVersion)
+            }
+
+            return newVersion
         } catch (ex: IOException) {
             if (scratchFile.exists()) {
                 scratchFile.delete() // Swallow failure to delete
@@ -421,6 +491,17 @@
         }
     }
 
+    private fun fileWithSuffix(suffix: String): File {
+        return File(file.absolutePath + suffix)
+    }
+
+    private fun File.createIfNotExists() {
+        createParentDirectories()
+        if (!exists()) {
+            createNewFile()
+        }
+    }
+
     private fun File.createParentDirectories() {
         val parent: File? = canonicalFile.parentFile
 
@@ -432,6 +513,36 @@
         }
     }
 
+    private suspend fun getWriteFileLock(block: suspend () -> T): Data<T> {
+        // TODO(b/239970979): use kotlinx.coroutines.sync.Mutex instead of adhoc ThreadLock with
+        // semaphore to make the best use of coroutine
+        ThreadLock.acquire(threadLockSemaphore).use {
+            FileOutputStream(lockFile).use { lockFileStream ->
+                lockFileStream.getChannel().lock(0L, Long.MAX_VALUE, /* shared= */ false)
+                    .use { _ ->
+                        val data = block()
+                        return Data(data, data.hashCode(), sharedCounter.getValue())
+                    }
+            }
+        }
+    }
+
+    private suspend fun tryGetReadFileLock(
+        block: suspend (Boolean) -> Data<T>
+    ): Data<T> {
+        ThreadLock.tryAcquire(threadLockSemaphore).use {
+            if (it.acquired() == false) {
+                return block(false)
+            }
+            FileInputStream(lockFile).use { lockFileStream ->
+                lockFileStream.getChannel().tryLock(0L, Long.MAX_VALUE, /* shared= */ true)
+                    .use { lock ->
+                        return block(lock != null)
+                    }
+            }
+        }
+    }
+
     internal companion object {
         /**
          * Active files should contain the absolute path for which there are currently active
@@ -443,5 +554,7 @@
         internal val activeFiles = mutableSetOf<String>()
 
         internal val activeFilesLock = Any()
+
+        internal val initTaskLock = Mutex()
     }
 }
\ No newline at end of file
diff --git a/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/ThreadLock.kt b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/ThreadLock.kt
new file mode 100644
index 0000000..27ef8fa
--- /dev/null
+++ b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/ThreadLock.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.datastore.multiprocess
+
+import java.io.Closeable
+import java.io.InterruptedIOException
+import java.util.concurrent.Semaphore
+
+internal class ThreadLock(
+    private val semaphore: Semaphore?
+) : Closeable {
+    fun acquired(): Boolean {
+        return semaphore != null
+    }
+
+    override fun close() {
+        if (acquired()) {
+            semaphore!!.release()
+        }
+    }
+
+    internal companion object {
+        suspend fun tryAcquire(semaphore: Semaphore): ThreadLock {
+            val acquired = semaphore.tryAcquire()
+            return if (acquired) ThreadLock(semaphore) else ThreadLock(null)
+        }
+
+        suspend fun acquire(semaphore: Semaphore): ThreadLock {
+            try {
+                semaphore.acquire()
+            } catch (ex: InterruptedException) {
+                throw InterruptedIOException("semaphore not acquired: $ex")
+            }
+            return ThreadLock(semaphore)
+        }
+    }
+}
diff --git a/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/internal/Message.kt b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/internal/Message.kt
index b3ae931..0b8ff0c 100644
--- a/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/internal/Message.kt
+++ b/datastore/datastore-multiprocess/src/main/java/androidx/datastore/multiprocess/internal/Message.kt
@@ -28,8 +28,7 @@
      * has not been cached, it triggers a new read to the specified dataChannel.
      */
     class Read<T>(
-        override val lastState: State<T>?,
-        val isBlocking: Boolean = false
+        override val lastState: State<T>?
     ) : Message<T>()
 
     /** Represents an update operation. */
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
index ee2d264..c9cca26 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
@@ -33,10 +33,10 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.datastore.preferences.core.intPreferencesKey
-import androidx.glance.Button
 import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
 import androidx.glance.LocalContext
+import androidx.glance.action.Action
 import androidx.glance.action.ActionParameters
 import androidx.glance.action.actionParametersOf
 import androidx.glance.action.actionStartActivity
@@ -56,10 +56,13 @@
 import androidx.glance.currentState
 import androidx.glance.layout.Alignment
 import androidx.glance.layout.Column
+import androidx.glance.layout.ColumnScope
 import androidx.glance.layout.Row
+import androidx.glance.layout.Spacer
 import androidx.glance.layout.fillMaxSize
 import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
+import androidx.glance.layout.size
 import androidx.glance.text.FontWeight
 import androidx.glance.text.Text
 import androidx.glance.text.TextDecoration
@@ -129,7 +132,7 @@
 }
 
 @Composable
-private fun StartActivityActions() {
+private fun ColumnScope.StartActivityActions() {
     Button(
         text = "Intent",
         onClick = actionStartActivity(
@@ -161,12 +164,13 @@
             actionParametersOf(
                 StartMessageKey to "Start activity by component name"
             )
-        )
+        ),
+        withSpace = false
     )
 }
 
 @Composable
-private fun StartServiceActions() {
+private fun ColumnScope.StartServiceActions() {
     Button(
         text = "Intent",
         onClick = actionStartService(
@@ -185,12 +189,13 @@
         text = "Component name",
         onClick = actionStartService(
             ComponentName(LocalContext.current, ActionDemoService::class.java)
-        )
+        ),
+        withSpace = false
     )
 }
 
 @Composable
-private fun SendBroadcastActions() {
+private fun ColumnScope.SendBroadcastActions() {
     Button(
         text = "Intent",
         onClick = actionSendBroadcast(
@@ -211,11 +216,24 @@
         text = "Component name",
         onClick = actionSendBroadcast(
             ComponentName(LocalContext.current, ActionAppWidgetReceiver::class.java)
-        )
+        ),
+        withSpace = false
     )
 }
 
 /**
+ * Reimplementation of the [androidx.glance.Button] that adds a spacer after it.
+ */
+@Suppress("unused")
+@Composable
+private fun ColumnScope.Button(text: String, onClick: Action, withSpace: Boolean = true) {
+    androidx.glance.Button(text, onClick)
+    if (withSpace) {
+        Spacer(GlanceModifier.size(4.dp))
+    }
+}
+
+/**
  * Action to update the [SelectedItemKey] value whenever users clicks on text
  */
 class UpdateAction : ActionCallback {
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/DefaultStateAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/DefaultStateAppWidget.kt
index 854aadc..360c3de 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/DefaultStateAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/DefaultStateAppWidget.kt
@@ -50,6 +50,7 @@
             Button(
                 modifier = GlanceModifier.defaultWeight(),
                 text = "-",
+                style = TextStyle(textAlign = TextAlign.Center),
                 onClick = actionRunCallback<ClickAction>(
                     actionParametersOf(ClickValueKey to -1)
                 )
@@ -62,6 +63,7 @@
             Button(
                 modifier = GlanceModifier.defaultWeight(),
                 text = "+",
+                style = TextStyle(textAlign = TextAlign.Center),
                 onClick = actionRunCallback<ClickAction>(
                     actionParametersOf(ClickValueKey to 1)
                 )
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ImageAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ImageAppWidget.kt
index b27d911..f15b3d8 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ImageAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ImageAppWidget.kt
@@ -37,9 +37,11 @@
 import androidx.glance.currentState
 import androidx.glance.layout.Column
 import androidx.glance.layout.ContentScale
+import androidx.glance.layout.Spacer
 import androidx.glance.layout.fillMaxSize
 import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
+import androidx.glance.layout.size
 
 /**
  * Sample AppWidget that showcase the [ContentScale] options for [Image]
@@ -61,6 +63,7 @@
                 modifier = GlanceModifier.fillMaxWidth(),
                 onClick = actionRunCallback<ChangeImageAction>()
             )
+            Spacer(GlanceModifier.size(4.dp))
             Image(
                 provider = ImageProvider(R.drawable.compose),
                 contentDescription = "Content Scale image sample (value: $type)",
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ResponsiveAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ResponsiveAppWidget.kt
index 2854922..a801ca0 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ResponsiveAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ResponsiveAppWidget.kt
@@ -24,6 +24,7 @@
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
 import androidx.glance.Button
+import androidx.glance.ButtonColors
 import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
 import androidx.glance.LocalSize
@@ -44,6 +45,7 @@
 import androidx.glance.layout.size
 import androidx.glance.text.TextAlign
 import androidx.glance.text.TextStyle
+import androidx.glance.unit.ColorProvider
 
 /**
  * Sample AppWidget that showcase the Responsive SizeMode changing its content to Row, Column or Box
@@ -152,6 +154,10 @@
         Button(
             text = text,
             modifier = GlanceModifier.fillMaxSize().padding(8.dp).background(color),
+            colors = ButtonColors(
+                backgroundColor = ColorProvider(color),
+                contentColor = ColorProvider(Color.White)
+            ),
             style = textStyle ?: TextStyle(textAlign = TextAlign.Center),
             onClick = actionRunCallback<ResponsiveAction>(
                 actionParametersOf(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index df01294..9dec36d 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -44,7 +44,7 @@
 protobuf = "3.19.4"
 skiko = "0.7.7"
 sqldelight = "1.3.0"
-wire = "3.6.0"
+wire = "4.4.1"
 
 [libraries]
 androidAccessibilityFramework = { module = "com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework", version = { strictly = "2.1" } }
@@ -58,6 +58,7 @@
 androidLintChecks = { module = "com.android.tools.lint:lint-checks", version.ref = "androidLint" }
 androidLintChecksMin = { module = "com.android.tools.lint:lint-checks", version.ref = "androidLintMin" }
 androidLintTests = { module = "com.android.tools.lint:lint-tests", version.ref = "androidLint" }
+androidToolsCommon = { module = "com.android.tools:common", version.ref = "androidLint" }
 autoCommon = { module = "com.google.auto:auto-common", version = "0.11" }
 atomicFu = { module = "org.jetbrains.kotlinx:atomicfu", version.ref = "atomicFu" }
 atomicFuPluginz = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "atomicFu" }
@@ -67,7 +68,9 @@
 autoValueAnnotations = { module = "com.google.auto.value:auto-value-annotations", version.ref = "autoValue" }
 autoValueParcel = { module = "com.ryanharter.auto.value:auto-value-parcel", version = "0.2.6" }
 antlr4 = { module = "org.antlr:antlr4", version = "4.7.1" }
+apacheAnt = { module = "org.apache.ant:ant", version = "1.10.11" }
 apacheCommonsCodec = { module = "commons-codec:commons-codec", version = "1.15" }
+apacheCommonIo = { module = "commons-io:commons-io", version = "2.4" }
 assertj = { module = "org.assertj:assertj-core", version = "3.11.1" }
 checkerframework = { module = "org.checkerframework:checker-qual", version = "2.5.3" }
 checkmark = { module = "net.saff.checkmark:checkmark", version = "0.1.2" }
@@ -96,6 +99,7 @@
 hiltCore = { module = "com.google.dagger:hilt-core", version.ref = "hilt" }
 intellijAnnotations = { module = "com.intellij:annotations", version = "12.0" }
 javapoet = { module = "com.squareup:javapoet", version = "1.13.0" }
+json = { module = "org.json:json", version = "20180813" }
 jsonSimple = { module = "com.googlecode.json-simple:json-simple", version = "1.1" }
 jsqlparser = { module = "com.github.jsqlparser:jsqlparser", version = "3.1" }
 jsr250 = { module = "javax.annotation:javax.annotation-api", version = "1.2" }
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index e28fe80..51bedde 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -419,7 +419,10 @@
          <trusted-key id="d790f72ea8fd39551012b62dcf9f3090ce4cb752" group="org.abego.treelayout" name="org.abego.treelayout.core"/>
          <trusted-key id="da7a1bb85b19e4fb05073431205c8673dc742c7c" group="org.apache.maven"/>
          <trusted-key id="db0597e3144342256bc81e3ec727d053c4481cf5" group="org.tensorflow"/>
-         <trusted-key id="dbd744ace7ade6aa50dd591f66b50994442d2d40" group="com.squareup.okio"/>
+         <trusted-key id="dbd744ace7ade6aa50dd591f66b50994442d2d40">
+            <trusting group="com.squareup.okio"/>
+            <trusting group="com.squareup.wire"/>
+         </trusted-key>
          <trusted-key id="dddafa7674e54418" group="org.testng"/>
          <trusted-key id="e0130a3ed5a2079e" group="org.webjars"/>
          <trusted-key id="e0cb7823cfd00fbf" group="com.jakewharton.android.repackaged"/>
diff --git a/mediarouter/mediarouter/src/main/res/values-zh-rCN/strings.xml b/mediarouter/mediarouter/src/main/res/values-zh-rCN/strings.xml
index 0ba8e06..bae9baf 100644
--- a/mediarouter/mediarouter/src/main/res/values-zh-rCN/strings.xml
+++ b/mediarouter/mediarouter/src/main/res/values-zh-rCN/strings.xml
@@ -18,14 +18,14 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="7449553026175453403">"系统"</string>
     <string name="mr_user_route_category_name" msgid="4088331695424166162">"设备"</string>
-    <string name="mr_button_content_description" msgid="2939063992730535343">"投射"</string>
-    <string name="mr_cast_button_disconnected" msgid="8071109333469380363">"投射。已断开连接"</string>
-    <string name="mr_cast_button_connecting" msgid="6629927151350192407">"投射。正在连接"</string>
-    <string name="mr_cast_button_connected" msgid="6073720094880410356">"投射。已连接"</string>
-    <string name="mr_chooser_title" msgid="1419936397646839840">"投射到"</string>
+    <string name="mr_button_content_description" msgid="2939063992730535343">"投放"</string>
+    <string name="mr_cast_button_disconnected" msgid="8071109333469380363">"投放。已断开连接"</string>
+    <string name="mr_cast_button_connecting" msgid="6629927151350192407">"投放。正在连接"</string>
+    <string name="mr_cast_button_connected" msgid="6073720094880410356">"投放。已连接"</string>
+    <string name="mr_chooser_title" msgid="1419936397646839840">"投放到"</string>
     <string name="mr_chooser_searching" msgid="6114250663023140921">"正在查找设备"</string>
     <string name="mr_controller_disconnect" msgid="7812275474138309497">"断开连接"</string>
-    <string name="mr_controller_stop_casting" msgid="804210341192624074">"停止投射"</string>
+    <string name="mr_controller_stop_casting" msgid="804210341192624074">"停止投放"</string>
     <string name="mr_controller_close_description" msgid="5684434439232634509">"关闭"</string>
     <string name="mr_controller_play" msgid="1253345086594430054">"播放"</string>
     <string name="mr_controller_pause" msgid="747801650871398383">"暂停"</string>
@@ -36,7 +36,7 @@
     <string name="mr_controller_volume_slider" msgid="2955862765169128170">"音量滑块"</string>
     <string name="mr_controller_no_media_selected" msgid="5495452265246139458">"未选择任何媒体内容"</string>
     <string name="mr_controller_no_info_available" msgid="855271725131981086">"没有任何相关信息"</string>
-    <string name="mr_controller_casting_screen" msgid="9171231064758955152">"正在投射屏幕"</string>
+    <string name="mr_controller_casting_screen" msgid="9171231064758955152">"正在投放屏幕"</string>
     <string name="mr_dialog_default_group_name" msgid="4115858704575247342">"群组"</string>
     <string name="mr_dialog_groupable_header" msgid="4307018456678388936">"添加设备"</string>
     <string name="mr_dialog_transferable_header" msgid="6068257520605505468">"在一组设备上播放"</string>
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/res/values-fa/strings.xml b/navigation/navigation-dynamic-features-fragment/src/main/res/values-fa/strings.xml
index 4f43a5e..f4be2eb 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/res/values-fa/strings.xml
+++ b/navigation/navigation-dynamic-features-fragment/src/main/res/values-fa/strings.xml
@@ -21,6 +21,6 @@
     <string name="installation_cancelled" msgid="475402237100444685">"نصب لغو شد."</string>
     <string name="installing_module" msgid="5968445461040787716">"مدول نصب:"</string>
     <string name="progress" msgid="8366783942222789124">"پیشرفت:"</string>
-    <string name="retry" msgid="1065327189183624288">"سعی مجدد"</string>
+    <string name="retry" msgid="1065327189183624288">"مجدد امتحان کردن"</string>
     <string name="ok" msgid="4702104660890557116">"تأیید"</string>
 </resources>
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Tests.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Tests.java
index a25c616..ef94ee4 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Tests.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Tests.java
@@ -158,7 +158,7 @@
     @Test
     @SdkSuppress(minSdkVersion = 24)
     public void testDrag_dest() {
-        launchTestActivity(UiObject2TestDragActivity.class);
+        launchTestActivity(DragTestActivity.class);
 
         UiObject2 dragButton = mDevice.findObject(By.res(TEST_APP, "drag_button"));
         UiObject2 dragDestination = mDevice.findObject(By.res(TEST_APP, "drag_destination"));
@@ -172,7 +172,7 @@
     @Test
     @SdkSuppress(minSdkVersion = 24)
     public void testDrag_destAndSpeed() {
-        launchTestActivity(UiObject2TestDragActivity.class);
+        launchTestActivity(DragTestActivity.class);
 
         UiObject2 dragButton = mDevice.findObject(By.res(TEST_APP, "drag_button"));
         UiObject2 dragDestination = mDevice.findObject(By.res(TEST_APP, "drag_destination"));
@@ -186,7 +186,7 @@
     @Test
     @SdkSuppress(minSdkVersion = 24)
     public void testDrag_destAndSpeed_throwsIllegalArgumentException() {
-        launchTestActivity(UiObject2TestDragActivity.class);
+        launchTestActivity(DragTestActivity.class);
 
         UiObject2 dragButton = mDevice.findObject(By.res(TEST_APP, "drag_button"));
         UiObject2 dragDestination = mDevice.findObject(By.res(TEST_APP, "drag_destination"));
@@ -557,7 +557,7 @@
 
     @Test
     public void testSwipe() {
-        launchTestActivity(UiObject2TestSwipeActivity.class);
+        launchTestActivity(SwipeTestActivity.class);
 
         UiObject2 swipeRegion = mDevice.findObject(By.res(TEST_APP, "swipe_region"));
         swipeRegion.setGestureMargin(SCROLL_MARGIN);
@@ -577,7 +577,7 @@
 
     @Test
     public void testSwipe_throwsIllegalArgumentException() {
-        launchTestActivity(UiObject2TestSwipeActivity.class);
+        launchTestActivity(SwipeTestActivity.class);
 
         UiObject2 swipeRegion = mDevice.findObject(By.res(TEST_APP, "swipe_region"));
 
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 d1ce15d..5301a70 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
@@ -21,6 +21,9 @@
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
+import android.graphics.Rect;
+
+import androidx.test.filters.SdkSuppress;
 import androidx.test.uiautomator.UiObject;
 import androidx.test.uiautomator.UiObjectNotFoundException;
 import androidx.test.uiautomator.UiSelector;
@@ -28,6 +31,7 @@
 import org.junit.Test;
 
 public class UiObjectTest extends BaseTest {
+    private static final int TIMEOUT_MS = 10_000;
 
     @Test
     public void testGetChild() throws Exception {
@@ -74,20 +78,94 @@
                 noNode::getChildCount);
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    public void testDragTo_destObjAndSteps() throws Exception {
+        launchTestActivity(DragTestActivity.class);
+
+        UiObject dragButton = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_button"));
+        UiObject dragDestination = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_destination"));
+        UiObject expectedDragDest = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_destination").text("drag_received"));
+
+        assertEquals("no_drag_yet", dragDestination.getText());
+        // Returning true from `dragTo` means that the drag action is performed successfully, not
+        // necessarily the target is dragged to the desired destination.
+        // The same applies to all the following tests.
+        assertTrue(dragButton.dragTo(dragDestination, 40));
+        assertTrue(expectedDragDest.waitForExists(TIMEOUT_MS));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    public void testDragTo_destXAndDestYAndSteps() throws Exception {
+        launchTestActivity(DragTestActivity.class);
+
+        UiObject dragButton = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_button"));
+        UiObject dragDestination = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_destination"));
+        UiObject expectedDragDest = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/drag_destination").text("drag_received"));
+        Rect destBounds = dragDestination.getVisibleBounds();
+
+        assertEquals("no_drag_yet", dragDestination.getText());
+        assertTrue(dragButton.dragTo(destBounds.centerX(), destBounds.centerY(), 40));
+        assertTrue(expectedDragDest.waitForExists(TIMEOUT_MS));
+    }
+
+    @Test
+    public void testSwipeUp() throws Exception {
+        launchTestActivity(SwipeTestActivity.class);
+
+        UiObject swipeRegion = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/swipe_region"));
+
+        assertEquals("no_swipe", swipeRegion.getText());
+        assertTrue(swipeRegion.swipeUp(100));
+        assertEquals("swipe_up", swipeRegion.getText());
+    }
+
+    @Test
+    public void testSwipeDown() throws Exception {
+        launchTestActivity(SwipeTestActivity.class);
+
+        UiObject swipeRegion = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/swipe_region"));
+
+        assertEquals("no_swipe", swipeRegion.getText());
+        assertTrue(swipeRegion.swipeDown(100));
+        assertEquals("swipe_down", swipeRegion.getText());
+    }
+
+    @Test
+    public void testSwipeLeft() throws Exception {
+        launchTestActivity(SwipeTestActivity.class);
+
+        UiObject swipeRegion = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/swipe_region"));
+
+        assertEquals("no_swipe", swipeRegion.getText());
+        assertTrue(swipeRegion.swipeLeft(100));
+        assertEquals("swipe_left", swipeRegion.getText());
+    }
+
+    @Test
+    public void testSwipeRight() throws Exception {
+        launchTestActivity(SwipeTestActivity.class);
+
+        UiObject swipeRegion = mDevice.findObject(new UiSelector().resourceId(TEST_APP + ":id"
+                + "/swipe_region"));
+
+        assertEquals("no_swipe", swipeRegion.getText());
+        assertTrue(swipeRegion.swipeRight(100));
+        assertEquals("swipe_right", swipeRegion.getText());
+    }
+
     /* TODO(b/241158642): Implement these tests, and the tests for exceptions of each tested method.
 
-    public void testDragTo_destObjAndSteps() {}
-
-    public void testDragTo_destXAndDestYAndSteps() {}
-
-    public void testSwipeUp() {}
-
-    public void testSwipeDown() {}
-
-    public void testSwipeLeft() {}
-
-    public void testSwipeRight() {}
-
     public void testClick() {}
 
     public void testClickAndWaitForNewWindow() {}
diff --git a/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml b/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
index 59e6900..99fd1c1 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -41,6 +41,13 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
+        <activity android:name=".DragTestActivity"
+            android:exported="true"
+            android:theme="@android:style/Theme.Holo.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
         <activity android:name=".ParentChildTestActivity"
             android:exported="true"
             android:theme="@android:style/Theme.Holo.NoActionBar">
@@ -65,6 +72,13 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
+        <activity android:name=".SwipeTestActivity"
+            android:exported="true"
+            android:theme="@android:style/Theme.Holo.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
         <activity android:name=".UiDeviceTestClickActivity"
             android:exported="true"
             android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
@@ -94,13 +108,6 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
-        <activity android:name=".UiObject2TestDragActivity"
-            android:exported="true"
-            android:theme="@android:style/Theme.Holo.NoActionBar">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
         <activity android:name=".UiObject2TestFlingActivity"
             android:exported="true"
             android:theme="@android:style/Theme.Holo.NoActionBar">
@@ -157,13 +164,6 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
-        <activity android:name=".UiObject2TestSwipeActivity"
-            android:exported="true"
-            android:theme="@android:style/Theme.Holo.NoActionBar">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
         <activity android:name=".UiObject2TestVerticalScrollActivity"
             android:exported="true"
             android:theme="@android:style/Theme.Holo.NoActionBar">
diff --git a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestDragActivity.java b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/DragTestActivity.java
similarity index 86%
rename from test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestDragActivity.java
rename to test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/DragTestActivity.java
index be56bfd..5db41de 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestDragActivity.java
+++ b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/DragTestActivity.java
@@ -29,16 +29,16 @@
 import androidx.annotation.RequiresApi;
 
 @RequiresApi(24)
-public class UiObject2TestDragActivity extends Activity {
+public class DragTestActivity extends Activity {
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        setContentView(R.layout.uiobject2_testdrag_activity);
+        setContentView(R.layout.drag_test_activity);
 
-        Button dragButton = (Button) findViewById(R.id.drag_button);
-        TextView dragDestination = (TextView) findViewById(R.id.drag_destination);
+        Button dragButton = findViewById(R.id.drag_button);
+        TextView dragDestination = findViewById(R.id.drag_destination);
 
         dragButton.setOnLongClickListener(v -> {
             v.startDragAndDrop(ClipData.newPlainText(null, null),
diff --git a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestSwipeActivity.java b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/SwipeTestActivity.java
similarity index 93%
rename from test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestSwipeActivity.java
rename to test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/SwipeTestActivity.java
index ed36e65..fda840d 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/UiObject2TestSwipeActivity.java
+++ b/test/uiautomator/integration-tests/testapp/src/main/java/androidx/test/uiautomator/testapp/SwipeTestActivity.java
@@ -24,7 +24,7 @@
 
 import androidx.annotation.Nullable;
 
-public class UiObject2TestSwipeActivity extends Activity {
+public class SwipeTestActivity extends Activity {
 
     private GestureDetector mGestureDetector;
 
@@ -32,7 +32,7 @@
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        setContentView(R.layout.uiobject2_testswipe_activity);
+        setContentView(R.layout.swipe_test_activity);
 
         TextView swipeRegion = findViewById(R.id.swipe_region);
 
diff --git a/test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testdrag_activity.xml b/test/uiautomator/integration-tests/testapp/src/main/res/layout/drag_test_activity.xml
similarity index 92%
rename from test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testdrag_activity.xml
rename to test/uiautomator/integration-tests/testapp/src/main/res/layout/drag_test_activity.xml
index aa9e570..47890f3 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testdrag_activity.xml
+++ b/test/uiautomator/integration-tests/testapp/src/main/res/layout/drag_test_activity.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?><!--
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 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.
@@ -18,7 +18,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    tools:context=".UiObject2TestDragActivity">
+    tools:context=".DragTestActivity">
 
     <Button
         android:id="@+id/drag_button"
diff --git a/test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testswipe_activity.xml b/test/uiautomator/integration-tests/testapp/src/main/res/layout/swipe_test_activity.xml
similarity index 89%
rename from test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testswipe_activity.xml
rename to test/uiautomator/integration-tests/testapp/src/main/res/layout/swipe_test_activity.xml
index 9da8334..c9936e2 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/res/layout/uiobject2_testswipe_activity.xml
+++ b/test/uiautomator/integration-tests/testapp/src/main/res/layout/swipe_test_activity.xml
@@ -18,12 +18,14 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    tools:context=".UiObject2TestSwipeActivity">
+    tools:context=".SwipeTestActivity">
 
     <TextView
         android:id="@+id/swipe_region"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:layout_margin="30dp"
+        android:background="@android:color/white"
         android:gravity="center"
         android:text="no_swipe" />
 
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt b/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt
deleted file mode 100644
index 53c9775..0000000
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt
+++ /dev/null
@@ -1,364 +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.tv.compose.foundation.lazy.list
-
-import android.R.id.accessibilityActionScrollDown
-import android.R.id.accessibilityActionScrollLeft
-import android.R.id.accessibilityActionScrollRight
-import android.R.id.accessibilityActionScrollUp
-import android.view.View
-import android.view.accessibility.AccessibilityNodeProvider
-import androidx.activity.ComponentActivity
-import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.foundation.text.BasicText
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.semantics.SemanticsNode
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.assertIsDisplayed
-import androidx.compose.ui.test.junit4.createAndroidComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.onNodeWithText
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import androidx.core.view.ViewCompat
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD
-import androidx.test.filters.MediumTest
-import androidx.tv.foundation.PivotOffsets
-import com.google.common.truth.IterableSubject
-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
-
-@MediumTest
-@RunWith(Parameterized::class)
-class LazyScrollAccessibilityTest(private val config: TestConfig) {
-    data class TestConfig(
-        val horizontal: Boolean,
-        val rtl: Boolean,
-        val reversed: Boolean
-    ) {
-        val vertical = !horizontal
-
-        override fun toString(): String {
-            return (if (horizontal) "horizontal" else "vertical") +
-                (if (rtl) ",rtl" else ",ltr") +
-                (if (reversed) ",reversed" else "")
-        }
-    }
-
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun params() =
-            listOf(true, false).flatMap { horizontal ->
-                listOf(false, true).flatMap { rtl ->
-                    listOf(false, true).map { reversed ->
-                        TestConfig(horizontal, rtl, reversed)
-                    }
-                }
-            }
-    }
-
-    @get:Rule
-    val rule = createAndroidComposeRule<ComponentActivity>()
-
-    private val scrollerTag = "ScrollerTest"
-    private var composeView: View? = null
-    private val accessibilityNodeProvider: AccessibilityNodeProvider
-        get() = checkNotNull(composeView) {
-            "composeView not initialized. Did `composeView = LocalView.current` not work?"
-        }.let { composeView ->
-            ViewCompat
-                .getAccessibilityDelegate(composeView)!!
-                .getAccessibilityNodeProvider(composeView)!!
-                .provider as AccessibilityNodeProvider
-        }
-
-    @Test
-    fun scrollForward() {
-        testRelativeDirection(58, ACTION_SCROLL_FORWARD)
-    }
-
-    @Test
-    fun scrollBackward() {
-        testRelativeDirection(41, ACTION_SCROLL_BACKWARD)
-    }
-
-    @Test
-    fun scrollRight() {
-        testAbsoluteDirection(58, accessibilityActionScrollRight, config.horizontal)
-    }
-
-    @Test
-    fun scrollLeft() {
-        testAbsoluteDirection(41, accessibilityActionScrollLeft, config.horizontal)
-    }
-
-    @Test
-    fun scrollDown() {
-        testAbsoluteDirection(58, accessibilityActionScrollDown, config.vertical)
-    }
-
-    @Test
-    fun scrollUp() {
-        testAbsoluteDirection(41, accessibilityActionScrollUp, config.vertical)
-    }
-
-    @Test
-    fun verifyScrollActionsAtStart() {
-        createScrollableContent_StartAtStart()
-        verifyNodeInfoScrollActions(
-            expectForward = !config.reversed,
-            expectBackward = config.reversed
-        )
-    }
-
-    @Test
-    fun verifyScrollActionsInMiddle() {
-        createScrollableContent_StartInMiddle()
-        verifyNodeInfoScrollActions(
-            expectForward = true,
-            expectBackward = true
-        )
-    }
-
-    @Test
-    fun verifyScrollActionsAtEnd() {
-        createScrollableContent_StartAtEnd()
-        verifyNodeInfoScrollActions(
-            expectForward = config.reversed,
-            expectBackward = !config.reversed
-        )
-    }
-
-    /**
-     * Setup the test, run the given [accessibilityAction], and check if the [canonicalTarget]
-     * has been reached. The canonical target is the item that we expect to see when moving
-     * forward in a non-reversed scrollable (e.g. down in LazyColumn or right in LazyRow in LTR).
-     * The actual target is either the canonical target or the target that is as far from the
-     * middle of the lazy list as the canonical target, but on the other side of the middle,
-     * depending on the [configuration][config].
-     */
-    private fun testRelativeDirection(canonicalTarget: Int, accessibilityAction: Int) {
-        val target = if (!config.reversed) canonicalTarget else 100 - canonicalTarget - 1
-        testScrollAction(target, accessibilityAction)
-    }
-
-    /**
-     * Setup the test, run the given [accessibilityAction], and check if the [canonicalTarget]
-     * has been reached (but only if we [expect][expectActionSuccess] the action to succeed).
-     * The canonical target is the item that we expect to see when moving forward in a
-     * non-reversed scrollable (e.g. down in LazyColumn or right in LazyRow in LTR). The actual
-     * target is either the canonical target or the target that is as far from the middle of the
-     * scrollable as the canonical target, but on the other side of the middle, depending on the
-     * [configuration][config].
-     */
-    private fun testAbsoluteDirection(
-        canonicalTarget: Int,
-        accessibilityAction: Int,
-        expectActionSuccess: Boolean
-    ) {
-        var target = canonicalTarget
-        if (config.horizontal && config.rtl) {
-            target = 100 - target - 1
-        }
-        if (config.reversed) {
-            target = 100 - target - 1
-        }
-        testScrollAction(target, accessibilityAction, expectActionSuccess)
-    }
-
-    /**
-     * Setup the test, run the given [accessibilityAction], and check if the [target] has been
-     * reached (but only if we [expect][expectActionSuccess] the action to succeed).
-     */
-    private fun testScrollAction(
-        target: Int,
-        accessibilityAction: Int,
-        expectActionSuccess: Boolean = true
-    ) {
-        createScrollableContent_StartInMiddle()
-        rule.onNodeWithText("$target").assertDoesNotExist()
-
-        val returnValue = rule.onNodeWithTag(scrollerTag).withSemanticsNode {
-            accessibilityNodeProvider.performAction(id, accessibilityAction, null)
-        }
-
-        assertThat(returnValue).isEqualTo(expectActionSuccess)
-        if (expectActionSuccess) {
-            rule.onNodeWithText("$target").assertIsDisplayed()
-        } else {
-            rule.onNodeWithText("$target").assertDoesNotExist()
-        }
-    }
-
-    /**
-     * Checks if all of the scroll actions are present or not according to what we expect based on
-     * [expectForward] and [expectBackward]. The scroll actions that are checked are forward,
-     * backward, left, right, up and down. The expectation parameters must already account for
-     * [reversing][TestConfig.reversed].
-     */
-    private fun verifyNodeInfoScrollActions(expectForward: Boolean, expectBackward: Boolean) {
-        val nodeInfo = rule.onNodeWithTag(scrollerTag).withSemanticsNode {
-            rule.runOnUiThread {
-                accessibilityNodeProvider.createAccessibilityNodeInfo(id)
-            }
-        }
-
-        val actions = nodeInfo.actionList.map { it.id }
-
-        assertThat(actions).contains(expectForward, ACTION_SCROLL_FORWARD)
-        assertThat(actions).contains(expectBackward, ACTION_SCROLL_BACKWARD)
-
-        if (config.horizontal) {
-            val expectLeft = if (config.rtl) expectForward else expectBackward
-            val expectRight = if (config.rtl) expectBackward else expectForward
-            assertThat(actions).contains(expectLeft, accessibilityActionScrollLeft)
-            assertThat(actions).contains(expectRight, accessibilityActionScrollRight)
-            assertThat(actions).contains(false, accessibilityActionScrollDown)
-            assertThat(actions).contains(false, accessibilityActionScrollUp)
-        } else {
-            assertThat(actions).contains(false, accessibilityActionScrollLeft)
-            assertThat(actions).contains(false, accessibilityActionScrollRight)
-            assertThat(actions).contains(expectForward, accessibilityActionScrollDown)
-            assertThat(actions).contains(expectBackward, accessibilityActionScrollUp)
-        }
-    }
-
-    private fun IterableSubject.contains(expectPresent: Boolean, element: Any) {
-        if (expectPresent) {
-            contains(element)
-        } else {
-            doesNotContain(element)
-        }
-    }
-
-    /**
-     * Creates a Row/Column that starts at the first item, according to [createScrollableContent]
-     */
-    private fun createScrollableContent_StartAtStart() {
-        createScrollableContent {
-            // Start at the start:
-            // -> pretty basic
-            rememberLazyListState(0, 0)
-        }
-    }
-
-    /**
-     * Creates a Row/Column that starts in the middle, according to [createScrollableContent]
-     */
-    private fun createScrollableContent_StartInMiddle() {
-        createScrollableContent {
-            // Start at the middle:
-            // Content size: 100 items * 21dp per item = 2100dp
-            // Viewport size: 200dp rect - 50dp padding on both sides = 100dp
-            // Content outside viewport: 2100dp - 100dp = 2000dp
-            // -> centered when 1000dp on either side, which is 47 items + 13dp
-            rememberLazyListState(
-                47,
-                with(LocalDensity.current) { 13.dp.roundToPx() }
-            )
-        }
-    }
-
-    /**
-     * Creates a Row/Column that starts at the last item, according to [createScrollableContent]
-     */
-    private fun createScrollableContent_StartAtEnd() {
-        createScrollableContent {
-            // Start at the end:
-            // Content size: 100 items * 21dp per item = 2100dp
-            // Viewport size: 200dp rect - 50dp padding on both sides = 100dp
-            // Content outside viewport: 2100dp - 100dp = 2000dp
-            // -> at the end when offset at 2000dp, which is 95 items + 5dp
-            rememberLazyListState(
-                95,
-                with(LocalDensity.current) { 5.dp.roundToPx() }
-            )
-        }
-    }
-
-    /**
-     * Creates a Row/Column with a viewport of 100.dp, containing 100 items each 17.dp in size.
-     * The items have a text with their index (ASC), and where the viewport starts is determined
-     * by the given [lambda][rememberLazyListState]. All properties from [config] are applied.
-     * The viewport has padding around it to make sure scroll distance doesn't include padding.
-     */
-    private fun createScrollableContent(rememberLazyListState: @Composable () -> TvLazyListState) {
-        rule.setContent {
-            composeView = LocalView.current
-            val lazyContent: TvLazyListScope.() -> Unit = {
-                items(100) {
-                    Box(Modifier.requiredSize(21.dp).background(Color.Yellow)) {
-                        BasicText("$it", Modifier.align(Alignment.Center))
-                    }
-                }
-            }
-
-            val state = rememberLazyListState()
-
-            Box(Modifier.requiredSize(200.dp).background(Color.White)) {
-                val direction = if (config.rtl) LayoutDirection.Rtl else LayoutDirection.Ltr
-                CompositionLocalProvider(LocalLayoutDirection provides direction) {
-                    if (config.horizontal) {
-                        TvLazyRow(
-                            Modifier.testTag(scrollerTag).matchParentSize(),
-                            state = state,
-                            contentPadding = PaddingValues(50.dp),
-                            reverseLayout = config.reversed,
-                            verticalAlignment = Alignment.CenterVertically,
-                            pivotOffsets =
-                            PivotOffsets(parentFraction = 0f)
-                        ) {
-                            lazyContent()
-                        }
-                    } else {
-                        TvLazyColumn(
-                            Modifier.testTag(scrollerTag).matchParentSize(),
-                            state = state,
-                            contentPadding = PaddingValues(50.dp),
-                            reverseLayout = config.reversed,
-                            horizontalAlignment = Alignment.CenterHorizontally,
-                            pivotOffsets =
-                            PivotOffsets(parentFraction = 0f)
-                        ) {
-                            lazyContent()
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private fun <T> SemanticsNodeInteraction.withSemanticsNode(block: SemanticsNode.() -> T): T {
-        return block.invoke(fetchSemanticsNode())
-    }
-}
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/AutoTestFrameClock.kt
similarity index 95%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/AutoTestFrameClock.kt
index 19e2105..ced2983 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/AutoTestFrameClock.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/AutoTestFrameClock.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy
+package androidx.tv.foundation.lazy
 
 import androidx.compose.runtime.MonotonicFrameClock
 import java.util.concurrent.atomic.AtomicLong
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt
index 5bf00b4..8c90559 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/BaseLazyGridTestWithOrientation.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.animation.core.snap
 import androidx.compose.foundation.gestures.Orientation
@@ -167,7 +167,7 @@
     fun LazyGrid(
         cells: Int,
         modifier: Modifier = Modifier,
-        state: TvLazyGridState = rememberLazyGridState(),
+        state: TvLazyGridState = rememberTvLazyGridState(),
         contentPadding: PaddingValues = PaddingValues(0.dp),
         reverseLayout: Boolean = false,
         userScrollEnabled: Boolean = true,
@@ -190,7 +190,7 @@
     fun LazyGrid(
         cells: TvGridCells,
         modifier: Modifier = Modifier,
-        state: TvLazyGridState = rememberLazyGridState(),
+        state: TvLazyGridState = rememberTvLazyGridState(),
         contentPadding: PaddingValues = PaddingValues(0.dp),
         reverseLayout: Boolean = false,
         userScrollEnabled: Boolean = true,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyArrangementsTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyArrangementsTest.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyArrangementsTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyArrangementsTest.kt
index 0ed6481..106d662 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyArrangementsTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyArrangementsTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.gestures.scrollBy
@@ -305,7 +305,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyVerticalGrid(
                 modifier = Modifier.size(itemSize * 3),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 verticalArrangement = Arrangement.spacedBy(spacingSize),
                 columns = TvGridCells.Fixed(1)
             ) {
@@ -342,7 +342,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyVerticalGrid(
                 modifier = Modifier.size(itemSize * 3),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 verticalArrangement = Arrangement.spacedBy(spacingSize),
                 columns = TvGridCells.Fixed(1)
             ) {
@@ -381,7 +381,7 @@
             TvLazyHorizontalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.size(itemSize * 3),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 horizontalArrangement = Arrangement.spacedBy(spacingSize)
             ) {
                 items(5) {
@@ -418,7 +418,7 @@
             TvLazyHorizontalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.size(itemSize * 3),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 horizontalArrangement = Arrangement.spacedBy(spacingSize)
             ) {
                 items(5) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyCustomKeysTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyCustomKeysTest.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyCustomKeysTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyCustomKeysTest.kt
index 0f444fa..55a2fe3 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyCustomKeysTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyCustomKeysTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
@@ -257,7 +257,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), state = state) {
                 items(list, key = { it.id }) {
                     Item(remember { "${it.id}" })
@@ -278,7 +278,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(columns = TvGridCells.Fixed(columns), state = state) {
                 items(list, key = { it.id }) {
                     Item(remember { "${it.id}" })
@@ -303,7 +303,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), Modifier.size(itemSize * 2.5f), state) {
                 items(list) {
                     Item(remember { "$it" })
@@ -326,7 +326,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), Modifier.size(itemSize * 2.5f), state) {
                 items(list, key = { it }) {
                     Item(remember { "$it" })
@@ -352,7 +352,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState(5)
+            state = rememberTvLazyGridState(5)
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), Modifier.size(itemSize * 2.5f), state) {
                 items(list, key = { it }) {
                     Item(remember { "$it" })
@@ -378,7 +378,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState(10) // key 20 is the first item
+            state = rememberTvLazyGridState(10) // key 20 is the first item
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), Modifier.size(itemSize * 2.5f), state) {
                 items(list, key = { it }) {
                     Item(remember { "$it" })
@@ -404,7 +404,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContent {
-            state = rememberLazyGridState(8)
+            state = rememberTvLazyGridState(8)
             TvLazyVerticalGrid(TvGridCells.Fixed(columns), Modifier.size(itemSize * 2.5f), state) {
                 items(list, key = { it }) {
                     Item(remember { "$it" })
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
similarity index 99%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
index d966436..c0efb11 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridAnimateItemPlacementTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.LinearEasing
@@ -1257,7 +1257,7 @@
         endPadding: Dp = 0.dp,
         content: TvLazyGridScope.() -> Unit
     ) {
-        state = rememberLazyGridState(startIndex)
+        state = rememberTvLazyGridState(startIndex)
         if (isVertical) {
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(columns),
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
index b2e1a5a..a2d095d 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.scrollBy
@@ -308,7 +308,7 @@
             ) { constraints ->
                 val placeable = if (emit) {
                     subcompose(Unit) {
-                        state = rememberLazyGridState()
+                        state = rememberTvLazyGridState()
                         LazyGrid(
                             2,
                             Modifier.mainAxisSize(itemsSizeDp * 1.5f),
@@ -359,7 +359,7 @@
         contentPadding: PaddingValues = PaddingValues(0.dp)
     ) {
         rule.setContent {
-            state = rememberLazyGridState(
+            state = rememberTvLazyGridState(
                 initialFirstVisibleItemIndex = firstItem,
                 initialFirstVisibleItemScrollOffset = itemOffset
             )
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSlotsReuseTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSlotsReuseTest.kt
similarity index 95%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSlotsReuseTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSlotsReuseTest.kt
index c9f6943..cd16ae9 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSlotsReuseTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSlotsReuseTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -51,7 +51,7 @@
     fun scroll1ItemScrolledOffItemIsKeptForReuse() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -83,7 +83,7 @@
     fun scroll2ItemsScrolledOffItemsAreKeptForReuse() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -120,7 +120,7 @@
     fun checkMaxItemsKeptForReuse() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * (DefaultMaxItemsToRetain + 0.5f)),
@@ -153,7 +153,7 @@
     fun scroll3Items2OfScrolledOffItemsAreKeptForReuse() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -204,7 +204,7 @@
     fun doMultipleScrollsOneByOne() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -248,7 +248,7 @@
     fun scrollBackwardOnce() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState(10)
+            state = rememberTvLazyGridState(10)
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -284,7 +284,7 @@
     fun scrollBackwardOneByOne() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState(10)
+            state = rememberTvLazyGridState(10)
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -323,7 +323,7 @@
         var rememberedValue0 = -1
         var rememberedValue1 = -1
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 1.5f),
@@ -373,7 +373,7 @@
         val visibleItemsCount = (DefaultMaxItemsToRetain + 1) * 2
         val startOfType1 = DefaultMaxItemsToRetain + 1
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * (visibleItemsCount - 0.5f)),
@@ -425,7 +425,7 @@
     fun differentTypesFromDifferentItemCalls() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.height(itemsSizeDp * 2.5f),
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSpanTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSpanTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSpanTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSpanTest.kt
index 3d4c09e..94d404a 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridSpanTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridSpanTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -275,7 +275,7 @@
         // regression from b/222530458
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             TvLazyVerticalGrid(
                 columns = TvGridCells.Fixed(2),
                 state = state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridTest.kt
index 4f170ec..5e29562 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import android.os.Build
 import androidx.compose.foundation.focusable
@@ -648,7 +648,7 @@
         var count by mutableStateOf(100)
         val composedIndexes = mutableListOf<Int>()
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             LazyGrid(
                 cells = 1,
                 modifier = Modifier.mainAxisSize(10.dp),
@@ -759,7 +759,7 @@
             LazyGrid(
                 cells = 1,
                 modifier = Modifier.size(itemSize * 3),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 userScrollEnabled = false,
             ) {
                 items(5) {
@@ -842,7 +842,7 @@
         val itemMainAxisSize = with(rule.density) { 30.toDp() }
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             LazyGrid(
                 cells = 2,
                 modifier = Modifier.mainAxisSize(itemMainAxisSize + 1.dp),
@@ -937,7 +937,7 @@
         lateinit var state: TvLazyGridState
 
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             LazyGrid(
                 cells = 1,
                 modifier = Modifier.composed {
@@ -1042,7 +1042,7 @@
         val items by mutableStateOf((1..20).toList())
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             LazyGrid(
                 1,
                 Modifier.requiredSize(100.dp).testTag(LazyGridTag),
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsContentPaddingTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsContentPaddingTest.kt
similarity index 95%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsContentPaddingTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsContentPaddingTest.kt
index 0f06a2b..6fd11c8 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsContentPaddingTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsContentPaddingTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.animation.core.snap
 import androidx.compose.foundation.gestures.animateScrollBy
@@ -82,7 +82,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(containerSize)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     start = smallPaddingSize,
                     top = largePaddingSize,
@@ -117,7 +117,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(itemSize * 2)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     top = itemSize,
                     bottom = itemSize
@@ -145,7 +145,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
@@ -187,7 +187,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(itemSize + padding * 2)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
@@ -223,7 +223,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
@@ -268,7 +268,7 @@
                 columns = TvGridCells.Fixed(1),
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 contentPadding = PaddingValues(
                     top = padding,
                     bottom = padding
@@ -384,7 +384,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 reverseLayout = true,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 modifier = Modifier.size(listSize),
                 contentPadding = PaddingValues(top = topPadding, bottom = bottomPadding),
             ) {
@@ -415,7 +415,7 @@
     fun column_overscrollWithContentPadding() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize + smallPaddingSize * 2)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -461,7 +461,7 @@
     fun totalPaddingLargerParentSize_initialState() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -492,7 +492,7 @@
     fun totalPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -527,7 +527,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -562,7 +562,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -598,7 +598,7 @@
         // the whole end content padding is displayed
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -630,7 +630,7 @@
     fun eachPaddingLargerParentSize_initialState() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -658,7 +658,7 @@
     fun eachPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -693,7 +693,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -731,7 +731,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -770,7 +770,7 @@
         // only the end content padding is displayed
         lateinit var state: TvLazyGridState
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 TvLazyVerticalGrid(
                     TvGridCells.Fixed(1),
@@ -808,7 +808,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(containerSize)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 top = smallPaddingSize,
     //                 start = largePaddingSize,
@@ -845,7 +845,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(itemSize * 2)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 start = itemSize,
     //                 end = itemSize
@@ -872,7 +872,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(padding * 2 + itemSize)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 start = padding,
     //                 end = padding
@@ -913,7 +913,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(itemSize + padding * 2)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 start = padding,
     //                 end = padding
@@ -948,7 +948,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(padding * 2 + itemSize)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 start = padding,
     //                 end = padding
@@ -992,7 +992,7 @@
     //         LazyRow(
     //             modifier = Modifier.requiredSize(padding * 2 + itemSize)
     //                 .testTag(LazyListTag),
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             contentPadding = PaddingValues(
     //                 start = padding,
     //                 end = padding
@@ -1104,7 +1104,7 @@
     //     rule.setContentWithTestViewConfiguration {
     //         LazyRow(
     //             reverseLayout = true,
-    //             state = rememberLazyGridState().also { state = it },
+    //             state = rememberTvLazyGridState().also { state = it },
     //             modifier = Modifier.requiredSize(listSize),
     //             contentPadding = PaddingValues(start = startPadding, end = endPadding),
     //         ) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsIndexedTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsIndexedTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsIndexedTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsIndexedTest.kt
index e99a386..7bc39fb 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsIndexedTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsIndexedTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.requiredHeight
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt
index c3cd0a9..5cf5c36 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridsReverseLayoutTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -132,7 +132,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(2),
                 reverseLayout = true,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 modifier = Modifier.size(itemSize * 2).testTag(ContainerTag)
             ) {
                 items((0..5).toList()) {
@@ -154,7 +154,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 reverseLayout = true,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 modifier = Modifier.size(itemSize * 2).testTag(ContainerTag)
             ) {
                 items((0..2).toList()) {
@@ -184,7 +184,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 reverseLayout = true,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag)
             ) {
                 items((0..2).toList()) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyItemStateRestoration.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyItemStateRestoration.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyItemStateRestoration.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyItemStateRestoration.kt
index f4e519e..d75b265 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyItemStateRestoration.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyItemStateRestoration.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.requiredSize
@@ -89,7 +89,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyGridState().also { state = it }
+                state = rememberTvLazyGridState().also { state = it }
             ) {
                 items((0..10).toList()) {
                     if (it == 0) {
@@ -140,7 +140,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyGridState().also { state = it }
+                state = rememberTvLazyGridState().also { state = it }
             ) {
                 items((0..1).toList()) {
                     if (it == 0) {
@@ -190,7 +190,7 @@
             TvLazyVerticalGrid(
                 TvGridCells.Fixed(1),
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyGridState().also { state = it }
+                state = rememberTvLazyGridState().also { state = it }
             ) {
                 items((0..10).toList()) {
                     if (it == 0) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyNestedScrollingTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyNestedScrollingTest.kt
similarity index 99%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyNestedScrollingTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyNestedScrollingTest.kt
index 404218a..ed9df04 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyNestedScrollingTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyNestedScrollingTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.gestures.ScrollableState
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollAccessibilityTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollAccessibilityTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollAccessibilityTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollAccessibilityTest.kt
index 8af2b8d..3f108d0 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollAccessibilityTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollAccessibilityTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import android.R.id.accessibilityActionScrollDown
 import android.R.id.accessibilityActionScrollLeft
@@ -230,7 +230,7 @@
             }
         }
 
-        val actions = nodeInfo.actionList.map { it.id }
+        val actions = nodeInfo?.actionList?.map { it.id }
 
         assertThat(actions).contains(expectForward, ACTION_SCROLL_FORWARD)
         assertThat(actions).contains(expectBackward, ACTION_SCROLL_BACKWARD)
@@ -265,7 +265,7 @@
         createScrollableContent {
             // Start at the start:
             // -> pretty basic
-            rememberLazyGridState(0, 0)
+            rememberTvLazyGridState(0, 0)
         }
     }
 
@@ -279,7 +279,7 @@
             // Viewport size: 200dp rect - 50dp padding on both sides = 100dp
             // Content outside viewport: 2100dp - 100dp = 2000dp
             // -> centered when 1000dp on either side, which is 47 items + 13dp
-            rememberLazyGridState(
+            rememberTvLazyGridState(
                 47,
                 with(LocalDensity.current) { 13.dp.roundToPx() }
             )
@@ -296,7 +296,7 @@
             // Viewport size: 200dp rect - 50dp padding on both sides = 100dp
             // Content outside viewport: 2100dp - 100dp = 2000dp
             // -> at the end when offset at 2000dp, which is 95 items + 5dp
-            rememberLazyGridState(
+            rememberTvLazyGridState(
                 95,
                 with(LocalDensity.current) { 5.dp.roundToPx() }
             )
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
index dc794c5..f7fd6c7 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazyScrollTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyScrollTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.animation.core.FloatSpringSpec
 import androidx.compose.foundation.gestures.animateScrollBy
@@ -66,7 +66,7 @@
             containerSizeDp = itemSizeDp * 3
         }
         rule.setContent {
-            state = rememberLazyGridState()
+            state = rememberTvLazyGridState()
             scope = rememberCoroutineScope()
             TestContent()
         }
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazySemanticsTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazySemanticsTest.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazySemanticsTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazySemanticsTest.kt
index 68c75ee..850aa91 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/LazySemanticsTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazySemanticsTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxHeight
@@ -82,7 +82,7 @@
     @Test
     fun itemsSemantics_verticalGrid() {
         rule.setContent {
-            val state = rememberLazyGridState()
+            val state = rememberTvLazyGridState()
             TvLazyVerticalGrid(TvGridCells.Fixed(1), LazyGridModifier, state) {
                 items(items = List(N) { it }, key = { key(it) }) {
                     SpacerInColumn(it)
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt
similarity index 94%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt
index d2bee39..c1ef2fb9e 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/TvLazyGridLayoutInfoTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.grid
+package androidx.tv.foundation.lazy.grid
 
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
@@ -77,7 +77,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.axisSize(gridWidthDp, itemSizeDp * 3.5f),
             ) {
@@ -98,7 +98,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.axisSize(gridWidthDp, itemSizeDp * 3.5f),
             ) {
@@ -123,7 +123,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 1,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 mainAxisSpacedBy = itemSizeDp,
                 modifier = Modifier.axisSize(itemSizeDp, itemSizeDp * 3.5f),
@@ -150,7 +150,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.axisSize(itemSizeDp * 2f, itemSizeDp * 3.5f),
             ) {
@@ -190,7 +190,7 @@
                 cells = 1,
                 modifier = Modifier.crossAxisSize(itemSizeDp),
                 reverseLayout = reverseLayout,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
             ) {
                 item {
                     Box(Modifier.size(size))
@@ -232,7 +232,7 @@
             LazyGrid(
                 cells = 2,
                 reverseLayout = reverseLayout,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
             ) {
                 items((0 until count).toList()) {
                     Box(Modifier.mainAxisSize(10.dp))
@@ -260,7 +260,7 @@
                 cells = 2,
                 modifier = Modifier.axisSize(sizeDp * 2, sizeDp),
                 reverseLayout = reverseLayout,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
             ) {
                 items((0..7).toList()) {
                     Box(Modifier.mainAxisSize(sizeDp))
@@ -305,7 +305,7 @@
                     afterContentCrossAxis = 2.dp
                 ),
                 reverseLayout = reverseLayout,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
             ) {
                 items((0..7).toList()) {
                     Box(Modifier.mainAxisSize(sizeDp))
@@ -333,7 +333,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it }
+                state = rememberTvLazyGridState().also { state = it }
             ) {
                 item { Box(Modifier) }
                 item { }
@@ -364,7 +364,7 @@
             LazyGrid(
                 cells = 1,
                 modifier = Modifier.mainAxisSize(sizeDp).crossAxisSize(sizeDp * 2),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 contentPadding = PaddingValues(
                     beforeContent = beforeContentPaddingDp,
@@ -402,7 +402,7 @@
             LazyGrid(
                 cells = 1,
                 modifier = Modifier.mainAxisSize(sizeDp).crossAxisSize(sizeDp * 2),
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 contentPadding = PaddingValues(
                     beforeContent = beforeContentPaddingDp,
@@ -432,7 +432,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.width(gridWidthDp).height(itemSizeDp * 3.5f),
             ) {
@@ -453,7 +453,7 @@
         rule.setContent {
             LazyGrid(
                 cells = 2,
-                state = rememberLazyGridState().also { state = it },
+                state = rememberTvLazyGridState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.axisSize(gridWidthDp, itemSizeDp * 3.5f),
             ) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/BaseLazyListTestWithOrientation.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/BaseLazyListTestWithOrientation.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/BaseLazyListTestWithOrientation.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/BaseLazyListTestWithOrientation.kt
index 9ab4802..d451964 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/BaseLazyListTestWithOrientation.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/BaseLazyListTestWithOrientation.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.animation.core.snap
 import androidx.compose.foundation.gestures.Orientation
@@ -75,7 +75,7 @@
             this.fillMaxHeight()
         }
 
-    fun LazyItemScope.fillParentMaxCrossAxis() =
+    fun TvLazyListItemScope.fillParentMaxCrossAxis() =
         if (vertical) {
             Modifier.fillParentMaxWidth()
         } else {
@@ -178,7 +178,7 @@
     @Composable
     fun LazyColumnOrRow(
         modifier: Modifier = Modifier,
-        state: TvLazyListState = rememberLazyListState(),
+        state: TvLazyListState = rememberTvLazyListState(),
         contentPadding: PaddingValues = PaddingValues(0.dp),
         reverseLayout: Boolean = false,
         userScrollEnabled: Boolean = true,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyArrangementsTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyArrangementsTest.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyArrangementsTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyArrangementsTest.kt
index f960ffa..9285bd1 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyArrangementsTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyArrangementsTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.gestures.scrollBy
@@ -303,7 +303,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 Modifier.size(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 verticalArrangement = Arrangement.spacedBy(spacingSize),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -340,7 +340,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 Modifier.size(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 verticalArrangement = Arrangement.spacedBy(spacingSize),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -378,7 +378,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 Modifier.size(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 horizontalArrangement = Arrangement.spacedBy(spacingSize),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -415,7 +415,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 Modifier.size(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 horizontalArrangement = Arrangement.spacedBy(spacingSize),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyColumnTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyColumnTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyColumnTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyColumnTest.kt
index 8e8bc51..45825f43 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyColumnTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyColumnTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import android.os.Build
 import androidx.tv.foundation.lazy.AutoTestFrameClock
@@ -218,7 +218,7 @@
         var count by mutableStateOf(100)
         val composedIndexes = mutableListOf<Int>()
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.fillMaxWidth().height(10.dp),
                 state,
@@ -410,7 +410,7 @@
     fun scrolledAwayItemIsNotDisplayedAnymore() {
         lateinit var state: TvLazyListState
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier
                     .requiredSize(10.dp)
@@ -456,7 +456,7 @@
     fun wrappedNestedLazyRowDisplayCorrectContent() {
         lateinit var state: TvLazyListState
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.size(20.dp),
                 state = state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyCustomKeysTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyCustomKeysTest.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyCustomKeysTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyCustomKeysTest.kt
index 69d0123..b3c8a3b 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyCustomKeysTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyCustomKeysTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.Spacer
@@ -262,7 +262,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 state = state,
                 pivotOffsets = PivotOffsets(parentFraction = 0f)) {
@@ -285,7 +285,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 state = state,
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
@@ -313,7 +313,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.size(itemSize * 2.5f),
                 state,
@@ -340,7 +340,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.size(itemSize * 2.5f),
                 state,
@@ -370,7 +370,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState(5)
+            state = rememberTvLazyListState(5)
             TvLazyColumn(
                 Modifier.size(itemSize * 2.5f),
                 state,
@@ -400,7 +400,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState(10) // key 20 is the first item
+            state = rememberTvLazyListState(10) // key 20 is the first item
             TvLazyColumn(
                 Modifier.size(itemSize * 2.5f),
                 state,
@@ -430,7 +430,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContent {
-            state = rememberLazyListState(5)
+            state = rememberTvLazyListState(5)
             TvLazyColumn(
                 Modifier.size(itemSize * 2.5f),
                 state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyItemStateRestoration.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyItemStateRestoration.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyItemStateRestoration.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyItemStateRestoration.kt
index 6a037fb..15c520a 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyItemStateRestoration.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyItemStateRestoration.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -89,7 +89,7 @@
         restorationTester.setContent {
             TvLazyColumn(
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
                 items((0..10).toList()) {
@@ -140,7 +140,7 @@
         restorationTester.setContent {
             TvLazyColumn(
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
                 items((0..1).toList()) {
@@ -190,7 +190,7 @@
         restorationTester.setContent {
             TvLazyColumn(
                 Modifier.requiredSize(20.dp),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
                 items((0..10).toList()) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
index 351bf6f..07b5201 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.LinearEasing
@@ -111,7 +111,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -137,7 +137,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -160,7 +160,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -195,7 +195,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -233,7 +233,7 @@
                 maxSize = itemSizeDp * 5
             ) {
                 items(listOf(0, 1, 2, 3), key = { it }) {
-                    Item(it, size = if (it == 1) size else itemSizeDp)
+                    item(it, size = if (it == 1) size else itemSizeDp)
                 }
             }
         }
@@ -275,7 +275,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it, animSpec = if (it == 1 || it == 3) AnimSpec else null)
+                    item(it, animSpec = if (it == 1 || it == 3) AnimSpec else null)
                 }
             }
         }
@@ -303,7 +303,7 @@
             LazyList {
                 items(list, key = { it }) {
                     val duration = if (it == 1 || it == 3) Duration * 2 else Duration
-                    Item(it, animSpec = tween(duration.toInt(), easing = LinearEasing))
+                    item(it, animSpec = tween(duration.toInt(), easing = LinearEasing))
                 }
             }
         }
@@ -331,8 +331,8 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
-                    Item(it + 1)
+                    item(it)
+                    item(it + 1)
                 }
             }
         }
@@ -365,8 +365,8 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
-                    Item(it + 1, animSpec = null)
+                    item(it)
+                    item(it + 1, animSpec = null)
                 }
             }
         }
@@ -396,7 +396,7 @@
                 maxSize = itemSizeDp * 5
             ) {
                 items(listOf(1, 2, 3), key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -428,7 +428,7 @@
         rule.setContent {
             LazyList(maxSize = itemSizeDp * 3) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -473,7 +473,7 @@
         rule.setContent {
             LazyList(maxSize = itemSizeDp * 3f, startIndex = 3) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -518,7 +518,7 @@
         rule.setContent {
             LazyList(arrangement = Arrangement.spacedBy(spacingDp)) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -547,7 +547,7 @@
                 arrangement = Arrangement.spacedBy(spacingDp)
             ) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -599,7 +599,7 @@
                 arrangement = Arrangement.spacedBy(spacingDp)
             ) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -648,7 +648,7 @@
                 items(list, key = { it }) {
                     val size =
                         if (it == 3) itemSize2Dp else if (it == 1) itemSize3Dp else itemSizeDp
-                    Item(it, size = size)
+                    item(it, size = size)
                 }
             }
         }
@@ -708,7 +708,7 @@
                 items(list, key = { it }) {
                     val size =
                         if (it == 0) itemSize2Dp else if (it == 4) itemSize3Dp else itemSizeDp
-                    Item(it, size = size)
+                    item(it, size = size)
                 }
             }
         }
@@ -769,7 +769,7 @@
                 items(listOf(1, 2, 3), key = { it }) {
                     val crossAxisSize =
                         if (it == 1) itemSizeDp else if (it == 2) itemSize2Dp else itemSize3Dp
-                    Item(it, crossAxisSize = crossAxisSize)
+                    item(it, crossAxisSize = crossAxisSize)
                 }
             }
         }
@@ -821,7 +821,7 @@
                     listOf(1, 2, 3).forEach {
                         val crossAxisSize =
                             if (it == 1) itemSizeDp else if (it == 2) itemSize2Dp else itemSize3Dp
-                        Item(it, crossAxisSize = crossAxisSize)
+                        item(it, crossAxisSize = crossAxisSize)
                     }
                 }
             }
@@ -863,7 +863,7 @@
                     items(listOf(1, 2, 3), key = { it }) {
                         val crossAxisSize =
                             if (it == 1) itemSizeDp else if (it == 2) itemSize2Dp else itemSize3Dp
-                        Item(it, crossAxisSize = crossAxisSize)
+                        item(it, crossAxisSize = crossAxisSize)
                     }
                 }
             }
@@ -911,7 +911,7 @@
         rule.setContent {
             LazyList(startPadding = startPaddingDp, endPadding = endPaddingDp) {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -949,7 +949,7 @@
         rule.setContent {
             LazyList {
                 items(list, key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
             LaunchedEffect(Unit) {
@@ -982,7 +982,7 @@
         rule.setContent {
             LazyList(maxSize = itemSizeDp * 3) {
                 items(listOf(0, 1, 2, 3, 4, 5, 6, 7), key = { it }) {
-                    Item(it)
+                    item(it)
                 }
             }
         }
@@ -1098,7 +1098,7 @@
         endPadding: Dp = 0.dp,
         content: TvLazyListScope.() -> Unit
     ) {
-        state = rememberLazyListState(startIndex)
+        state = rememberTvLazyListState(startIndex)
         if (isVertical) {
             val verticalArrangement =
                 arrangement ?: if (!reverseLayout) Arrangement.Top else Arrangement.Bottom
@@ -1161,7 +1161,7 @@
     }
 
     @Composable
-    private fun LazyItemScope.Item(
+    private fun TvLazyListItemScope.item(
         tag: Int,
         size: Dp = itemSizeDp,
         crossAxisSize: Dp = size,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListLayoutInfoTest.kt
similarity index 92%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListLayoutInfoTest.kt
index 5e39177..cf2e225 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListLayoutInfoTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
@@ -71,7 +71,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
             ) {
@@ -91,7 +91,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
             ) {
@@ -114,7 +114,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 spacedBy = itemSizeDp,
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
@@ -131,16 +131,16 @@
     }
 
     @Composable
-    fun ObservingFun(state: TvLazyListState, currentInfo: StableRef<LazyListLayoutInfo?>) {
+    fun ObservingFun(state: TvLazyListState, currentInfo: StableRef<TvLazyListLayoutInfo?>) {
         currentInfo.value = state.layoutInfo
     }
     @Test
     fun visibleItemsAreObservableWhenWeScroll() {
         lateinit var state: TvLazyListState
-        val currentInfo = StableRef<LazyListLayoutInfo?>(null)
+        val currentInfo = StableRef<TvLazyListLayoutInfo?>(null)
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
             ) {
@@ -169,7 +169,7 @@
     fun visibleItemsAreObservableWhenResize() {
         lateinit var state: TvLazyListState
         var size by mutableStateOf(itemSizeDp * 2)
-        var currentInfo: LazyListLayoutInfo? = null
+        var currentInfo: TvLazyListLayoutInfo? = null
         @Composable
         fun observingFun() {
             currentInfo = state.layoutInfo
@@ -177,7 +177,7 @@
         rule.setContent {
             LazyColumnOrRow(
                 reverseLayout = reverseLayout,
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 item {
                     Box(Modifier.requiredSize(size))
@@ -206,7 +206,7 @@
         rule.setContent {
             LazyColumnOrRow(
                 reverseLayout = reverseLayout,
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 items((0 until count).toList()) {
                     Box(Modifier.requiredSize(10.dp))
@@ -233,7 +233,7 @@
             LazyColumnOrRow(
                 Modifier.mainAxisSize(sizeDp).crossAxisSize(sizeDp * 2),
                 reverseLayout = reverseLayout,
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 items((0..3).toList()) {
                     Box(Modifier.requiredSize(sizeDp))
@@ -273,7 +273,7 @@
                     afterContentCrossAxis = 2.dp
                 ),
                 reverseLayout = reverseLayout,
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 items((0..3).toList()) {
                     Box(Modifier.requiredSize(sizeDp))
@@ -296,7 +296,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 item { Box(Modifier) }
                 item { }
@@ -326,7 +326,7 @@
         rule.setContent {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(sizeDp).crossAxisSize(sizeDp * 2),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 contentPadding = PaddingValues(
                     beforeContent = beforeContentPaddingDp,
@@ -363,7 +363,7 @@
         rule.setContent {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(sizeDp).crossAxisSize(sizeDp * 2),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 contentPadding = PaddingValues(
                     beforeContent = beforeContentPaddingDp,
@@ -392,7 +392,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 reverseLayout = reverseLayout,
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
             ) {
@@ -412,7 +412,7 @@
         lateinit var state: TvLazyListState
         rule.setContent {
             LazyColumnOrRow(
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSizeDp * 3.5f)
             ) {
                 items((0..5).toList()) {
@@ -427,7 +427,7 @@
         }
     }
 
-    fun LazyListLayoutInfo.assertVisibleItems(
+    private fun TvLazyListLayoutInfo.assertVisibleItems(
         count: Int,
         startIndex: Int = 0,
         startOffset: Int = 0,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListPrefetcherTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
index db1d248..14401a4 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.tv.foundation.lazy.AutoTestFrameClock
 import androidx.compose.foundation.gestures.Orientation
@@ -290,7 +290,7 @@
             ) { constraints ->
                 val placeable = if (emit) {
                     subcompose(Unit) {
-                        state = rememberLazyListState()
+                        state = rememberTvLazyListState()
                         LazyColumnOrRow(
                             Modifier.mainAxisSize(itemsSizeDp * 1.5f),
                             state,
@@ -342,7 +342,7 @@
         contentPadding: PaddingValues = PaddingValues(0.dp)
     ) {
         rule.setContent {
-            state = rememberLazyListState(
+            state = rememberTvLazyListState(
                 initialFirstVisibleItemIndex = firstItem,
                 initialFirstVisibleItemScrollOffset = itemOffset
             )
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListSlotsReuseTest.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListSlotsReuseTest.kt
index 7e0f810..3083be7 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListSlotsReuseTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -54,7 +54,7 @@
     fun scroll1ItemScrolledOffItemIsKeptForReuse() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -88,7 +88,7 @@
     fun scroll2ItemsScrolledOffItemsAreKeptForReuse() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -127,7 +127,7 @@
     fun checkMaxItemsKeptForReuse() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * (DefaultMaxItemsToRetain + 0.5f)),
                 state,
@@ -162,7 +162,7 @@
     fun scroll3Items2OfScrolledOffItemsAreKeptForReuse() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -215,7 +215,7 @@
     fun doMultipleScrollsOneByOne() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -261,7 +261,7 @@
     fun scrollBackwardOnce() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState(10)
+            state = rememberTvLazyListState(10)
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -299,7 +299,7 @@
     fun scrollBackwardOneByOne() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState(10)
+            state = rememberTvLazyListState(10)
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -340,7 +340,7 @@
         var rememberedValue0 = -1
         var rememberedValue1 = -1
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 1.5f),
                 state,
@@ -392,7 +392,7 @@
         val visibleItemsCount = (DefaultMaxItemsToRetain + 1) * 2
         val startOfType1 = DefaultMaxItemsToRetain + 1
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * (visibleItemsCount - 0.5f)),
                 state,
@@ -445,7 +445,7 @@
     fun differentTypesFromDifferentItemCalls() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             TvLazyColumn(
                 Modifier.height(itemsSizeDp * 2.5f),
                 state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
similarity index 97%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
index 6b61bf4..5438a7a 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import android.os.Build
 import androidx.compose.foundation.background
@@ -762,7 +762,7 @@
         val items by mutableStateOf((1..20).toList())
         lateinit var state: TvLazyListState
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             state.prefetchingEnabled = false
             LazyColumnOrRow(
                 Modifier.requiredSize(100.dp).testTag(LazyListTag),
@@ -792,7 +792,7 @@
         val items by mutableStateOf((1..20).toList())
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(
                 Modifier.requiredSize(100.dp).testTag(LazyListTag),
                 state = state
@@ -837,7 +837,7 @@
         lateinit var state: TvLazyListState
         val expectedOffset = with(rule.density) { 10.dp.roundToPx() }
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState(2, expectedOffset)
+            state = rememberTvLazyListState(2, expectedOffset)
             LazyColumnOrRow(
                 Modifier.requiredSize(100.dp).testTag(LazyListTag),
                 state = state
@@ -862,7 +862,7 @@
         val restorationTester = StateRestorationTester(rule)
         var state: TvLazyListState? = null
         restorationTester.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(
                 Modifier.requiredSize(100.dp).testTag(LazyListTag),
                 state = state!!
@@ -893,7 +893,7 @@
     fun snapToItemIndex() {
         lateinit var state: TvLazyListState
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(
                 Modifier.requiredSize(100.dp).testTag(LazyListTag),
                 state = state
@@ -991,7 +991,7 @@
         rule.setContentWithTestViewConfiguration {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(itemSizeMinusOne).testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 items(2) {
                     Spacer(
@@ -1019,7 +1019,7 @@
         rule.setContentWithTestViewConfiguration {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(itemSize * 1.75f).testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it }
+                state = rememberTvLazyListState().also { state = it }
             ) {
                 items(items) {
                     Spacer(
@@ -1095,7 +1095,7 @@
         var count by mutableStateOf(100)
         val composedIndexes = mutableListOf<Int>()
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(Modifier.fillMaxCrossAxis().mainAxisSize(10.dp), state) {
                 items(count) { index ->
                     composedIndexes.add(index)
@@ -1133,7 +1133,7 @@
                     Modifier
                         .testTag(LazyListTag)
                         .background(Color.Blue),
-                    state = rememberLazyListState(2, 5)
+                    state = rememberTvLazyListState(2, 5)
                 ) {
                     items(100) {
                         Box(
@@ -1171,7 +1171,7 @@
                     Modifier
                         .padding(20.dp)
                         .fillMaxSize(),
-                    rememberLazyListState(1)
+                    rememberTvLazyListState(1)
                 ) {
                     items(4) {
                         Box(Modifier.size(20.dp).drawOutsideOfBounds())
@@ -1200,7 +1200,7 @@
         lateinit var state: TvLazyListState
         var itemsCount by mutableStateOf(0)
         rule.setContent {
-            state = rememberLazyListState(2, 10)
+            state = rememberTvLazyListState(2, 10)
             LazyColumnOrRow(Modifier.fillMaxSize(), state) {
                 items(itemsCount) {
                     Box(Modifier.size(20.dp))
@@ -1225,7 +1225,7 @@
         val recomposeCounter = mutableStateOf(0)
         val tester = StateRestorationTester(rule)
         tester.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(Modifier.fillMaxSize(), state) {
                 recomposeCounter.value
                 items(itemsCount) {
@@ -1260,7 +1260,7 @@
         var target = 0
         var reverse = false
         rule.setContent {
-            val listState = rememberLazyListState()
+            val listState = rememberTvLazyListState()
             SideEffect {
                 state = listState
             }
@@ -1313,7 +1313,7 @@
     fun animateScrollToTheLastItemWhenItemsAreLargerThenTheScreen() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(Modifier.crossAxisSize(150.dp).mainAxisSize(100.dp), state) {
                 items(20) {
                     Box(Modifier.size(150.dp))
@@ -1435,7 +1435,7 @@
         rule.setContentWithTestViewConfiguration {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
             ) {
                 items(5) {
                     Spacer(
@@ -1503,7 +1503,7 @@
         rule.setContentWithTestViewConfiguration {
             LazyColumnOrRow(
                 Modifier.mainAxisSize(itemSize * 3),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 userScrollEnabled = false,
             ) {
                 items(5) {
@@ -1552,7 +1552,7 @@
         val itemSize = with(rule.density) { 30.toDp() }
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(
                 modifier = Modifier.mainAxisSize(itemSize + 1.dp),
                 state = state
@@ -1640,7 +1640,7 @@
         lateinit var state: TvLazyListState
 
         rule.setContentWithTestViewConfiguration {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             LazyColumnOrRow(
                 Modifier.composed {
                     recomposeCount++
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsContentPaddingTest.kt
similarity index 95%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsContentPaddingTest.kt
index eccaaed..cfead8b 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsContentPaddingTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.scrollBy
@@ -67,7 +67,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(containerSize)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(
                     mainAxis = largePaddingSize,
                     crossAxis = smallPaddingSize
@@ -104,7 +104,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(itemSize * 2)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(mainAxis = itemSize)
             ) {
                 items(listOf(1)) {
@@ -132,7 +132,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(mainAxis = padding)
             ) {
                 items((0..3).toList()) {
@@ -170,7 +170,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(itemSize + padding * 2)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(mainAxis = padding)
             ) {
                 items((0..3).toList()) {
@@ -202,7 +202,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(mainAxis = padding)
             ) {
                 items((0..3).toList()) {
@@ -243,7 +243,7 @@
             LazyColumnOrRow(
                 modifier = Modifier.requiredSize(padding * 2 + itemSize)
                     .testTag(LazyListTag),
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 contentPadding = PaddingValues(mainAxis = padding)
             ) {
                 items((0..3).toList()) {
@@ -352,7 +352,7 @@
         rule.setContentWithTestViewConfiguration {
             LazyColumnOrRow(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(listSize),
                 contentPadding = PaddingValues(
                     beforeContent = topPadding,
@@ -386,7 +386,7 @@
     fun overscrollWithContentPadding() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize + smallPaddingSize * 2)) {
                 LazyColumnOrRow(
                     state = state,
@@ -429,7 +429,7 @@
     fun totalPaddingLargerParentSize_initialState() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -459,7 +459,7 @@
     fun totalPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -493,7 +493,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -527,7 +527,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -562,7 +562,7 @@
         // the whole end content padding is displayed
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -593,7 +593,7 @@
     fun eachPaddingLargerParentSize_initialState() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -620,7 +620,7 @@
     fun eachPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -654,7 +654,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -691,7 +691,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
@@ -729,7 +729,7 @@
         // only the end content padding is displayed
         lateinit var state: TvLazyListState
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             Box(modifier = Modifier.testTag(ContainerTag).size(itemSize * 1.5f)) {
                 LazyColumnOrRow(
                     state = state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsIndexedTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsIndexedTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsIndexedTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsIndexedTest.kt
index a868e08..9eab54b 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsIndexedTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsIndexedTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Spacer
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsReverseLayoutTest.kt
similarity index 95%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsReverseLayoutTest.kt
index 1798212..4ec7ab7 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListsReverseLayoutTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -105,7 +105,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -127,7 +127,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -157,7 +157,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0.3f)
             ) {
@@ -189,7 +189,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyColumn(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -264,7 +264,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -286,7 +286,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -316,7 +316,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0.3f)
             ) {
@@ -348,7 +348,7 @@
         rule.setContentWithTestViewConfiguration {
             TvLazyRow(
                 reverseLayout = true,
-                state = rememberLazyListState().also { state = it },
+                state = rememberTvLazyListState().also { state = it },
                 modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                 pivotOffsets = PivotOffsets(parentFraction = 0f)
             ) {
@@ -427,7 +427,7 @@
             CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                 TvLazyRow(
                     reverseLayout = true,
-                    state = rememberLazyListState().also { state = it },
+                    state = rememberTvLazyListState().also { state = it },
                     modifier = Modifier.requiredSize(itemSize * 2).testTag(ContainerTag),
                     pivotOffsets = PivotOffsets(parentFraction = 0.3f)
                 ) {
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyNestedScrollingTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyNestedScrollingTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyNestedScrollingTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyNestedScrollingTest.kt
index c79c0f8..02ba39f 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyNestedScrollingTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyNestedScrollingTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.gestures.ScrollableState
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyRowTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyRowTest.kt
similarity index 96%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyRowTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyRowTest.kt
index 13bfd51..0817a21 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyRowTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyRowTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -126,7 +126,7 @@
         rule.setContentWithTestViewConfiguration {
             CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                 Box(Modifier.width(100.dp)) {
-                    state = rememberLazyListState()
+                    state = rememberTvLazyListState()
                     TvLazyRow(
                         Modifier.testTag(LazyListTag),
                         state,
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyScrollTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyScrollTest.kt
index e8416f6..f5b44f4 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazyScrollTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyScrollTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.animation.core.FloatSpringSpec
 import androidx.tv.foundation.lazy.AutoTestFrameClock
@@ -70,7 +70,7 @@
             containerSizeDp = itemSizeDp * 3
         }
         rule.setContent {
-            state = rememberLazyListState()
+            state = rememberTvLazyListState()
             scope = rememberCoroutineScope()
             TestContent()
         }
diff --git a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazySemanticsTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazySemanticsTest.kt
similarity index 98%
rename from tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazySemanticsTest.kt
rename to tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazySemanticsTest.kt
index 2ac1492..328d9ca 100644
--- a/tv/tv-foundation/src/androidAndroidTest/kotlin/androidx/tv/compose/foundation/lazy/list/LazySemanticsTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazySemanticsTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.tv.compose.foundation.lazy.list
+package androidx.tv.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxHeight
diff --git a/wear/watchface/watchface-client-guava/lint-baseline.xml b/wear/watchface/watchface-client-guava/lint-baseline.xml
deleted file mode 100644
index a4e3c85..0000000
--- a/wear/watchface/watchface-client-guava/lint-baseline.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 27 (current min is 26): `WatchFaceControlService`"
-        errorLine1="    private val realService = object : WatchFaceControlService() {"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Extending WatchFaceControlService requires API level 27 (current min is 26): `WatchFaceControlService`"
-        errorLine1="    private val realService = object : WatchFaceControlService() {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt"/>
-    </issue>
-
-</issues>
diff --git a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
index 05be0f5..43b28e3 100644
--- a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
+++ b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
@@ -22,7 +22,9 @@
 import android.content.Context
 import android.content.Intent
 import android.content.res.XmlResourceParser
+import android.os.Build
 import android.os.IBinder
+import androidx.annotation.RequiresApi
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
@@ -43,6 +45,7 @@
  * [ListenableWatchFaceMetadataClientTest] and to optionally override the reported API version.
  */
 public class WatchFaceControlTestService : Service() {
+    @RequiresApi(Build.VERSION_CODES.O_MR1)
     private val realService = object : WatchFaceControlService() {
         @SuppressLint("NewApi")
         override fun createServiceStub(): IWatchFaceInstanceServiceStub =
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Type.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Type.kt
index 263c5bc..905b056a 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Type.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Type.kt
@@ -85,6 +85,9 @@
                 PHOTO_IMAGE.wireType -> PHOTO_IMAGE
                 NO_PERMISSION.wireType -> NO_PERMISSION
                 PROTO_LAYOUT.wireType -> PROTO_LAYOUT
+                GOAL_PROGRESS.wireType -> GOAL_PROGRESS
+                DISCRETE_RANGED_VALUE.wireType -> DISCRETE_RANGED_VALUE
+                WEIGHTED_ELEMENTS.wireType -> WEIGHTED_ELEMENTS
                 LIST.wireType -> LIST
                 else -> EMPTY
             }
diff --git a/wear/watchface/watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt b/wear/watchface/watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
index 666a11c..52b49d5 100644
--- a/wear/watchface/watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
+++ b/wear/watchface/watchface-style/src/test/java/androidx/wear/watchface/style/StyleParcelableTest.kt
@@ -38,8 +38,6 @@
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
-import org.junit.Assume.assumeTrue
-import org.junit.Before
 import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,11 +79,6 @@
         watchFaceEditorData = WatchFaceEditorData(wfIcon4)
     )
 
-    @Before
-    public fun setUp() {
-        assumeTrue("These tests require API 28", Build.VERSION.SDK_INT >= 28)
-    }
-
     @Test
     public fun parcelAndUnparcelStyleSettingAndOption() {
         val settingIcon = Icon.createWithContentUri("settingIcon")
diff --git a/wear/watchface/watchface/build.gradle b/wear/watchface/watchface/build.gradle
index b755288..ccdc3b9 100644
--- a/wear/watchface/watchface/build.gradle
+++ b/wear/watchface/watchface/build.gradle
@@ -25,7 +25,7 @@
 }
 
 dependencies {
-    api(project(":annotation:annotation"))
+    api("androidx.annotation:annotation:1.5.0-alpha01")
     api("androidx.fragment:fragment:1.2.0")
     api(project(":wear:watchface:watchface-complications-data"))
     api(project(":wear:watchface:watchface-data"))
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/foreground/SystemForegroundService.java b/work/work-runtime/src/main/java/androidx/work/impl/foreground/SystemForegroundService.java
index 3055080..271594a 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/foreground/SystemForegroundService.java
+++ b/work/work-runtime/src/main/java/androidx/work/impl/foreground/SystemForegroundService.java
@@ -17,6 +17,7 @@
 package androidx.work.impl.foreground;
 
 import android.Manifest;
+import android.app.ForegroundServiceStartNotAllowedException;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.Service;
@@ -125,7 +126,10 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                    Api31Impl.startForeground(SystemForegroundService.this, notificationId,
+                            notification, notificationType);
+                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                     Api29Impl.startForeground(SystemForegroundService.this, notificationId,
                             notification, notificationType);
                 } else {
@@ -176,4 +180,24 @@
             service.startForeground(id, notification, foregroundServiceType);
         }
     }
+
+    @RequiresApi(31)
+    static class Api31Impl {
+        private Api31Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void startForeground(Service service, int id, Notification notification,
+                int foregroundServiceType) {
+            try {
+                service.startForeground(id, notification, foregroundServiceType);
+            } catch (ForegroundServiceStartNotAllowedException exception) {
+                // This should ideally never happen. But there a chance that this method
+                // is called, and the app is no longer in a state where it's possible to start a
+                // foreground service. WorkManager will eventually call stop() to clean up.
+                Logger.get().warning(TAG, "Unable to start foreground service", exception);
+            }
+        }
+    }
 }