Merge "Create VideoCapture" into androidx-main
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index 2071570..e93305c 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -71,6 +71,7 @@
 
         var modified = false
         for (useCase in useCases) {
+            enabledUseCases.remove(useCase)
             modified = attachedUseCases.remove(useCase) || modified
         }
 
diff --git a/camera/camera-camera2/src/androidTest/AndroidManifest.xml b/camera/camera-camera2/src/androidTest/AndroidManifest.xml
index b53d4ff..4a5d228 100644
--- a/camera/camera-camera2/src/androidTest/AndroidManifest.xml
+++ b/camera/camera-camera2/src/androidTest/AndroidManifest.xml
@@ -1,42 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!--
+  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
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
 
-  http://www.apache.org/licenses/LICENSE-2.0
+       http://www.apache.org/licenses/LICENSE-2.0
 
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT 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"
     package="androidx.camera.camera2.test">
-
-
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
-    <application>
-        <activity
-            android:name="androidx.camera.testing.activity.CameraXTestActivity"
-            android:label="CameraX TestActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-        <activity
-            android:name="androidx.camera.testing.activity.Camera2TestActivity"
-            android:label="Camera2 TestActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
 </manifest>
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
deleted file mode 100644
index 2b8db23..0000000
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/CameraDisconnectTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.camera2;
-
-import static androidx.camera.testing.CoreAppTestUtil.ForegroundOccupiedError;
-import static androidx.camera.testing.CoreAppTestUtil.assumeCanTestCameraDisconnect;
-import static androidx.camera.testing.CoreAppTestUtil.assumeCompatibleDevice;
-import static androidx.camera.testing.CoreAppTestUtil.prepareDeviceUI;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-
-import androidx.camera.core.CameraX;
-import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.activity.Camera2TestActivity;
-import androidx.camera.testing.activity.CameraXTestActivity;
-import androidx.test.core.app.ActivityScenario;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.espresso.Espresso;
-import androidx.test.espresso.IdlingRegistry;
-import androidx.test.espresso.IdlingResource;
-import androidx.test.espresso.idling.CountingIdlingResource;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
-
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class CameraDisconnectTest {
-
-    @Rule
-    public TestRule mCameraRule = CameraUtil.grantCameraPermissionAndPreTest();
-
-    @Before
-    public void setUp() throws ForegroundOccupiedError {
-        assumeCompatibleDevice();
-        assumeCanTestCameraDisconnect();
-
-        final Context context = ApplicationProvider.getApplicationContext();
-        CameraX.initialize(context, Camera2Config.defaultConfig());
-
-        // Clear the device UI and check if there is no dialog or lock screen on the top of the
-        // window before start the test.
-        prepareDeviceUI(InstrumentationRegistry.getInstrumentation());
-    }
-
-    @After
-    public void tearDown() throws ExecutionException, InterruptedException, TimeoutException {
-        CameraX.shutdown().get(10_000, TimeUnit.MILLISECONDS);
-    }
-
-    @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.M) // Known issue, checkout b/147393563.
-    public void testDisconnect_launchCamera2App() {
-        // Launch CameraX test activity
-        final ActivityScenario<CameraXTestActivity> cameraXActivity = ActivityScenario.launch(
-                CameraXTestActivity.class);
-
-        // Wait for preview to become active
-        final AtomicReference<CountingIdlingResource> cameraXPreviewReady = new AtomicReference<>();
-        cameraXActivity.onActivity(activity -> cameraXPreviewReady.set(activity.getPreviewReady()));
-        waitFor(cameraXPreviewReady.get());
-
-        // Get id of camera opened by CameraX test activity
-        final AtomicReference<String> cameraId = new AtomicReference<>();
-        cameraXActivity.onActivity(activity -> cameraId.set(activity.getCameraId()));
-        assertThat(cameraId.get()).isNotNull();
-
-        // Launch Camera2 test activity. It should cause the camera to disconnect from CameraX.
-        final Intent intent = new Intent(ApplicationProvider.getApplicationContext(),
-                Camera2TestActivity.class);
-        intent.putExtra(Camera2TestActivity.EXTRA_CAMERA_ID, cameraId.get());
-        final ActivityScenario<Camera2TestActivity> camera2Activity = ActivityScenario.launch(
-                intent);
-
-        // Wait for preview to become active
-        final AtomicReference<CountingIdlingResource> camera2PreviewReady = new AtomicReference<>();
-        camera2Activity.onActivity(activity -> camera2PreviewReady.set(activity.mPreviewReady));
-        waitFor(camera2PreviewReady.get());
-
-        // Close Camera2 test activity, and verify the CameraX Preview resumes successfully.
-        camera2Activity.close();
-        waitFor(cameraXPreviewReady.get());
-
-        // Close CameraX test activity
-        cameraXActivity.close();
-    }
-
-    private static void waitFor(IdlingResource idlingResource) {
-        IdlingRegistry.getInstance().register(idlingResource);
-        Espresso.onIdle();
-        IdlingRegistry.getInstance().unregister(idlingResource);
-    }
-
-}
diff --git a/camera/camera-testing/src/main/AndroidManifest.xml b/camera/camera-testing/src/main/AndroidManifest.xml
index 20e22e1..958dea7 100644
--- a/camera/camera-testing/src/main/AndroidManifest.xml
+++ b/camera/camera-testing/src/main/AndroidManifest.xml
@@ -17,6 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="androidx.camera.testing">
     <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
+    <uses-permission android:name="android.permission.CAMERA" />
     <application>
         <activity
             android:name="androidx.camera.testing.activity.ForegroundTestActivity"
@@ -26,6 +27,22 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+        <activity
+            android:name="androidx.camera.testing.activity.CameraXTestActivity"
+            android:label="CameraX TestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="androidx.camera.testing.activity.Camera2TestActivity"
+            android:label="Camera2 TestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
 
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java b/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
index 0952135..30e7dea 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/activity/CameraXTestActivity.java
@@ -17,11 +17,13 @@
 package androidx.camera.testing.activity;
 
 
+import static androidx.camera.testing.SurfaceTextureProvider.createSurfaceTextureProvider;
+
 import android.graphics.SurfaceTexture;
 import android.os.Bundle;
 import android.util.Size;
-import android.view.Surface;
 import android.view.TextureView;
+import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -32,10 +34,10 @@
 import androidx.camera.core.Logger;
 import androidx.camera.core.Preview;
 import androidx.camera.core.impl.CameraInternal;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.internal.CameraUseCaseAdapter;
 import androidx.camera.testing.CameraUtil;
 import androidx.camera.testing.R;
+import androidx.camera.testing.SurfaceTextureProvider;
 import androidx.test.espresso.idling.CountingIdlingResource;
 
 import java.util.Collections;
@@ -113,7 +115,6 @@
                     public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture,
                             int width, int height) {
                         Logger.d(TAG, "SurfaceTexture available");
-                        setSurfaceProvider(surfaceTexture);
                     }
 
                     @Override
@@ -138,6 +139,24 @@
                     }
                 });
 
+        mPreview.setSurfaceProvider(createSurfaceTextureProvider(
+                new SurfaceTextureProvider.SurfaceTextureCallback() {
+                    @Override
+                    public void onSurfaceTextureReady(@NonNull SurfaceTexture surfaceTexture,
+                            @NonNull Size resolution) {
+                        ViewGroup viewGroup = (ViewGroup) textureView.getParent();
+                        viewGroup.removeView(textureView);
+                        viewGroup.addView(textureView, resolution.getWidth(),
+                                resolution.getHeight());
+                        textureView.setSurfaceTexture(surfaceTexture);
+                    }
+
+                    @Override
+                    public void onSafeToRelease(@NonNull SurfaceTexture surfaceTexture) {
+                        surfaceTexture.release();
+                    }
+                }));
+
         try {
             final CameraX cameraX = CameraX.getOrCreateInstance(this).get();
             final LinkedHashSet<CameraInternal> cameras =
@@ -158,25 +177,6 @@
                 cameraSelector).getCameraInfoInternal().getCameraId();
     }
 
-    void setSurfaceProvider(@NonNull SurfaceTexture surfaceTexture) {
-        if (mPreview == null) {
-            return;
-        }
-        mPreview.setSurfaceProvider((surfaceRequest) -> {
-            final Size resolution = surfaceRequest.getResolution();
-            surfaceTexture.setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
-
-            final Surface surface = new Surface(surfaceTexture);
-            surfaceRequest.provideSurface(
-                    surface,
-                    CameraXExecutors.directExecutor(),
-                    (surfaceResponse) -> {
-                        surface.release();
-                        surfaceTexture.release();
-                    });
-        });
-    }
-
     @Nullable
     public String getCameraId() {
         return mCameraId;
diff --git a/camera/camera-testing/src/main/res/layout/activity_camera_main.xml b/camera/camera-testing/src/main/res/layout/activity_camera_main.xml
index fdc92c0..5a08f695 100644
--- a/camera/camera-testing/src/main/res/layout/activity_camera_main.xml
+++ b/camera/camera-testing/src/main/res/layout/activity_camera_main.xml
@@ -13,7 +13,7 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<RelativeLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -23,4 +23,4 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-</RelativeLayout>
+</FrameLayout>
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraDisconnectTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraDisconnectTest.kt
new file mode 100644
index 0000000..45de9b6
--- /dev/null
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/CameraDisconnectTest.kt
@@ -0,0 +1,158 @@
+/*
+ * 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.camera.integration.core
+
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.camera2.pipe.integration.CameraPipeConfig
+import androidx.camera.core.CameraX
+import androidx.camera.core.CameraXConfig
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CoreAppTestUtil
+import androidx.camera.testing.activity.Camera2TestActivity
+import androidx.camera.testing.activity.CameraXTestActivity
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.IdlingPolicies
+import androidx.test.espresso.IdlingRegistry
+import androidx.test.espresso.IdlingResource
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.TimeUnit
+
+/** Tests for [CameraX] which varies use case combinations to run. */
+@LargeTest
+@RunWith(Parameterized::class)
+class CameraDisconnectTest(
+    private val implName: String,
+    private val cameraConfig: CameraXConfig
+) {
+
+    @get:Rule
+    val cameraRule = CameraUtil.grantCameraPermissionAndPreTest()
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun data() = listOf(
+            arrayOf(Camera2Config::class.simpleName, Camera2Config.defaultConfig()),
+            arrayOf(CameraPipeConfig::class.simpleName, CameraPipeConfig.defaultConfig())
+        )
+    }
+
+    @Suppress("DEPRECATION")
+    @get:Rule
+    val cameraXTestActivityRule = androidx.test.rule.ActivityTestRule(
+        CameraXTestActivity::class.java, true, false
+    )
+
+    @Suppress("DEPRECATION")
+    @get:Rule
+    val camera2ActivityRule = androidx.test.rule.ActivityTestRule(
+        Camera2TestActivity::class.java, true, false
+    )
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Before
+    fun setUp() {
+        IdlingPolicies.setIdlingResourceTimeout(10, TimeUnit.SECONDS)
+        CoreAppTestUtil.assumeCompatibleDevice()
+        CoreAppTestUtil.assumeCanTestCameraDisconnect()
+        runBlocking {
+            CameraX.initialize(context, cameraConfig).get(10, TimeUnit.SECONDS)
+        }
+
+        // Clear the device UI and check if there is no dialog or lock screen on the top of the
+        // window before start the test.
+        CoreAppTestUtil.prepareDeviceUI(InstrumentationRegistry.getInstrumentation())
+    }
+
+    @After
+    fun tearDown() {
+        if (cameraXTestActivityRule.activity != null) {
+            cameraXTestActivityRule.finishActivity()
+        }
+
+        if (camera2ActivityRule.activity != null) {
+            camera2ActivityRule.finishActivity()
+        }
+
+        runBlocking {
+            CameraX.shutdown().get(10, TimeUnit.SECONDS)
+        }
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.M) // Known issue, checkout b/147393563.
+    fun testCameraDisconnect() {
+
+        // TODO(b/184603071): Migrate the ActivityTestRule to ActivityScenario
+        // Launch CameraX test activity
+        with(cameraXTestActivityRule.launchActivity(Intent())) {
+
+            // Wait for preview to become active
+            waitForCameraXPreview()
+
+            // Get id of camera opened by CameraX test activity
+            Truth.assertThat(cameraId).isNotNull()
+
+            // Launch Camera2 test activity. It should cause the camera to disconnect from CameraX.
+            val intent = Intent(
+                context,
+                Camera2TestActivity::class.java
+            ).apply {
+                putExtra(Camera2TestActivity.EXTRA_CAMERA_ID, cameraId)
+            }
+            camera2ActivityRule.launchActivity(intent)
+
+            // Wait for preview to become active
+            camera2ActivityRule.activity.waitForCamera2Preview()
+
+            // Close Camera2 test activity, and verify the CameraX Preview resumes successfully.
+            camera2ActivityRule.finishActivity()
+
+            // Verify the CameraX Preview can resume successfully.
+            waitForCameraXPreview()
+        }
+    }
+
+    private fun CameraXTestActivity.waitForCameraXPreview() {
+        waitFor(previewReady)
+    }
+
+    private fun Camera2TestActivity.waitForCamera2Preview() {
+        waitFor(mPreviewReady)
+    }
+
+    private fun waitFor(idlingResource: IdlingResource) {
+        IdlingRegistry.getInstance().register(idlingResource)
+        Espresso.onIdle()
+        IdlingRegistry.getInstance().unregister(idlingResource)
+    }
+}
\ No newline at end of file
diff --git a/car/app/app-activity/src/main/java/androidx/car/app/activity/CarAppActivity.java b/car/app/app-activity/src/main/java/androidx/car/app/activity/CarAppActivity.java
index 3deb43b..7928b66 100644
--- a/car/app/app-activity/src/main/java/androidx/car/app/activity/CarAppActivity.java
+++ b/car/app/app-activity/src/main/java/androidx/car/app/activity/CarAppActivity.java
@@ -216,7 +216,7 @@
                 public void onServiceDisconnected(@NonNull ComponentName name) {
                     onServiceConnectionError(
                             String.format("Host service %s is disconnected", requireNonNull(name)),
-                            ErrorActionType.FINISH);
+                            ErrorActionType.DISCONNECT);
                 }
             };
 
@@ -370,6 +370,11 @@
      * @param errorMessage the error message to be shown in the logs
      */
     void onServiceConnectionError(@Nullable String errorMessage, ErrorActionType type) {
+        if (type == ErrorActionType.DISCONNECT) {
+            Log.d(TAG, "Disconnect by user, don't kill the CarAppActivity");
+            return;
+        }
+
         // Remove the renderer callback since there is no need to communicate the state with
         // the host.
         mActivityLifecycleDelegate.registerRendererCallback(null);
@@ -466,5 +471,8 @@
 
         /** Finish the CarAppActivity */
         FINISH,
+
+        /** Finish the CarAppActivity */
+        DISCONNECT,
     }
 }
diff --git a/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyBenchmark.kt b/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyBenchmark.kt
deleted file mode 100644
index a3ffd44..0000000
--- a/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyBenchmark.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.testutils.benchmark
-
-import androidx.compose.runtime.Composable
-import androidx.compose.testutils.ComposeTestCase
-import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
-import androidx.compose.testutils.benchmark.benchmarkDrawPerf
-import androidx.compose.testutils.benchmark.benchmarkFirstCompose
-import androidx.compose.testutils.benchmark.benchmarkFirstDraw
-import androidx.compose.testutils.benchmark.benchmarkFirstLayout
-import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
-import androidx.test.filters.LargeTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import androidx.test.ext.junit.runners.AndroidJUnit4
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class EmptyBenchmark {
-
-    @get:Rule
-    val benchmarkRule = ComposeBenchmarkRule()
-
-    private val textCaseFactory = { EmptyTestCase() }
-
-    @Test
-    fun first_compose() {
-        benchmarkRule.benchmarkFirstCompose(textCaseFactory)
-    }
-
-    @Test
-    fun first_measure() {
-        benchmarkRule.benchmarkFirstMeasure(textCaseFactory)
-    }
-
-    @Test
-    fun first_layout() {
-        benchmarkRule.benchmarkFirstLayout(textCaseFactory)
-    }
-
-    @Test
-    fun first_draw() {
-        benchmarkRule.benchmarkFirstDraw(textCaseFactory)
-    }
-
-    @Test
-    fun draw() {
-        benchmarkRule.benchmarkDrawPerf(textCaseFactory)
-    }
-}
-
-class EmptyTestCase : ComposeTestCase {
-    @Composable
-    override fun Content() {
-    }
-}
\ No newline at end of file
diff --git a/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyFirstFastBenchmark.kt b/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyFirstFastBenchmark.kt
deleted file mode 100644
index e5b3694..0000000
--- a/compose/benchmark-utils/benchmark/src/androidTest/java/androidx/compose/benchmarkutils/benchmark/EmptyFirstFastBenchmark.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.testutils.benchmark
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.runtime.Composable
-import androidx.compose.testutils.LayeredComposeTestCase
-import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
-import androidx.compose.testutils.benchmark.benchmarkFirstComposeFast
-import androidx.compose.testutils.benchmark.benchmarkFirstDrawFast
-import androidx.compose.testutils.benchmark.benchmarkFirstLayoutFast
-import androidx.compose.testutils.benchmark.benchmarkFirstMeasureFast
-import androidx.test.filters.LargeTest
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import androidx.test.ext.junit.runners.AndroidJUnit4
-
-@LargeTest
-@RunWith(AndroidJUnit4::class)
-class EmptyFirstFastBenchmark {
-
-    @get:Rule
-    val benchmarkRule = ComposeBenchmarkRule()
-
-    private val testCaseFactory = { EmptyLayeredTestCase() }
-
-    @Test
-    fun first_compose() {
-        benchmarkRule.benchmarkFirstComposeFast(testCaseFactory)
-    }
-
-    @Test
-    fun first_measure() {
-        benchmarkRule.benchmarkFirstMeasureFast(testCaseFactory)
-    }
-
-    @Test
-    fun first_layout() {
-        benchmarkRule.benchmarkFirstLayoutFast(testCaseFactory)
-    }
-
-    @Test
-    fun first_draw() {
-        benchmarkRule.benchmarkFirstDrawFast(testCaseFactory)
-    }
-}
-
-class EmptyLayeredTestCase : LayeredComposeTestCase {
-    @Composable
-    override fun MeasuredContent() {}
-
-    @Composable
-    override fun ContentWrappers(content: @Composable () -> Unit) {
-        Box {
-            content()
-        }
-    }
-}
\ No newline at end of file
diff --git a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarkFirstExtensions.kt b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarkFirstExtensions.kt
index 1765fa0..74f1e03 100644
--- a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarkFirstExtensions.kt
+++ b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarkFirstExtensions.kt
@@ -24,6 +24,7 @@
 import androidx.compose.testutils.ComposeTestCase
 import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.assertNoPendingChanges
+import androidx.compose.testutils.benchmark.android.AndroidTestCase
 import androidx.compose.testutils.doFramesUntilNoChangesPending
 import org.junit.Assert.assertTrue
 
@@ -31,7 +32,7 @@
  * Measures the time of the first composition right after the given test case is added to an
  * already existing hierarchy.
  */
-fun ComposeBenchmarkRule.benchmarkFirstComposeFast(caseFactory: () -> LayeredComposeTestCase) {
+fun ComposeBenchmarkRule.benchmarkFirstCompose(caseFactory: () -> LayeredComposeTestCase) {
     runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
         measureRepeated {
             runWithTimingDisabled {
@@ -53,7 +54,7 @@
  * Measures the time of the first measure right after the given test case is added to an already
  * existing hierarchy.
  */
-fun ComposeBenchmarkRule.benchmarkFirstMeasureFast(caseFactory: () -> LayeredComposeTestCase) {
+fun ComposeBenchmarkRule.benchmarkFirstMeasure(caseFactory: () -> LayeredComposeTestCase) {
     runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
         measureRepeated {
             runWithTimingDisabled {
@@ -78,7 +79,7 @@
  * Measures the time of the first layout right after the given test case is added to an already
  * existing hierarchy.
  */
-fun ComposeBenchmarkRule.benchmarkFirstLayoutFast(caseFactory: () -> LayeredComposeTestCase) {
+fun ComposeBenchmarkRule.benchmarkFirstLayout(caseFactory: () -> LayeredComposeTestCase) {
     runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
         measureRepeated {
             runWithTimingDisabled {
@@ -104,7 +105,7 @@
  * Measures the time of the first draw right after the given test case is added to an already
  * existing hierarchy.
  */
-fun ComposeBenchmarkRule.benchmarkFirstDrawFast(caseFactory: () -> LayeredComposeTestCase) {
+fun ComposeBenchmarkRule.benchmarkFirstDraw(caseFactory: () -> LayeredComposeTestCase) {
     runBenchmarkFor(LayeredCaseAdapter.of(caseFactory)) {
         measureRepeated {
             runWithTimingDisabled {
@@ -130,6 +131,85 @@
 }
 
 /**
+ * Measures the time of the first set content of the given Android test case.
+ */
+fun AndroidBenchmarkRule.benchmarkFirstSetContent(caseFactory: () -> AndroidTestCase) {
+    runBenchmarkFor(caseFactory) {
+        measureRepeated {
+            setupContent()
+            runWithTimingDisabled {
+                disposeContent()
+            }
+        }
+    }
+}
+
+/**
+ * Measures the time of the first measure of the given test case.
+ */
+fun AndroidBenchmarkRule.benchmarkFirstMeasure(caseFactory: () -> AndroidTestCase) {
+    runBenchmarkFor(caseFactory) {
+        measureRepeated {
+            runWithTimingDisabled {
+                setupContent()
+                requestLayout()
+            }
+
+            measure()
+
+            runWithTimingDisabled {
+                disposeContent()
+            }
+        }
+    }
+}
+
+/**
+ * Measures the time of the first layout of the given test case.
+ */
+fun AndroidBenchmarkRule.benchmarkFirstLayout(caseFactory: () -> AndroidTestCase) {
+    runBenchmarkFor(caseFactory) {
+        measureRepeated {
+            runWithTimingDisabled {
+                setupContent()
+                requestLayout()
+                measure()
+            }
+
+            layout()
+
+            runWithTimingDisabled {
+                disposeContent()
+            }
+        }
+    }
+}
+
+/**
+ * Measures the time of the first draw of the given test case.
+ */
+fun AndroidBenchmarkRule.benchmarkFirstDraw(caseFactory: () -> AndroidTestCase) {
+    runBenchmarkFor(caseFactory) {
+        measureRepeated {
+            runWithTimingDisabled {
+                setupContent()
+                requestLayout()
+                measure()
+                layout()
+                drawPrepare()
+            }
+
+            draw()
+
+            runWithTimingDisabled {
+                drawFinish()
+                disposeContent()
+            }
+        }
+    }
+}
+
+/**
  * Runs recompositions until there are no changes pending.
  *
  * @param maxAmountOfStep Max amount of recomposition to perform before giving up and throwing
diff --git a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
index c53a78e..ea64883 100644
--- a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
+++ b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
@@ -26,7 +26,6 @@
 import androidx.compose.testutils.benchmark.android.AndroidTestCase
 import androidx.compose.testutils.doFramesUntilNoChangesPending
 import androidx.compose.testutils.recomposeAssertHadChanges
-import androidx.compose.testutils.setupContent
 
 /**
  * Measures measure and layout performance of the given test case by toggling measure constraints.
@@ -146,180 +145,6 @@
 }
 
 /**
- * Measures the time of the first composition of the given compose test case.
- *
- * @param assertNoPendingRecompositions whether the benchmark will fail if there are pending
- * recompositions after the first composition. By default this is true to enforce correctness in
- * the benchmark, but for components that have an initial animation after being composed this can
- * be turned off to benchmark just the first composition without any pending animations.
- */
-fun ComposeBenchmarkRule.benchmarkFirstCompose(
-    caseFactory: () -> ComposeTestCase,
-    assertNoPendingRecompositions: Boolean = true
-) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                createTestCase()
-            }
-
-            emitContent()
-
-            runWithTimingDisabled {
-                if (assertNoPendingRecompositions) {
-                    assertNoPendingChanges()
-                }
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first set content of the given Android test case.
- */
-fun AndroidBenchmarkRule.benchmarkFirstSetContent(caseFactory: () -> AndroidTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            setupContent()
-            runWithTimingDisabled {
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first measure of the given test case.
- */
-fun ComposeBenchmarkRule.benchmarkFirstMeasure(caseFactory: () -> ComposeTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-            }
-
-            measure()
-
-            runWithTimingDisabled {
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first measure of the given test case.
- */
-fun AndroidBenchmarkRule.benchmarkFirstMeasure(caseFactory: () -> AndroidTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-            }
-
-            measure()
-
-            runWithTimingDisabled {
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first layout of the given test case.
- */
-fun ComposeBenchmarkRule.benchmarkFirstLayout(caseFactory: () -> ComposeTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-                measure()
-            }
-
-            layout()
-
-            runWithTimingDisabled {
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first layout of the given test case.
- */
-fun AndroidBenchmarkRule.benchmarkFirstLayout(caseFactory: () -> AndroidTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-                measure()
-            }
-
-            layout()
-
-            runWithTimingDisabled {
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first draw of the given test case.
- */
-fun ComposeBenchmarkRule.benchmarkFirstDraw(caseFactory: () -> ComposeTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-                measure()
-                layout()
-                drawPrepare()
-            }
-
-            draw()
-
-            runWithTimingDisabled {
-                drawFinish()
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
- * Measures the time of the first draw of the given test case.
- */
-fun AndroidBenchmarkRule.benchmarkFirstDraw(caseFactory: () -> AndroidTestCase) {
-    runBenchmarkFor(caseFactory) {
-        measureRepeated {
-            runWithTimingDisabled {
-                setupContent()
-                requestLayout()
-                measure()
-                layout()
-                drawPrepare()
-            }
-
-            draw()
-
-            runWithTimingDisabled {
-                drawFinish()
-                disposeContent()
-            }
-        }
-    }
-}
-
-/**
  *  Measures recomposition time of the hierarchy after changing a state.
  *
  * @param assertOneRecomposition whether the benchmark will fail if there are pending
diff --git a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/NestedBoxesTestCase.kt b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/NestedBoxesTestCase.kt
index 4e5a26b..237f9fb 100644
--- a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/NestedBoxesTestCase.kt
+++ b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/NestedBoxesTestCase.kt
@@ -18,7 +18,7 @@
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 
 /**
  * Test case representing a layout hierarchy of nested boxes.
@@ -26,10 +26,10 @@
 class NestedBoxesTestCase(
     private val depth: Int,
     private val children: Int
-) : ComposeTestCase {
+) : LayeredComposeTestCase {
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         Box {
             Boxes(depth - 1, children)
         }
diff --git a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnSharedModelTestCase.kt b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnSharedModelTestCase.kt
index 34791dd..48fb82f 100644
--- a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnSharedModelTestCase.kt
+++ b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnSharedModelTestCase.kt
@@ -20,10 +20,9 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.size
-import androidx.compose.material.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -38,20 +37,18 @@
  */
 class RectsInColumnSharedModelTestCase(
     private val amountOfRectangles: Int
-) : ComposeTestCase, ToggleableTestCase {
+) : LayeredComposeTestCase, ToggleableTestCase {
 
     private val color = mutableStateOf(Color.Black)
 
     @Composable
-    override fun Content() {
-        MaterialTheme {
-            Column {
-                repeat(amountOfRectangles) { i ->
-                    if (i == 0) {
-                        Box(Modifier.size(100.dp, 50.dp).background(color = color.value))
-                    } else {
-                        Box(Modifier.size(100.dp, 50.dp).background(color = Color.Green))
-                    }
+    override fun MeasuredContent() {
+        Column {
+            repeat(amountOfRectangles) { i ->
+                if (i == 0) {
+                    Box(Modifier.size(100.dp, 50.dp).background(color = color.value))
+                } else {
+                    Box(Modifier.size(100.dp, 50.dp).background(color = Color.Green))
                 }
             }
         }
diff --git a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnTestCase.kt b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnTestCase.kt
index fce4d49..88548cc 100644
--- a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnTestCase.kt
+++ b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInColumnTestCase.kt
@@ -20,13 +20,11 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.size
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -40,19 +38,15 @@
  */
 class RectsInColumnTestCase(
     private val amountOfRectangles: Int
-) : ComposeTestCase, ToggleableTestCase {
+) : LayeredComposeTestCase, ToggleableTestCase {
 
     private val states = mutableListOf<MutableState<Color>>()
 
     @Composable
-    override fun Content() {
-        MaterialTheme {
-            Surface {
-                Column {
-                    repeat(amountOfRectangles) {
-                        ColoredRectWithModel()
-                    }
-                }
+    override fun MeasuredContent() {
+        Column {
+            repeat(amountOfRectangles) {
+                ColoredRectWithModel()
             }
         }
     }
diff --git a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/SpacingBenchmark.kt b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/SpacingBenchmark.kt
index ca00d7b..54c3b2e 100644
--- a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/SpacingBenchmark.kt
+++ b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/SpacingBenchmark.kt
@@ -24,7 +24,7 @@
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkDrawPerf
@@ -158,7 +158,7 @@
     }
 }
 
-private sealed class PaddingTestCase : ComposeTestCase, ToggleableTestCase {
+private sealed class PaddingTestCase : LayeredComposeTestCase, ToggleableTestCase {
 
     var paddingState: MutableState<Dp>? = null
 
@@ -169,7 +169,7 @@
     }
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         val padding = remember { mutableStateOf(5.dp) }
         paddingState = padding
 
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/NestedScrollerTestCase.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/NestedScrollerTestCase.kt
index 2ad14ed..2db5f25 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/NestedScrollerTestCase.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/NestedScrollerTestCase.kt
@@ -28,12 +28,10 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.rememberScrollState
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -45,20 +43,16 @@
 /**
  * Test case that puts many horizontal scrollers in a vertical scroller
  */
-class NestedScrollerTestCase : ComposeTestCase, ToggleableTestCase {
+class NestedScrollerTestCase : LayeredComposeTestCase, ToggleableTestCase {
     // ScrollerPosition must now be constructed during composition to obtain the Density
     private lateinit var scrollState: ScrollState
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         scrollState = rememberScrollState()
-        MaterialTheme {
-            Surface {
-                LazyColumn {
-                    items(5) { index ->
-                        SquareRow(index == 0)
-                    }
-                }
+        LazyColumn {
+            items(5) { index ->
+                SquareRow(index == 0)
             }
         }
     }
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/ScrollerTestCase.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/ScrollerTestCase.kt
index 1a2fcc1..ec48333 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/ScrollerTestCase.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/ScrollerTestCase.kt
@@ -24,7 +24,7 @@
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -34,11 +34,11 @@
 /**
  * Test case that puts a large number of boxes in a column in a vertical scroller to force scrolling.
  */
-class ScrollerTestCase : ComposeTestCase, ToggleableTestCase {
+class ScrollerTestCase : LayeredComposeTestCase, ToggleableTestCase {
     private lateinit var scrollState: ScrollState
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         scrollState = rememberScrollState()
         Column(Modifier.verticalScroll(scrollState)) {
             Column(Modifier.fillMaxHeight()) {
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/SimpleComponentImplementationBenchmark.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/SimpleComponentImplementationBenchmark.kt
index 0e9330f..a23c9cd 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/SimpleComponentImplementationBenchmark.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/SimpleComponentImplementationBenchmark.kt
@@ -28,7 +28,7 @@
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkDrawPerf
@@ -231,7 +231,7 @@
 class ComponentWithModifiersTestCase : SimpleComponentImplementationTestCase() {
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         val innerSize = getInnerSize()
         Box(
             Modifier.size(48.dp)
@@ -249,7 +249,7 @@
 class ComponentWithRedrawTestCase : SimpleComponentImplementationTestCase() {
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         val innerSize = getInnerSize()
         val stroke = Stroke()
         Canvas(Modifier.size(48.dp)) {
@@ -261,7 +261,7 @@
 
 class ComponentWithTwoLayoutNodesTestCase : SimpleComponentImplementationTestCase() {
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         Box(
             modifier = Modifier
                 .size(48.dp)
@@ -280,7 +280,7 @@
     }
 }
 
-abstract class SimpleComponentImplementationTestCase : ComposeTestCase, ToggleableTestCase {
+abstract class SimpleComponentImplementationTestCase : LayeredComposeTestCase, ToggleableTestCase {
 
     private var state: MutableState<Dp>? = null
 
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/TrailingLambdaBenchmark.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/TrailingLambdaBenchmark.kt
index 335d283..f823649 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/TrailingLambdaBenchmark.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/TrailingLambdaBenchmark.kt
@@ -23,7 +23,7 @@
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkFirstCompose
@@ -44,7 +44,7 @@
 
     @Test
     fun withTrailingLambdas_compose() {
-        benchmarkRule.benchmarkFirstCompose({ WithTrailingLambdas() })
+        benchmarkRule.benchmarkFirstCompose { WithTrailingLambdas() }
     }
 
     @Test
@@ -54,7 +54,7 @@
 
     @Test
     fun withoutTrailingLambdas_compose() {
-        benchmarkRule.benchmarkFirstCompose({ WithoutTrailingLambdas() })
+        benchmarkRule.benchmarkFirstCompose { WithoutTrailingLambdas() }
     }
 
     @Test
@@ -63,12 +63,12 @@
     }
 }
 
-private sealed class TrailingLambdaTestCase : ComposeTestCase, ToggleableTestCase {
+private sealed class TrailingLambdaTestCase : LayeredComposeTestCase, ToggleableTestCase {
 
     var numberState: MutableState<Int>? = null
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         val number = remember { mutableStateOf(5) }
         numberState = number
 
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextBasicBenchmark.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextBasicBenchmark.kt
index 6ddf510..f7f3edd 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextBasicBenchmark.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextBasicBenchmark.kt
@@ -18,10 +18,10 @@
 
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkDrawPerf
-import androidx.compose.testutils.benchmark.benchmarkFirstComposeFast
-import androidx.compose.testutils.benchmark.benchmarkFirstDrawFast
-import androidx.compose.testutils.benchmark.benchmarkFirstLayoutFast
-import androidx.compose.testutils.benchmark.benchmarkFirstMeasureFast
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
 import androidx.compose.testutils.benchmark.benchmarkLayoutPerf
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkDraw
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkLayout
@@ -85,7 +85,7 @@
      */
     @Test
     fun first_compose() {
-        benchmarkRule.benchmarkFirstComposeFast(caseFactory)
+        benchmarkRule.benchmarkFirstCompose(caseFactory)
     }
 
     /**
@@ -94,7 +94,7 @@
      */
     @Test
     fun first_measure() {
-        benchmarkRule.benchmarkFirstMeasureFast(caseFactory)
+        benchmarkRule.benchmarkFirstMeasure(caseFactory)
     }
 
     /**
@@ -103,7 +103,7 @@
      */
     @Test
     fun first_layout() {
-        benchmarkRule.benchmarkFirstLayoutFast(caseFactory)
+        benchmarkRule.benchmarkFirstLayout(caseFactory)
     }
 
     /**
@@ -111,7 +111,7 @@
      */
     @Test
     fun first_draw() {
-        benchmarkRule.benchmarkFirstDrawFast(caseFactory)
+        benchmarkRule.benchmarkFirstDraw(caseFactory)
     }
 
     /**
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextFieldToggleTextBenchmark.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextFieldToggleTextBenchmark.kt
index 14f1941..e64f1de 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextFieldToggleTextBenchmark.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/TextFieldToggleTextBenchmark.kt
@@ -18,10 +18,10 @@
 
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkDrawPerf
-import androidx.compose.testutils.benchmark.benchmarkFirstComposeFast
-import androidx.compose.testutils.benchmark.benchmarkFirstDrawFast
-import androidx.compose.testutils.benchmark.benchmarkFirstLayoutFast
-import androidx.compose.testutils.benchmark.benchmarkFirstMeasureFast
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
 import androidx.compose.testutils.benchmark.benchmarkLayoutPerf
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkDraw
 import androidx.compose.testutils.benchmark.toggleStateBenchmarkLayout
@@ -77,7 +77,7 @@
      */
     @Test
     fun first_compose() {
-        benchmarkRule.benchmarkFirstComposeFast(caseFactory)
+        benchmarkRule.benchmarkFirstCompose(caseFactory)
     }
 
     /**
@@ -87,7 +87,7 @@
      */
     @Test
     fun first_measure() {
-        benchmarkRule.benchmarkFirstMeasureFast(caseFactory)
+        benchmarkRule.benchmarkFirstMeasure(caseFactory)
     }
 
     /**
@@ -96,7 +96,7 @@
      */
     @Test
     fun first_layout() {
-        benchmarkRule.benchmarkFirstLayoutFast(caseFactory)
+        benchmarkRule.benchmarkFirstLayout(caseFactory)
     }
 
     /**
@@ -105,7 +105,7 @@
      */
     @Test
     fun first_draw() {
-        benchmarkRule.benchmarkFirstDrawFast(caseFactory)
+        benchmarkRule.benchmarkFirstDraw(caseFactory)
     }
 
     /**
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/selection/SelectionContainerTestCase.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/selection/SelectionContainerTestCase.kt
index e94b226..93caa92 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/selection/SelectionContainerTestCase.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/text/selection/SelectionContainerTestCase.kt
@@ -20,13 +20,13 @@
 import androidx.compose.foundation.text.selection.SelectionContainer
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.sp
 
-class SelectionContainerTestCase(private val childrenCount: Int) : ComposeTestCase {
+class SelectionContainerTestCase(private val childrenCount: Int) : LayeredComposeTestCase {
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
         SelectionContainer {
             Column {
                 repeat(childrenCount) {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
index 0d82ef1..676634a 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/textfield/TextFieldTest.kt
@@ -723,7 +723,7 @@
 
     @Test
     fun textField_stringOverload_callsOnValueChange_whenTextChange() {
-        var onValueChangeCalled: Boolean
+        var onValueChangeCalled = false
 
         rule.setContent {
             val state = remember { mutableStateOf("abc") }
@@ -743,7 +743,9 @@
             .performTextInputSelection(TextRange(0, 0))
 
         // reset
-        onValueChangeCalled = false
+        rule.runOnIdle {
+            onValueChangeCalled = false
+        }
 
         // change selection
         @OptIn(ExperimentalTestApi::class)
@@ -765,7 +767,7 @@
 
     @Test
     fun textField_callsOnValueChange_whenTextFieldValueChange() {
-        var onValueChangeCalled: Boolean
+        var onValueChangeCalled = false
 
         rule.setContent {
             val state = remember { mutableStateOf(TextFieldValue("abc")) }
@@ -785,7 +787,9 @@
             .performTextInputSelection(TextRange(0, 0))
 
         // reset flag since click might change selection
-        onValueChangeCalled = false
+        rule.runOnIdle {
+            onValueChangeCalled = false
+        }
 
         @OptIn(ExperimentalTestApi::class)
         rule.onNodeWithTag(Tag)
@@ -794,11 +798,10 @@
         // selection changed
         rule.runOnIdle {
             assertThat(onValueChangeCalled).isTrue()
+            // reset flag
+            onValueChangeCalled = false
         }
 
-        // reset flag
-        onValueChangeCalled = false
-
         // set selection to same value, no change should occur
         @OptIn(ExperimentalTestApi::class)
         rule.onNodeWithTag(Tag)
diff --git a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsBenchmark.kt b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsBenchmark.kt
index f610771..dec4d18 100644
--- a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsBenchmark.kt
+++ b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsBenchmark.kt
@@ -53,10 +53,7 @@
 
     @Test
     fun first_compose() {
-        benchmarkRule.benchmarkFirstCompose(
-            checkboxCaseFactory,
-            assertNoPendingRecompositions = false
-        )
+        benchmarkRule.benchmarkFirstCompose(checkboxCaseFactory)
     }
 
     @Test
diff --git a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsTestCase.kt b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsTestCase.kt
index 979074bc6..a9526be 100644
--- a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsTestCase.kt
+++ b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/CheckboxesInRowsTestCase.kt
@@ -27,7 +27,7 @@
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -38,24 +38,29 @@
  */
 class CheckboxesInRowsTestCase(
     private val amountOfCheckboxes: Int
-) : ComposeTestCase, ToggleableTestCase {
+) : LayeredComposeTestCase, ToggleableTestCase {
 
     private val states = mutableListOf<MutableState<Boolean>>()
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
+        Column {
+            repeat(amountOfCheckboxes) {
+                Row {
+                    Text(text = "Check Me!")
+                    CheckboxWithState(
+                        Modifier.weight(1f).wrapContentSize(Alignment.CenterEnd)
+                    )
+                }
+            }
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: () -> Unit) {
         MaterialTheme {
             Surface {
-                Column {
-                    repeat(amountOfCheckboxes) {
-                        Row {
-                            Text(text = "Check Me!")
-                            CheckboxWithState(
-                                Modifier.weight(1f).wrapContentSize(Alignment.CenterEnd)
-                            )
-                        }
-                    }
-                }
+                content()
             }
         }
     }
diff --git a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/RadioGroupBenchmark.kt b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/RadioGroupBenchmark.kt
index 4a33072..e6fed73 100644
--- a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/RadioGroupBenchmark.kt
+++ b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/RadioGroupBenchmark.kt
@@ -24,7 +24,7 @@
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
 import androidx.compose.testutils.benchmark.benchmarkFirstCompose
@@ -57,7 +57,7 @@
 
     @Test
     fun first_compose() {
-        benchmarkRule.benchmarkFirstCompose(radioCaseFactory, assertNoPendingRecompositions = false)
+        benchmarkRule.benchmarkFirstCompose(radioCaseFactory)
     }
 
     @Test
@@ -99,7 +99,7 @@
     }
 }
 
-internal class RadioGroupTestCase : ComposeTestCase, ToggleableTestCase {
+internal class RadioGroupTestCase : LayeredComposeTestCase, ToggleableTestCase {
 
     private val radiosCount = 10
     private val options = (0 until radiosCount).toList()
@@ -110,25 +110,30 @@
     }
 
     @Composable
-    override fun Content() {
-        MaterialTheme {
-            Column {
-                options.forEach { item ->
-                    Row(
-                        modifier = Modifier.selectable(
-                            selected = (select.value == item),
-                            onClick = { select.value = item }
-                        ),
-                        verticalAlignment = Alignment.CenterVertically
-                    ) {
-                        Text(item.toString())
-                        RadioButton(
-                            selected = (select.value == item),
-                            onClick = { select.value = item }
-                        )
-                    }
+    override fun MeasuredContent() {
+        Column {
+            options.forEach { item ->
+                Row(
+                    modifier = Modifier.selectable(
+                        selected = (select.value == item),
+                        onClick = { select.value = item }
+                    ),
+                    verticalAlignment = Alignment.CenterVertically
+                ) {
+                    Text(item.toString())
+                    RadioButton(
+                        selected = (select.value == item),
+                        onClick = { select.value = item }
+                    )
                 }
             }
         }
     }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
 }
\ No newline at end of file
diff --git a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/TextInColumnSizeToggleTestCase.kt b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/TextInColumnSizeToggleTestCase.kt
index 339de17..270df6f 100644
--- a/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/TextInColumnSizeToggleTestCase.kt
+++ b/compose/material/material/benchmark/src/androidTest/java/androidx/compose/material/benchmark/TextInColumnSizeToggleTestCase.kt
@@ -22,7 +22,7 @@
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.mutableStateOf
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.testutils.ToggleableTestCase
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.sp
@@ -35,23 +35,28 @@
  */
 class TextInColumnSizeToggleTestCase(
     private val numberOfTexts: Int
-) : ComposeTestCase, ToggleableTestCase {
+) : LayeredComposeTestCase, ToggleableTestCase {
 
     private val fontSize = mutableStateOf(20.sp)
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
+        Column {
+            repeat(numberOfTexts) {
+                // 32-character text to match dashboards
+                Text(
+                    "Hello World Hello World Hello W",
+                    style = TextStyle(fontSize = fontSize.value)
+                )
+            }
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
         MaterialTheme {
             Surface {
-                Column {
-                    repeat(numberOfTexts) {
-                        // 32-character text to match dashboards
-                        Text(
-                            "Hello World Hello World Hello W",
-                            style = TextStyle(fontSize = fontSize.value)
-                        )
-                    }
-                }
+                content()
             }
         }
     }
diff --git a/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/ComposeTestCase.kt b/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/ComposeTestCase.kt
index ed01647..f45d284 100644
--- a/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/ComposeTestCase.kt
+++ b/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/ComposeTestCase.kt
@@ -71,5 +71,7 @@
      * The lifecycle rules for this method are same as for [Content]
      */
     @Composable
-    fun ContentWrappers(content: @Composable () -> Unit)
+    fun ContentWrappers(content: @Composable () -> Unit) {
+        content()
+    }
 }
\ No newline at end of file
diff --git a/compose/ui/ui-graphics/benchmark/src/main/java/androidx/compose/ui/graphics/benchmark/ImageVectorTestCase.kt b/compose/ui/ui-graphics/benchmark/src/main/java/androidx/compose/ui/graphics/benchmark/ImageVectorTestCase.kt
index e7e5175..5b89155 100644
--- a/compose/ui/ui-graphics/benchmark/src/main/java/androidx/compose/ui/graphics/benchmark/ImageVectorTestCase.kt
+++ b/compose/ui/ui-graphics/benchmark/src/main/java/androidx/compose/ui/graphics/benchmark/ImageVectorTestCase.kt
@@ -29,7 +29,7 @@
 import androidx.compose.ui.graphics.vector.PathData
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.foundation.layout.size
-import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.LayeredComposeTestCase
 import androidx.compose.ui.graphics.vector.rememberVectorPainter
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.unit.dp
@@ -40,16 +40,21 @@
  * Subclasses are responsible for providing the vector asset, so we can test and benchmark different
  * methods of loading / creating this asset.
  */
-sealed class ImageVectorTestCase : ComposeTestCase {
+sealed class ImageVectorTestCase : LayeredComposeTestCase {
 
     @Composable
-    override fun Content() {
+    override fun MeasuredContent() {
+        Box(
+            Modifier.testTag(testTag)
+                .size(24.dp)
+                .paint(getPainter())
+        )
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
         Box {
-            Box(
-                Modifier.testTag(testTag)
-                    .size(24.dp)
-                    .paint(getPainter())
-            )
+            content()
         }
     }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/SetRootFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/SetRootFocusTest.kt
index 45e7cb0..07efd25 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/SetRootFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/SetRootFocusTest.kt
@@ -26,10 +26,12 @@
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import org.junit.Ignore
+import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit.SECONDS
 
 @LargeTest
 @RunWith(AndroidJUnit4::class)
@@ -40,11 +42,11 @@
     private val focusable = "Focusable"
     private val nonFocusable = "NotFocusable"
 
-    @Ignore("Flaky test. b/178470869")
     @Test
     fun clearFocus_byClickingOutsideFocusableComponent() {
         // Arrange.
         var isFocused = false
+        var focusChanged = CountDownLatch(1)
         rule.setContent {
             Column {
                 // TODO(b/163725615): Remove this after clickable is made focusable.
@@ -55,7 +57,10 @@
                         .testTag(focusable)
                         .clickable { focusRequester.requestFocus() }
                         .focusRequester(focusRequester)
-                        .onFocusChanged { isFocused = it.isFocused }
+                        .onFocusChanged {
+                            isFocused = it.isFocused
+                            focusChanged.countDown()
+                        }
                         .focusModifier()
                 )
                 BasicText(
@@ -65,12 +70,21 @@
             }
         }
         rule.onNodeWithTag(focusable).performClick()
-        rule.waitUntil(5_000) { isFocused == true }
+        rule.waitForIdle()
+        focusChanged.await(10, SECONDS)
+        rule.runOnIdle {
+            assertThat(isFocused).isTrue()
+            focusChanged = CountDownLatch(1)
+        }
 
         // Act.
         rule.onNodeWithTag(nonFocusable).performClick()
 
         // Assert.
-        rule.waitUntil(5_000) { isFocused == false }
+        rule.waitForIdle()
+        focusChanged.await(10, SECONDS)
+        rule.runOnIdle {
+            assertThat(isFocused).isFalse()
+        }
     }
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
index 73ff3df..0573699 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidDialog.android.kt
@@ -59,7 +59,7 @@
 /**
  * Properties used to customize the behavior of a [Dialog].
  *
- * @property dismissOnClickOutside whether the dialog can be dismissed by pressing the back button.
+ * @property dismissOnBackPress whether the dialog can be dismissed by pressing the back button.
  * If true, pressing the back button will call onDismissRequest.
  * @property dismissOnClickOutside whether the dialog can be dismissed by clicking outside the
  * dialog's bounds. If true, clicking outside the dialog will call onDismissRequest.
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index bbc9aac..39b2a25 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -136,7 +136,7 @@
     docs("androidx.lifecycle:lifecycle-runtime-testing:2.4.0-alpha01")
     docs("androidx.lifecycle:lifecycle-service:2.4.0-alpha01")
     docs("androidx.lifecycle:lifecycle-viewmodel:2.4.0-alpha01")
-    docs("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha03")
+    docs("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha04")
     docs("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0-alpha01")
     docs("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.4.0-alpha01")
     docs("androidx.loader:loader:1.1.0")
diff --git a/navigation/navigation-dynamic-features-fragment/build.gradle b/navigation/navigation-dynamic-features-fragment/build.gradle
index 818faab..ccf402b 100644
--- a/navigation/navigation-dynamic-features-fragment/build.gradle
+++ b/navigation/navigation-dynamic-features-fragment/build.gradle
@@ -28,7 +28,7 @@
 
 dependencies {
     api(project(":navigation:navigation-dynamic-features-runtime"))
-    api(project(":navigation:navigation-fragment-ktx"))
+    api(project(":navigation:navigation-fragment"))
     api(KOTLIN_STDLIB)
 
     testImplementation(ANDROIDX_TEST_CORE)
diff --git a/navigation/navigation-dynamic-features-runtime/build.gradle b/navigation/navigation-dynamic-features-runtime/build.gradle
index fdda131..3853ed4 100644
--- a/navigation/navigation-dynamic-features-runtime/build.gradle
+++ b/navigation/navigation-dynamic-features-runtime/build.gradle
@@ -27,7 +27,7 @@
 }
 
 dependencies {
-    api(project(":navigation:navigation-runtime-ktx"))
+    api(project(":navigation:navigation-runtime"))
     api(PLAY_CORE)
     api(KOTLIN_STDLIB)
 
diff --git a/navigation/navigation-fragment/build.gradle b/navigation/navigation-fragment/build.gradle
index cb93aa6..2c03dad 100644
--- a/navigation/navigation-fragment/build.gradle
+++ b/navigation/navigation-fragment/build.gradle
@@ -28,7 +28,7 @@
 
 dependencies {
     api(projectOrArtifact(":fragment:fragment-ktx"))
-    api(project(":navigation:navigation-runtime-ktx"))
+    api(project(":navigation:navigation-runtime"))
 
     api(KOTLIN_STDLIB)
     androidTestImplementation(projectOrArtifact(":fragment:fragment-testing"))
diff --git a/navigation/navigation-runtime/build.gradle b/navigation/navigation-runtime/build.gradle
index 19a91d6..92ad242 100644
--- a/navigation/navigation-runtime/build.gradle
+++ b/navigation/navigation-runtime/build.gradle
@@ -28,7 +28,7 @@
 }
 
 dependencies {
-    api(project(":navigation:navigation-common-ktx"))
+    api(project(":navigation:navigation-common"))
     api("androidx.activity:activity-ktx:1.2.2")
     api("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
     api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
diff --git a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.java b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.java
index 714516f..c85fea6 100644
--- a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.java
+++ b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.java
@@ -42,9 +42,11 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.Px;
 import androidx.core.content.ContextCompat;
+import androidx.core.graphics.Insets;
 import androidx.core.util.Consumer;
 import androidx.core.view.AccessibilityDelegateCompat;
 import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.customview.view.AbsSavedState;
 import androidx.customview.widget.Openable;
@@ -111,6 +113,18 @@
             "androidx.slidingpanelayout.widget.SlidingPaneLayout";
 
     /**
+     * This field is only used to support the setter and getter. It is not used by
+     * SlidingPaneLayout.
+     */
+    private int mSliderFadeColor = 0;
+
+    /**
+     * This field is only used to support the setter and getter. It is not used by
+     * SlidingPaneLayout.
+     */
+    private int mCoveredFadeColor;
+
+    /**
      * Drawable used to draw the shadow between panes by default.
      */
     private Drawable mShadowDrawableLeft;
@@ -212,6 +226,8 @@
 
     FoldingFeature mFoldingFeature;
 
+    private static boolean sEdgeSizeUsingSystemGestureInsets = Build.VERSION.SDK_INT >= 29;
+
     /**
      * Set the lock mode that controls how the user can swipe between the panes.
      */
@@ -347,6 +363,7 @@
      */
     @Deprecated
     public void setSliderFadeColor(@ColorInt int color) {
+        mSliderFadeColor = color;
     }
 
     /**
@@ -357,7 +374,7 @@
     @Deprecated
     @ColorInt
     public int getSliderFadeColor() {
-        return 0;
+        return mSliderFadeColor;
     }
 
     /**
@@ -369,6 +386,7 @@
      */
     @Deprecated
     public void setCoveredFadeColor(@ColorInt int color) {
+        mCoveredFadeColor = color;
     }
 
     /**
@@ -379,7 +397,7 @@
     @Deprecated
     @ColorInt
     public int getCoveredFadeColor() {
-        return 0;
+        return mCoveredFadeColor;
     }
 
     /**
@@ -1106,8 +1124,20 @@
         final boolean enableEdgeLeftTracking = isLayoutRtl ^ isOpen();
         if (enableEdgeLeftTracking) {
             mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
+            Insets gestureInsets = getSystemGestureInsets();
+            if (gestureInsets != null) {
+                // Gesture insets will be 0 if the device doesn't have gesture navigation enabled.
+                mDragHelper.setEdgeSize(Math.max(mDragHelper.getDefaultEdgeSize(),
+                        gestureInsets.left));
+            }
         } else {
             mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
+            Insets gestureInsets = getSystemGestureInsets();
+            if (gestureInsets != null) {
+                // Gesture insets will be 0 if the device doesn't have gesture navigation enabled.
+                mDragHelper.setEdgeSize(Math.max(mDragHelper.getDefaultEdgeSize(),
+                        gestureInsets.right));
+            }
         }
         final LayoutParams lp = (LayoutParams) child.getLayoutParams();
         boolean result;
@@ -1131,6 +1161,18 @@
         return result;
     }
 
+    // Get system gesture insets when SDK version is larger than 29. Otherwise, return null.
+    private Insets getSystemGestureInsets() {
+        Insets gestureInsets = null;
+        if (sEdgeSizeUsingSystemGestureInsets) {
+            WindowInsetsCompat rootInsetsCompat = ViewCompat.getRootWindowInsets(this);
+            if (rootInsetsCompat != null) {
+                gestureInsets = rootInsetsCompat.getSystemGestureInsets();
+            }
+        }
+        return gestureInsets;
+    }
+
     private Method mGetDisplayList;
     private Field mRecreateDisplayList;
     private boolean mDisplayListReflectionLoaded;