Merge changes from topic "room-runtime-paging-kotlinify" into androidx-main

* changes:
  Converting `paging` related files in `room-runtime` from Java to Kotlin.
  Initial code check-in for renaming `paging` related files in `room-runtime` from *.java to *.kt.
diff --git a/annotation/annotation-experimental-lint/integration-tests/lint-baseline.xml b/annotation/annotation-experimental-lint/integration-tests/lint-baseline.xml
index ff3d158..f99cc28 100644
--- a/annotation/annotation-experimental-lint/integration-tests/lint-baseline.xml
+++ b/annotation/annotation-experimental-lint/integration-tests/lint-baseline.xml
@@ -444,6 +444,61 @@
     <issue
         id="UnsafeOptInUsageError"
         message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        AnnotatedJavaMembers().field = -1"
+        errorLine2="                               ~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalFromKt.kt"
+            line="144"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        AnnotatedJavaMembers().field = -1"
+        errorLine2="                                       ~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalFromKt.kt"
+            line="144"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        val value = AnnotatedJavaMembers().field"
+        errorLine2="                                           ~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalFromKt.kt"
+            line="145"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        AnnotatedJavaMembers().fieldWithSetMarker = -1"
+        errorLine2="                               ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalFromKt.kt"
+            line="146"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        AnnotatedJavaMembers().fieldWithSetMarker = -1"
+        errorLine2="                                                    ~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalFromKt.kt"
+            line="146"
+            column="53"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
         errorLine1="        return stableObject.field;"
         errorLine2="                            ~~~~~">
         <location
@@ -487,6 +542,50 @@
 
     <issue
         id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        new AnnotatedJavaMembers().field = -1;"
+        errorLine2="                                   ~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java"
+            line="59"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        new AnnotatedJavaMembers().field = -1;"
+        errorLine2="                                           ~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java"
+            line="59"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        int value = new AnnotatedJavaMembers().field;"
+        errorLine2="                                               ~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java"
+            line="60"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class)`"
+        errorLine1="        new AnnotatedJavaMembers().setFieldWithSetMarker(-1);"
+        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java"
+            line="61"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="UnsafeOptInUsageError"
         message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalJavaAnnotation2` or `@OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation2.class)`"
         errorLine1="        AnnotatedJavaClass2 experimentalObject2 = new AnnotatedJavaClass2();"
         errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -804,4 +903,15 @@
             column="38"/>
     </issue>
 
+    <issue
+        id="UnsafeOptInUsageError"
+        message="This declaration is opt-in and its usage should be marked with `@sample.optin.ExperimentalKotlinAnnotation` or `@OptIn(markerClass = sample.optin.ExperimentalKotlinAnnotation.class)`"
+        errorLine1="        new AnnotatedKotlinMembers().setFieldWithSetMarker(-1);"
+        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/sample/optin/UseKtExperimentalFromJava.java"
+            line="117"
+            column="38"/>
+    </issue>
+
 </issues>
diff --git a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedJavaMembers.java b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedJavaMembers.java
index 406cb9f..82955e3 100644
--- a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedJavaMembers.java
+++ b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedJavaMembers.java
@@ -23,16 +23,27 @@
     @ExperimentalJavaAnnotation
     public static final int FIELD_STATIC = -1;
 
+    private int mFieldWithSetMarker;
+
     @ExperimentalJavaAnnotation
     public static int methodStatic() {
         return -1;
     }
 
     @ExperimentalJavaAnnotation
-    public final int field = -1;
+    public int field = -1;
 
     @ExperimentalJavaAnnotation
     public int method() {
         return -1;
     }
+
+    public int getFieldWithSetMarker() {
+        return mFieldWithSetMarker;
+    }
+
+    @ExperimentalJavaAnnotation
+    public void setFieldWithSetMarker(int value) {
+        mFieldWithSetMarker = value;
+    }
 }
diff --git a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedKotlinMembers.kt b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedKotlinMembers.kt
index 79a309e..275b2e0 100644
--- a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedKotlinMembers.kt
+++ b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/AnnotatedKotlinMembers.kt
@@ -18,7 +18,10 @@
 
 open class AnnotatedKotlinMembers {
     @ExperimentalKotlinAnnotation
-    val field: Int = -1
+    var field: Int = -1
+
+    @set:ExperimentalKotlinAnnotation
+    var fieldWithSetMarker: Int = -1
 
     @ExperimentalKotlinAnnotation
     fun method(): Int {
diff --git a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalFromKt.kt b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalFromKt.kt
index af88dc8..a13ae32 100644
--- a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalFromKt.kt
+++ b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalFromKt.kt
@@ -136,4 +136,15 @@
         val experimentalObject = AnnotatedJavaClass()
         return experimentalObject.method() + AnnotatedJavaClass2.FIELD_STATIC
     }
+
+    /**
+     * Unsafe references to experimental properties.
+     */
+    fun unsafePropertyUsage(): Int {
+        AnnotatedJavaMembers().field = -1
+        val value = AnnotatedJavaMembers().field
+        AnnotatedJavaMembers().fieldWithSetMarker = -1
+        val value2 = AnnotatedJavaMembers().fieldWithSetMarker // safe
+        return value + value2
+    }
 }
diff --git a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java
index 1aa316e..3366f72 100644
--- a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java
+++ b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseJavaExperimentalMembersFromJava.java
@@ -51,4 +51,14 @@
     int unsafeExperimentalStaticMethod() {
         return AnnotatedJavaMembers.methodStatic();
     }
+
+    /**
+     * Unsafe references to experimental properties.
+     */
+    void unsafePropertyUsage() {
+        new AnnotatedJavaMembers().field = -1;
+        int value = new AnnotatedJavaMembers().field;
+        new AnnotatedJavaMembers().setFieldWithSetMarker(-1);
+        int value2 = new AnnotatedJavaMembers().getFieldWithSetMarker(); // safe
+    }
 }
diff --git a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseKtExperimentalFromJava.java b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseKtExperimentalFromJava.java
index ec165d9..5b68a82 100644
--- a/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseKtExperimentalFromJava.java
+++ b/annotation/annotation-experimental-lint/integration-tests/src/main/java/sample/optin/UseKtExperimentalFromJava.java
@@ -109,6 +109,16 @@
     }
 
     /**
+     * Unsafe references to experimental properties.
+     */
+    void unsafePropertyUsage() {
+        new AnnotatedKotlinMembers().setField(-1);
+        int value = new AnnotatedKotlinMembers().getField();
+        new AnnotatedKotlinMembers().setFieldWithSetMarker(-1);
+        int value2 = new AnnotatedKotlinMembers().getFieldWithSetMarker(); // safe
+    }
+
+    /**
      * Safe usage due to opting in to experimental annotation.
      */
     @OptIn(markerClass = ExperimentalKotlinAnnotation.class)
diff --git a/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt b/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
index c618fc3..2bcefd3 100644
--- a/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
+++ b/annotation/annotation-experimental-lint/src/test/kotlin/androidx/annotation/experimental/lint/RequiresOptInDetectorTest.kt
@@ -66,7 +66,19 @@
 src/sample/optin/UseJavaExperimentalMembersFromJava.java:52: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
         return AnnotatedJavaMembers.methodStatic();
                                     ~~~~~~~~~~~~
-4 errors, 0 warnings
+src/sample/optin/UseJavaExperimentalMembersFromJava.java:59: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        new AnnotatedJavaMembers().field = -1;
+                                   ~~~~~
+src/sample/optin/UseJavaExperimentalMembersFromJava.java:59: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        new AnnotatedJavaMembers().field = -1;
+                                           ~~
+src/sample/optin/UseJavaExperimentalMembersFromJava.java:60: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        int value = new AnnotatedJavaMembers().field;
+                                               ~~~~~
+src/sample/optin/UseJavaExperimentalMembersFromJava.java:61: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        new AnnotatedJavaMembers().setFieldWithSetMarker(-1);
+                                   ~~~~~~~~~~~~~~~~~~~~~
+8 errors, 0 warnings
         """.trimIndent()
         /* ktlint-enable max-line-length */
 
@@ -179,7 +191,22 @@
 src/sample/optin/UseJavaExperimentalFromKt.kt:108: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation2 or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation2.class) [UnsafeOptInUsageError]
         return experimentalObject.method() + AnnotatedJavaClass2.FIELD_STATIC
                                                                  ~~~~~~~~~~~~
-11 errors, 0 warnings
+src/sample/optin/UseJavaExperimentalFromKt.kt:144: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        AnnotatedJavaMembers().field = -1
+                               ~~~~~
+src/sample/optin/UseJavaExperimentalFromKt.kt:144: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        AnnotatedJavaMembers().field = -1
+                                       ~~
+src/sample/optin/UseJavaExperimentalFromKt.kt:145: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        val value = AnnotatedJavaMembers().field
+                                           ~~~~~
+src/sample/optin/UseJavaExperimentalFromKt.kt:146: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        AnnotatedJavaMembers().fieldWithSetMarker = -1
+                               ~~~~~~~~~~~~~~~~~~
+src/sample/optin/UseJavaExperimentalFromKt.kt:146: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
+        AnnotatedJavaMembers().fieldWithSetMarker = -1
+                                                    ~~
+16 errors, 0 warnings
         """.trimIndent()
         /* ktlint-enable max-line-length */
 
@@ -198,6 +225,7 @@
             javaSample("sample.optin.UseKtExperimentalFromJava")
         )
 
+        // TODO(b/210881073): Access to annotated property `field` is still not detected.
         /* ktlint-disable max-line-length */
         val expected = """
 src/sample/optin/UseKtExperimentalFromJava.java:28: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalKotlinAnnotation or @OptIn(markerClass = sample.optin.ExperimentalKotlinAnnotation.class) [UnsafeOptInUsageError]
@@ -221,7 +249,10 @@
 src/sample/optin/UseKtExperimentalFromJava.java:108: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalJavaAnnotation or @OptIn(markerClass = sample.optin.ExperimentalJavaAnnotation.class) [UnsafeOptInUsageError]
         new AnnotatedKotlinMembers().methodWithJavaMarker();
                                      ~~~~~~~~~~~~~~~~~~~~
-7 errors, 0 warnings
+src/sample/optin/UseKtExperimentalFromJava.java:117: Error: This declaration is opt-in and its usage should be marked with @sample.optin.ExperimentalKotlinAnnotation or @OptIn(markerClass = sample.optin.ExperimentalKotlinAnnotation.class) [UnsafeOptInUsageError]
+        new AnnotatedKotlinMembers().setFieldWithSetMarker(-1);
+                                     ~~~~~~~~~~~~~~~~~~~~~
+8 errors, 0 warnings
         """.trimIndent()
         /* ktlint-enable max-line-length */
 
diff --git a/camera/camera-camera2/api/public_plus_experimental_1.1.0-beta02.txt b/camera/camera-camera2/api/public_plus_experimental_1.1.0-beta02.txt
index 583ba10..5c763c6 100644
--- a/camera/camera-camera2/api/public_plus_experimental_1.1.0-beta02.txt
+++ b/camera/camera-camera2/api/public_plus_experimental_1.1.0-beta02.txt
@@ -30,6 +30,7 @@
     ctor public Camera2Interop.Extender(androidx.camera.core.ExtendableBuilder<T!>);
     method public <ValueT> androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setDeviceStateCallback(android.hardware.camera2.CameraDevice.StateCallback);
+    method @RequiresApi(28) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setPhysicalCameraId(String);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionCaptureCallback(android.hardware.camera2.CameraCaptureSession.CaptureCallback);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionStateCallback(android.hardware.camera2.CameraCaptureSession.StateCallback);
   }
diff --git a/camera/camera-camera2/api/public_plus_experimental_current.txt b/camera/camera-camera2/api/public_plus_experimental_current.txt
index 583ba10..5c763c6 100644
--- a/camera/camera-camera2/api/public_plus_experimental_current.txt
+++ b/camera/camera-camera2/api/public_plus_experimental_current.txt
@@ -30,6 +30,7 @@
     ctor public Camera2Interop.Extender(androidx.camera.core.ExtendableBuilder<T!>);
     method public <ValueT> androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setCaptureRequestOption(android.hardware.camera2.CaptureRequest.Key<ValueT!>, ValueT);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setDeviceStateCallback(android.hardware.camera2.CameraDevice.StateCallback);
+    method @RequiresApi(28) public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setPhysicalCameraId(String);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionCaptureCallback(android.hardware.camera2.CameraCaptureSession.CaptureCallback);
     method public androidx.camera.camera2.interop.Camera2Interop.Extender<T!> setSessionStateCallback(android.hardware.camera2.CameraCaptureSession.StateCallback);
   }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
index 064b0a5..1381745 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
@@ -311,6 +311,8 @@
                         OutputConfigurationCompat outputConfiguration =
                                 new OutputConfigurationCompat(surface);
                         // Set the desired physical camera ID, or null to use the logical stream.
+                        // TODO(b/219414502): Configure different streams with different physical
+                        //  camera IDs.
                         outputConfiguration.setPhysicalCameraId(
                                 camera2Config.getPhysicalCameraId(null));
                         outputConfigList.add(outputConfiguration);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2Interop.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2Interop.java
index 25df968..c5d82ed 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2Interop.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/interop/Camera2Interop.java
@@ -190,15 +190,13 @@
          * <p>On API &lt;= 27, the physical camera ID will be ignored since logical camera is not
          * supported on these API levels.
          *
-         * <p>If use cases with different physical camera IDs are bound at the same time, an
+         * <p>Currently it doesn't support binding use cases with different physical camera IDs. If
+         * use cases with different physical camera IDs are bound at the same time, an
          * {@link IllegalArgumentException} will be thrown.
          *
          * @param cameraId The desired camera ID.
          * @return The current Extender.
-         *
-         * @hide
          */
-        @RestrictTo(Scope.LIBRARY)
         @RequiresApi(28)
         @NonNull
         public Extender<T> setPhysicalCameraId(@NonNull String cameraId) {
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/DeferrableSurfacesTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/DeferrableSurfacesTest.java
index a83af98..013a6ea 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/DeferrableSurfacesTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/DeferrableSurfacesTest.java
@@ -25,9 +25,11 @@
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.concurrent.futures.ResolvableFuture;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SdkSuppress;
@@ -99,6 +101,28 @@
     }
 
     @Test
+    public void surfaceListWithTimeout_cancelReturnedFutureWontCancelDeferrableSurfaces() {
+        DeferrableSurface deferrableSurface = new DeferrableSurface() {
+            private final ListenableFuture<Surface> mSurfaceFuture = ResolvableFuture.create();
+            @NonNull
+            @Override
+            protected ListenableFuture<Surface> provideSurface() {
+                // Return a never complete future.
+                return mSurfaceFuture;
+            }
+        };
+        List<DeferrableSurface> surfaces = Arrays.asList(deferrableSurface);
+        ListenableFuture<List<Surface>> listenableFuture =
+                DeferrableSurfaces.surfaceListWithTimeout(surfaces, false,
+                        /*timeout=*/Long.MAX_VALUE, CameraXExecutors.directExecutor(),
+                        mScheduledExecutorService);
+
+        listenableFuture.cancel(true);
+
+        assertThat(deferrableSurface.getSurface().isCancelled()).isFalse();
+    }
+
+    @Test
     public void tryIncrementAll_canIncrementAllCounts() {
         DeferrableSurface fakeSurface0 = getFakeDeferrableSurface();
         DeferrableSurface fakeSurface1 = getFakeDeferrableSurface();
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
index 6e4789c..aa31954 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
@@ -63,7 +63,8 @@
         List<ListenableFuture<Surface>> listenableFutureSurfaces = new ArrayList<>();
 
         for (DeferrableSurface deferrableSurface : deferrableSurfaces) {
-            listenableFutureSurfaces.add(deferrableSurface.getSurface());
+            listenableFutureSurfaces.add(
+                    Futures.nonCancellationPropagating(deferrableSurface.getSurface()));
         }
 
         return CallbackToFutureAdapter.getFuture(
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
index 52a95ad..1d007fb 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/MediaCodecInfoReportIncorrectInfoQuirk.java
@@ -43,6 +43,7 @@
  * See b/192431846#comment3.
  *
  * <p>Motc C, X650 and LG-X230 have the same problem as Nokia 1. See b/199582287</p>
+ * <p>Positivo Twist 2 Pro have the same problem as Nokia 1. See b/218841498</p>
  *
  * <p>On Huawei Mate9, {@link CamcorderProfile} indicates it can support resolutions 3840x2160 for
  *  video codec type {@link android.media.MediaRecorder.VideoEncoder#HEVC}, but the current video
@@ -57,7 +58,8 @@
 public class MediaCodecInfoReportIncorrectInfoQuirk implements Quirk {
 
     static boolean load() {
-        return isNokia1() || isMotoC() || isX650() || isX230() || isHuaweiMate9();
+        return isNokia1() || isMotoC() || isX650() || isX230() || isHuaweiMate9()
+                || isPositivoTwist2Pro();
     }
 
     private static boolean isNokia1() {
@@ -81,9 +83,14 @@
         return "Huawei".equalsIgnoreCase(Build.BRAND) && "mha-l29".equalsIgnoreCase(Build.MODEL);
     }
 
+    private static boolean isPositivoTwist2Pro() {
+        return "positivo".equalsIgnoreCase(Build.BRAND) && "twist 2 pro".equalsIgnoreCase(
+                Build.MODEL);
+    }
+
     /** Check if problematic MediaFormat info for these candidate devices. */
     public boolean isUnSupportMediaCodecInfo(@NonNull MediaFormat mediaFormat) {
-        if (isNokia1() || isMotoC() || isX650() || isX230()) {
+        if (isNokia1() || isMotoC() || isX650() || isX230() || isPositivoTwist2Pro()) {
             /** Checks if the given mime type is a problematic mime type. */
             String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
             return MediaFormat.MIMETYPE_VIDEO_MPEG4.equals(mimeType);
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirk.java b/camera/camera-view/src/main/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirk.java
index b5995b9..c9dbc5d 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirk.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirk.java
@@ -34,13 +34,21 @@
     private static final String SAMSUNG = "SAMSUNG";
     private static final String GALAXY_Z_FOLD_2 = "F2Q";
     private static final String GALAXY_Z_FOLD_3 = "Q2Q";
+    private static final String OPPO = "OPPO";
+    private static final String OPPO_FIND_N = "OP4E75L1";
 
     static boolean load() {
-        return SAMSUNG.equalsIgnoreCase(Build.MANUFACTURER) && isFold2OrFold3();
+        return isSamsungFold2OrFold3() || isOppoFoldable();
     }
 
-    static boolean isFold2OrFold3() {
-        return GALAXY_Z_FOLD_2.equalsIgnoreCase(Build.DEVICE)
-                || GALAXY_Z_FOLD_3.equalsIgnoreCase(Build.DEVICE);
+    private static boolean isSamsungFold2OrFold3() {
+        return SAMSUNG.equalsIgnoreCase(Build.MANUFACTURER)
+                && (GALAXY_Z_FOLD_2.equalsIgnoreCase(Build.DEVICE)
+                || GALAXY_Z_FOLD_3.equalsIgnoreCase(Build.DEVICE));
+    }
+
+    private static boolean isOppoFoldable() {
+        return OPPO.equalsIgnoreCase(Build.MANUFACTURER)
+                && OPPO_FIND_N.equalsIgnoreCase(Build.DEVICE);
     }
 }
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirkTest.java b/camera/camera-view/src/test/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirkTest.java
index 97467b2..f653c37 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirkTest.java
+++ b/camera/camera-view/src/test/java/androidx/camera/view/internal/compat/quirk/SurfaceViewStretchedQuirkTest.java
@@ -37,18 +37,23 @@
 
     @Test
     public void quirkExistsOnSamsungGalaxyZFold2() {
-        quirkExistsOnDevice("f2q");
+        quirkExistsOnDevice("Samsung", "f2q");
     }
 
     @Test
     public void quirkExistsOnSamsungGalaxyZFold3() {
-        quirkExistsOnDevice("q2q");
+        quirkExistsOnDevice("Samsung", "q2q");
     }
 
-    public void quirkExistsOnDevice(String device) {
+    @Test
+    public void quirkExistsOnOppoFindN() {
+        quirkExistsOnDevice("Oppo", "OP4E75L1");
+    }
+
+    public void quirkExistsOnDevice(String manufacturer, String device) {
         // Arrange.
         ReflectionHelpers.setStaticField(Build.class, "DEVICE", device);
-        ReflectionHelpers.setStaticField(Build.class, "MANUFACTURER", "SAMSUNG");
+        ReflectionHelpers.setStaticField(Build.class, "MANUFACTURER", manufacturer);
 
         // Act.
         final SurfaceViewStretchedQuirk quirk = DeviceQuirks.get(SurfaceViewStretchedQuirk.class);
diff --git a/car/app/app/src/main/AndroidManifest.xml b/car/app/app/src/main/AndroidManifest.xml
index f621a9b..978d3dc 100644
--- a/car/app/app/src/main/AndroidManifest.xml
+++ b/car/app/app/src/main/AndroidManifest.xml
@@ -16,6 +16,7 @@
   limitations under the License.
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     package="androidx.car.app">
     <application>
         <activity
@@ -25,6 +26,9 @@
         <receiver android:name=".notification.CarAppNotificationBroadcastReceiver" />
     </application>
     <queries>
-        <provider android:authorities="androidx.car.app.connection" />
+        <provider
+            android:name="androidx.car.app.connection.provider"
+            android:authorities="androidx.car.app.connection"
+            tools:ignore="MissingClass" />
     </queries>
 </manifest>
\ No newline at end of file
diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt
index 9f1eed7..691783f 100644
--- a/compose/foundation/foundation-layout/api/current.txt
+++ b/compose/foundation/foundation-layout/api/current.txt
@@ -223,6 +223,7 @@
     method public static androidx.compose.foundation.layout.WindowInsets add(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Composable public static androidx.compose.foundation.layout.PaddingValues asPaddingValues(androidx.compose.foundation.layout.WindowInsets);
     method public static androidx.compose.foundation.layout.WindowInsets exclude(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
+    method public static androidx.compose.foundation.layout.WindowInsets only(androidx.compose.foundation.layout.WindowInsets, int sides);
     method public static androidx.compose.foundation.layout.WindowInsets union(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
   }
 
@@ -245,6 +246,30 @@
     method public static androidx.compose.ui.Modifier waterfallPadding(androidx.compose.ui.Modifier);
   }
 
+  @kotlin.jvm.JvmInline public final value class WindowInsetsSides {
+    method public operator int plus(int sides);
+    field public static final androidx.compose.foundation.layout.WindowInsetsSides.Companion Companion;
+  }
+
+  public static final class WindowInsetsSides.Companion {
+    method public int getBottom();
+    method public int getEnd();
+    method public int getHorizontal();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public int getTop();
+    method public int getVertical();
+    property public final int Bottom;
+    property public final int End;
+    property public final int Horizontal;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+    property public final int Top;
+    property public final int Vertical;
+  }
+
   public final class WindowInsetsSizeKt {
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsBottomHeight(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsEndWidth(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
diff --git a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
index ea81a4f..f2c39f2 100644
--- a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
@@ -226,6 +226,7 @@
     method public static androidx.compose.foundation.layout.WindowInsets add(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Composable public static androidx.compose.foundation.layout.PaddingValues asPaddingValues(androidx.compose.foundation.layout.WindowInsets);
     method public static androidx.compose.foundation.layout.WindowInsets exclude(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
+    method public static androidx.compose.foundation.layout.WindowInsets only(androidx.compose.foundation.layout.WindowInsets, int sides);
     method public static androidx.compose.foundation.layout.WindowInsets union(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
   }
 
@@ -250,6 +251,30 @@
     method public static androidx.compose.ui.Modifier waterfallPadding(androidx.compose.ui.Modifier);
   }
 
+  @kotlin.jvm.JvmInline public final value class WindowInsetsSides {
+    method public operator int plus(int sides);
+    field public static final androidx.compose.foundation.layout.WindowInsetsSides.Companion Companion;
+  }
+
+  public static final class WindowInsetsSides.Companion {
+    method public int getBottom();
+    method public int getEnd();
+    method public int getHorizontal();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public int getTop();
+    method public int getVertical();
+    property public final int Bottom;
+    property public final int End;
+    property public final int Horizontal;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+    property public final int Top;
+    property public final int Vertical;
+  }
+
   public final class WindowInsetsSizeKt {
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsBottomHeight(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsEndWidth(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt
index 2fccf29..c31ede2 100644
--- a/compose/foundation/foundation-layout/api/restricted_current.txt
+++ b/compose/foundation/foundation-layout/api/restricted_current.txt
@@ -228,6 +228,7 @@
     method public static androidx.compose.foundation.layout.WindowInsets add(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Composable public static androidx.compose.foundation.layout.PaddingValues asPaddingValues(androidx.compose.foundation.layout.WindowInsets);
     method public static androidx.compose.foundation.layout.WindowInsets exclude(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
+    method public static androidx.compose.foundation.layout.WindowInsets only(androidx.compose.foundation.layout.WindowInsets, int sides);
     method public static androidx.compose.foundation.layout.WindowInsets union(androidx.compose.foundation.layout.WindowInsets, androidx.compose.foundation.layout.WindowInsets insets);
   }
 
@@ -250,6 +251,30 @@
     method public static androidx.compose.ui.Modifier waterfallPadding(androidx.compose.ui.Modifier);
   }
 
+  @kotlin.jvm.JvmInline public final value class WindowInsetsSides {
+    method public operator int plus(int sides);
+    field public static final androidx.compose.foundation.layout.WindowInsetsSides.Companion Companion;
+  }
+
+  public static final class WindowInsetsSides.Companion {
+    method public int getBottom();
+    method public int getEnd();
+    method public int getHorizontal();
+    method public int getLeft();
+    method public int getRight();
+    method public int getStart();
+    method public int getTop();
+    method public int getVertical();
+    property public final int Bottom;
+    property public final int End;
+    property public final int Horizontal;
+    property public final int Left;
+    property public final int Right;
+    property public final int Start;
+    property public final int Top;
+    property public final int Vertical;
+  }
+
   public final class WindowInsetsSizeKt {
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsBottomHeight(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier windowInsetsEndWidth(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.WindowInsets insets);
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index be6e5ed..c92c558 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -46,6 +46,7 @@
         testImplementation(libs.testRules)
         testImplementation(libs.testRunner)
         testImplementation(libs.junit)
+        testImplementation(libs.truth)
 
         androidTestImplementation(project(":compose:foundation:foundation"))
         androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.0.0")
@@ -103,6 +104,7 @@
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
                 implementation(libs.junit)
+                implementation(libs.truth)
             }
 
             androidAndroidTest.dependencies {
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/WindowInsets.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/WindowInsets.kt
index 627e0f5..a1ce2ec 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/WindowInsets.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/WindowInsets.kt
@@ -66,6 +66,97 @@
 }
 
 /**
+ * [WindowInsetsSides] is used in [WindowInsets.only] to define which sides of the
+ * [WindowInsets] should apply.
+ */
+@kotlin.jvm.JvmInline
+value class WindowInsetsSides private constructor(private val value: Int) {
+    /**
+     * Returns a [WindowInsetsSides] containing sides defied in [sides] and the
+     * sides in `this`.
+     */
+    operator fun plus(sides: WindowInsetsSides): WindowInsetsSides =
+        WindowInsetsSides(value or sides.value)
+
+    internal fun hasAny(sides: WindowInsetsSides): Boolean =
+        (value and sides.value) != 0
+
+    companion object {
+        //    _---- allowLeft  in ltr
+        //    /
+        //    | _--- allowRight in ltr
+        //    |/
+        //    || _-- allowLeft  in rtl
+        //    ||/
+        //    ||| _- allowRight in rtl
+        //    |||/
+        //    VVVV
+        //    Mask   = ----
+        //
+        //    Left   = 1010
+        //    Right  = 0101
+        //    Start  = 1001
+        //    End    = 0110
+
+        internal val AllowLeftInLtr = WindowInsetsSides(1 shl 3)
+        internal val AllowRightInLtr = WindowInsetsSides(1 shl 2)
+        internal val AllowLeftInRtl = WindowInsetsSides(1 shl 1)
+        internal val AllowRightInRtl = WindowInsetsSides(1 shl 0)
+
+        /**
+         * Indicates a [WindowInsets] start side, which is left or right
+         * depending on [LayoutDirection]. If [LayoutDirection.Ltr], [Start]
+         * is the left side. If [LayoutDirection.Rtl], [Start] is the right side.
+         *
+         * Use [Left] or [Right] if the physical direction is required.
+         */
+        val Start = AllowLeftInLtr + AllowRightInRtl
+
+        /**
+         * Indicates a [WindowInsets] end side, which is left or right
+         * depending on [LayoutDirection]. If [LayoutDirection.Ltr], [End]
+         * is the right side. If [LayoutDirection.Rtl], [End] is the left side.
+         *
+         * Use [Left] or [Right] if the physical direction is required.
+         */
+        val End = AllowRightInLtr + AllowLeftInRtl
+
+        /**
+         * Indicates a [WindowInsets] top side.
+         */
+        val Top = WindowInsetsSides(1 shl 4)
+
+        /**
+         * Indicates a [WindowInsets] bottom side.
+         */
+        val Bottom = WindowInsetsSides(1 shl 5)
+
+        /**
+         * Indicates a [WindowInsets] left side. Most layouts will prefer using
+         * [Start] or [End] to account for [LayoutDirection].
+         */
+        val Left = AllowLeftInLtr + AllowLeftInRtl
+
+        /**
+         * Indicates a [WindowInsets] right side. Most layouts will prefer using
+         * [Start] or [End] to account for [LayoutDirection].
+         */
+        val Right = AllowRightInLtr + AllowRightInRtl
+
+        /**
+         * Indicates a [WindowInsets] horizontal sides. This is a combination of
+         * [Left] and [Right] sides, or [Start] and [End] sides.
+         */
+        val Horizontal = Left + Right
+
+        /**
+         * Indicates a [WindowInsets] [Top] and [Bottom] sides.
+         */
+        val Vertical = Top + Bottom
+    }
+}
+
+/**
  * Returns an [WindowInsets] that has the maximum values of this [WindowInsets] and [insets].
  */
 fun WindowInsets.union(insets: WindowInsets): WindowInsets = UnionInsets(this, insets)
@@ -83,13 +174,20 @@
 fun WindowInsets.exclude(insets: WindowInsets): WindowInsets = ExcludeInsets(this, insets)
 
 /**
- * Returns the an [WindowInsets] that has values of this, added to the values of [insets].
+ * Returns a [WindowInsets] that has values of this, added to the values of [insets].
  * For example, if this has a top of 10 and insets has a top of 5, the returned [WindowInsets]
  * will have a top of 15.
  */
 fun WindowInsets.add(insets: WindowInsets): WindowInsets = AddedInsets(this, insets)
 
 /**
+ * Returns a [WindowInsets] that eliminates all dimensions except the ones that are enabled.
+ * For example, to have a [WindowInsets] at the bottom of the screen, pass
+ * [WindowInsetsSides.Bottom].
+ */
+fun WindowInsets.only(sides: WindowInsetsSides): WindowInsets = LimitInsets(this, sides)
+
+/**
  * Convert an [WindowInsets] to a [PaddingValues] and uses [LocalDensity] for DP to pixel conversion.
  * [PaddingValues] can be passed to some containers to pad internal content so that it doesn't
  * overlap the insets when fully scrolled. Ensure that the insets are [consumed][consumedWindowInsets]
@@ -415,6 +513,63 @@
 }
 
 @Stable
+private class LimitInsets(
+    val insets: WindowInsets,
+    val sides: WindowInsetsSides
+) : WindowInsets {
+    override fun getLeft(density: Density, layoutDirection: LayoutDirection): Int {
+        val layoutDirectionSide = if (layoutDirection == LayoutDirection.Ltr) {
+            WindowInsetsSides.AllowLeftInLtr
+        } else {
+            WindowInsetsSides.AllowLeftInRtl
+        }
+        val allowLeft = sides.hasAny(layoutDirectionSide)
+        return if (allowLeft) {
+            insets.getLeft(density, layoutDirection)
+        } else {
+            0
+        }
+    }
+
+    override fun getTop(density: Density): Int =
+        if (sides.hasAny(WindowInsetsSides.Top)) insets.getTop(density) else 0
+
+    override fun getRight(density: Density, layoutDirection: LayoutDirection): Int {
+        val layoutDirectionSide = if (layoutDirection == LayoutDirection.Ltr) {
+            WindowInsetsSides.AllowRightInLtr
+        } else {
+            WindowInsetsSides.AllowRightInRtl
+        }
+        val allowRight = sides.hasAny(layoutDirectionSide)
+        return if (allowRight) {
+            insets.getRight(density, layoutDirection)
+        } else {
+            0
+        }
+    }
+
+    override fun getBottom(density: Density): Int =
+        if (sides.hasAny(WindowInsetsSides.Bottom)) insets.getBottom(density) else 0
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) {
+            return true
+        }
+        if (other !is LimitInsets) {
+            return false
+        }
+        return insets == other.insets &&
+            sides == other.sides
+    }
+
+    override fun hashCode(): Int {
+        var result = insets.hashCode()
+        result = 31 * result + sides.hashCode()
+        return result
+    }
+}
+
+@Stable
 private class InsetsPaddingValues(
     val insets: WindowInsets,
     private val density: Density
diff --git a/compose/foundation/foundation-layout/src/test/kotlin/androidx/compose/foundation/layout/WindowInsetsTest.kt b/compose/foundation/foundation-layout/src/test/kotlin/androidx/compose/foundation/layout/WindowInsetsTest.kt
new file mode 100644
index 0000000..a06bf1d
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/test/kotlin/androidx/compose/foundation/layout/WindowInsetsTest.kt
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text
+
+import androidx.compose.foundation.layout.InsetsValues
+import androidx.compose.foundation.layout.ValueInsets
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.exclude
+import androidx.compose.foundation.layout.only
+import androidx.compose.foundation.layout.union
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class WindowInsetsTest {
+    private val density = Density(density = 1f)
+    private val doubleDensity = Density(density = 2f)
+
+    @Test
+    fun valueInsets() {
+        val insetsValues = InsetsValues(10, 11, 12, 13)
+        val insets = ValueInsets(insetsValues, "hello")
+
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+
+        assertThat(insets.getLeft(doubleDensity, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+    }
+
+    @Test
+    fun fixedIntInsets() {
+        val insets = WindowInsets(10, 11, 12, 13)
+
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+
+        assertThat(insets.getLeft(doubleDensity, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+    }
+
+    @Test
+    fun fixedDpInsets() {
+        val insets = WindowInsets(10.dp, 11.dp, 12.dp, 13.dp)
+
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+
+        assertThat(insets.getLeft(doubleDensity, LayoutDirection.Ltr)).isEqualTo(20)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+    }
+
+    @Test
+    fun union() {
+        val first = WindowInsets(10, 11, 12, 13)
+        val second = WindowInsets(5, 20, 14, 2)
+        val union = first.union(second)
+        assertThat(union.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(union.getTop(density)).isEqualTo(20)
+        assertThat(union.getRight(density, LayoutDirection.Ltr)).isEqualTo(14)
+        assertThat(union.getBottom(density)).isEqualTo(13)
+    }
+
+    @Test
+    fun exclude() {
+        val first = WindowInsets(10, 11, 12, 13)
+        val second = WindowInsets(5, 20, 14, 2)
+        val exclude = first.exclude(second)
+        assertThat(exclude.getLeft(density, LayoutDirection.Ltr)).isEqualTo(5)
+        assertThat(exclude.getTop(density)).isEqualTo(0)
+        assertThat(exclude.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(exclude.getBottom(density)).isEqualTo(11)
+    }
+
+    @Test
+    fun add() {
+        val first = WindowInsets(10, 11, 12, 13)
+        val second = WindowInsets(5, 20, 14, 2)
+        val add = first.add(second)
+        assertThat(add.getLeft(density, LayoutDirection.Ltr)).isEqualTo(15)
+        assertThat(add.getTop(density)).isEqualTo(31)
+        assertThat(add.getRight(density, LayoutDirection.Ltr)).isEqualTo(26)
+        assertThat(add.getBottom(density)).isEqualTo(15)
+    }
+
+    @Test
+    fun onlyStart() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Start)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Rtl)).isEqualTo(12)
+    }
+
+    @Test
+    fun onlyTop() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Top)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+    }
+
+    @Test
+    fun onlyEnd() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.End)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+        assertThat(insets.getRight(density, LayoutDirection.Rtl)).isEqualTo(0)
+    }
+
+    @Test
+    fun onlyBottom() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Bottom)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+    }
+
+    @Test
+    fun onlyLeft() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Left)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+        assertThat(insets.getRight(density, LayoutDirection.Rtl)).isEqualTo(0)
+    }
+
+    @Test
+    fun onlyRight() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Right)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Rtl)).isEqualTo(12)
+    }
+
+    @Test
+    fun onlyHorizontal() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Horizontal)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(0)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(0)
+        assertThat(insets.getLeft(density, LayoutDirection.Rtl)).isEqualTo(10)
+        assertThat(insets.getRight(density, LayoutDirection.Rtl)).isEqualTo(12)
+    }
+
+    @Test
+    fun onlyVertical() {
+        val insets = WindowInsets(10, 11, 12, 13).only(WindowInsetsSides.Vertical)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(0)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+    }
+
+    @Test
+    fun plus() {
+        val insets = WindowInsets(10, 11, 12, 13)
+            .only(WindowInsetsSides.Vertical + WindowInsetsSides.Horizontal)
+        assertThat(insets.getLeft(density, LayoutDirection.Ltr)).isEqualTo(10)
+        assertThat(insets.getTop(density)).isEqualTo(11)
+        assertThat(insets.getRight(density, LayoutDirection.Ltr)).isEqualTo(12)
+        assertThat(insets.getBottom(density)).isEqualTo(13)
+    }
+}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeText.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeText.kt
index c0e7425..217fdd6 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeText.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeText.kt
@@ -16,17 +16,32 @@
 
 package androidx.compose.foundation.demos.text
 
+import androidx.compose.animation.animateColor
+import androidx.compose.animation.core.RepeatMode
+import androidx.compose.animation.core.infiniteRepeatable
+import androidx.compose.animation.core.rememberInfiniteTransition
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.text.InlineTextContent
+import androidx.compose.foundation.text.appendInlineContent
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.text.Placeholder
+import androidx.compose.ui.text.PlaceholderVerticalAlign
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.buildAnnotatedString
@@ -51,6 +66,7 @@
 import androidx.compose.ui.text.samples.TextStyleSample
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.em
 import androidx.compose.ui.unit.sp
 
@@ -138,6 +154,10 @@
             TagLine(tag = "textOverflow: Clip, Ellipsis, Visible")
             TextDemoTextOverflow()
         }
+        item {
+            TagLine(tag = "inline content")
+            TextDemoInlineContent()
+        }
     }
 }
 
@@ -539,4 +559,69 @@
     TextOverflowVisibleFixedSizeSample()
     SecondTagLine(tag = "overflow = TextOverflow.Visible with fixed width and min height")
     TextOverflowVisibleMinHeightSample()
+}
+
+@Composable
+fun TextDemoInlineContent() {
+    val inlineContentId = "box"
+    val inlineTextContent = InlineTextContent(
+        placeholder = Placeholder(
+            width = 5.em,
+            height = 1.em,
+            placeholderVerticalAlign = PlaceholderVerticalAlign.AboveBaseline
+        )
+    ) {
+        val colorAnimation = rememberInfiniteTransition()
+        val color by colorAnimation.animateColor(
+            initialValue = Color.Red,
+            targetValue = Color.Blue,
+            animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse)
+        )
+        Box(modifier = Modifier.fillMaxSize().background(color))
+    }
+
+    Text(
+        text = buildAnnotatedString {
+            append("Here is a wide inline composable ")
+            appendInlineContent(inlineContentId)
+            append(" that is repeatedly changing its color.")
+        },
+        inlineContent = mapOf(inlineContentId to inlineTextContent),
+        modifier = Modifier.fillMaxWidth()
+    )
+
+    SecondTagLine(tag = "RTL Layout")
+    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+        Text(
+            text = buildAnnotatedString {
+                append("Here is a wide inline composable ")
+                appendInlineContent(inlineContentId)
+                append(" that is repeatedly changing its color.")
+            },
+            inlineContent = mapOf(inlineContentId to inlineTextContent),
+            modifier = Modifier.fillMaxWidth()
+        )
+    }
+
+    SecondTagLine(tag = "Bidi Text - LTR/RTL")
+    Text(
+        text = buildAnnotatedString {
+            append("$displayText   ")
+            appendInlineContent(inlineContentId)
+            append("$displayTextArabic   ")
+        },
+        inlineContent = mapOf(inlineContentId to inlineTextContent),
+        modifier = Modifier.fillMaxWidth()
+    )
+
+    SecondTagLine(tag = "Bidi Text - RTL/LTR")
+    Text(
+        text = buildAnnotatedString {
+            append("$displayTextArabic   ")
+            appendInlineContent(inlineContentId)
+            append("$displayText   ")
+        },
+        inlineContent = mapOf(inlineContentId to inlineTextContent),
+        modifier = Modifier.fillMaxWidth()
+    )
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridTest.kt
index f65a3ce..17e6f3b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.lazy.grid
 
+import android.os.Build
 import androidx.compose.foundation.AutoTestFrameClock
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.gestures.scrollBy
@@ -42,8 +43,13 @@
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertPixels
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.testTag
@@ -58,12 +64,15 @@
 import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertWidthIsAtLeast
+import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.zIndex
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth
 import kotlinx.coroutines.runBlocking
 import org.junit.Rule
@@ -857,6 +866,26 @@
     }
 
     @Test
+    fun passingNegativeItemsCountIsNotAllowed() {
+        var exception: Exception? = null
+        rule.setContentWithTestViewConfiguration {
+            LazyVerticalGrid(GridCells.Fixed(1)) {
+                try {
+                    items(-1) {
+                        Box(Modifier)
+                    }
+                } catch (e: Exception) {
+                    exception = e
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            Truth.assertThat(exception).isInstanceOf(IllegalArgumentException::class.java)
+        }
+    }
+
+    @Test
     fun recomposingWithNewComposedModifierObjectIsNotCausingRemeasure() {
         var remeasureCount = 0
         val layoutModifier = Modifier.layout { measurable, constraints ->
@@ -925,4 +954,34 @@
             Truth.assertThat(recomposeCount).isEqualTo(1)
         }
     }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun zIndexOnItemAffectsDrawingOrder() {
+        rule.setContentWithTestViewConfiguration {
+            LazyVerticalGrid(
+                GridCells.Fixed(1),
+                Modifier.size(6.dp).testTag(LazyGridTag)
+            ) {
+                items(listOf(Color.Blue, Color.Green, Color.Red)) { color ->
+                    Box(
+                        Modifier
+                            .height(2.dp)
+                            .width(6.dp)
+                            .zIndex(if (color == Color.Green) 1f else 0f)
+                            .drawBehind {
+                                drawRect(
+                                    color,
+                                    topLeft = Offset(-10.dp.toPx(), -10.dp.toPx()),
+                                    size = Size(20.dp.toPx(), 20.dp.toPx())
+                                )
+                            })
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyGridTag)
+            .captureToImage()
+            .assertPixels { Color.Green }
+    }
 }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
index 6192186..d16186e 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
@@ -42,11 +42,13 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.testutils.WithTouchSlop
+import androidx.compose.testutils.assertPixels
 import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.layout.layout
@@ -75,6 +77,7 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.zIndex
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import com.google.common.collect.Range
@@ -1684,6 +1687,26 @@
     }
 
     @Test
+    fun passingNegativeItemsCountIsNotAllowed() {
+        var exception: Exception? = null
+        rule.setContentWithTestViewConfiguration {
+            LazyColumnOrRow {
+                try {
+                    items(-1) {
+                        Box(Modifier)
+                    }
+                } catch (e: Exception) {
+                    exception = e
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(exception).isInstanceOf(IllegalArgumentException::class.java)
+        }
+    }
+
+    @Test
     fun scrollingALotDoesntCauseLazyLayoutRecomposition() {
         var recomposeCount = 0
         lateinit var state: LazyListState
@@ -1716,6 +1739,35 @@
         }
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun zIndexOnItemAffectsDrawingOrder() {
+        rule.setContentWithTestViewConfiguration {
+            LazyColumnOrRow(
+                Modifier.size(6.dp).testTag(LazyListTag)
+            ) {
+                items(listOf(Color.Blue, Color.Green, Color.Red)) { color ->
+                    Box(
+                        Modifier
+                            .mainAxisSize(2.dp)
+                            .crossAxisSize(6.dp)
+                            .zIndex(if (color == Color.Green) 1f else 0f)
+                            .drawBehind {
+                                drawRect(
+                                    color,
+                                    topLeft = Offset(-10.dp.toPx(), -10.dp.toPx()),
+                                    size = Size(20.dp.toPx(), 20.dp.toPx())
+                                )
+                            })
+                }
+            }
+        }
+
+        rule.onNodeWithTag(LazyListTag)
+            .captureToImage()
+            .assertPixels { Color.Green }
+    }
+
     // ********************* END OF TESTS *********************
     // Helper functions, etc. live below here
 
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextInlineContentTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextInlineContentTest.kt
index 0604e3e..38f29ed 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextInlineContentTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/CoreTextInlineContentTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -25,17 +26,23 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.text.Placeholder
 import androidx.compose.ui.text.PlaceholderVerticalAlign
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextDirection
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.sp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.verify
 import org.junit.Rule
@@ -49,6 +56,10 @@
     @get:Rule
     val rule = createComposeRule()
 
+    private val fontSize = 10
+
+    private val textStyle = TextStyle(fontSize = fontSize.sp, fontFamily = TEST_FONT_FAMILY)
+
     @Test
     fun placeholder_changeSize_updateInlineContentSize() {
         // Callback to monitor the size changes of a composable.
@@ -94,4 +105,131 @@
         // Verify that the size has been updated to (100, 100).
         verify(onSizeChanged).invoke(IntSize(100, 100))
     }
+
+    @Test
+    fun rtlLayout_inlineContent_placement() {
+        rule.setContent {
+            CompositionLocalProvider(
+                LocalLayoutDirection provides LayoutDirection.Ltr,
+            ) {
+                // LTR character, supported by sample_font
+                TestContent(
+                    predicate = "\u0061\u0061\u0061\u0061\u0061",
+                    suffix = "\u0061\u0061\u0061"
+                )
+            }
+        }
+
+        // Expected text layout; "a" is LTR, "b" is RTL"
+        // Text[aaaaa[inline-content]aaa]
+        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
+    }
+
+    @Test
+    fun rtlTextContent_inlineContent_placement() {
+        rule.setContent {
+            // RTL character, supported by sample_font
+            TestContent(
+                predicate = "\u05D1\u05D1\u05D1\u05D1\u05D1",
+                suffix = "\u05D1\u05D1\u05D1"
+            )
+        }
+
+        // Expected text layout; "a" is LTR, "b" is RTL"
+        // Text[bbb[inline-content]bbbbb]
+        expectInlineContentPosition(left = fontSize * 3, right = fontSize * 5)
+    }
+
+    @Test
+    fun rtlTextDirection_inlineContent_placement() {
+        rule.setContent {
+            // LTR character, supported by sample_font
+            TestContent(
+                predicate = "\u0061\u0061\u0061\u0061\u0061",
+                suffix = "\u0061\u0061\u0061",
+                textStyle = textStyle.copy(textDirection = TextDirection.Rtl)
+            )
+        }
+
+        // Expected text layout; "a" is LTR, "b" is RTL"
+        // Text[aaaaa[inline-content]aaa]
+        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
+    }
+
+    @Test
+    fun bidiText_inlineContent_placement() {
+        rule.setContent {
+            // RTL and LTR characters, supported by sample_font
+            TestContent(
+                predicate = "\u05D1\u05D1\u05D1\u0061\u0061",
+                suffix = "\u0061\u0061\u0061"
+            )
+        }
+
+        // Expected text layout; "a" is LTR, "b" is RTL"
+        // Text[bbbaa[inline-content]aaa]
+        expectInlineContentPosition(left = fontSize * 5, right = fontSize * 3)
+    }
+
+    @Test
+    fun bidiText_2_inlineContent_placement() {
+        rule.setContent {
+            // RTL and LTR characters, supported by sample_font
+            TestContent(
+                predicate = "\u0061\u0061\u0061\u05D1\u05D1",
+                suffix = "\u05D1\u05D1\u05D1"
+            )
+        }
+
+        // Expected text layout; "a" is LTR, "b" is RTL"
+        // Text[aaabbb[inline-content]bb]
+        expectInlineContentPosition(left = fontSize * 6, right = fontSize * 2)
+    }
+
+    @Composable
+    private fun TestContent(
+        predicate: String,
+        suffix: String,
+        textStyle: TextStyle = this.textStyle
+    ) {
+        CompositionLocalProvider(
+            LocalDensity provides Density(density = 1f, fontScale = 1f)
+        ) {
+            val inlineTextContent = InlineTextContent(
+                placeholder = Placeholder(
+                    fontSize.sp,
+                    fontSize.sp,
+                    PlaceholderVerticalAlign.AboveBaseline
+                )
+            ) {
+                Box(modifier = Modifier.fillMaxSize().testTag("box"))
+            }
+
+            BasicText(
+                text = buildAnnotatedString {
+                    append(predicate)
+                    appendInlineContent("box")
+                    append(suffix)
+                },
+                modifier = Modifier.testTag("text"),
+                style = textStyle,
+                inlineContent = mapOf("box" to inlineTextContent),
+                maxLines = 1
+            )
+        }
+    }
+
+    private fun expectInlineContentPosition(left: Int, right: Int) {
+        val (boxLeft, boxRight) = with(rule.onNodeWithTag("box").fetchSemanticsNode()) {
+            Pair(positionInRoot.x, positionInRoot.x + size.width)
+        }
+        val (textLeft, textRight) = with(rule.onNodeWithTag("text").fetchSemanticsNode()) {
+            Pair(positionInRoot.x, positionInRoot.x + size.width)
+        }
+
+        rule.waitForIdle()
+
+        assertThat(boxLeft - textLeft).isEqualTo(left)
+        assertThat(textRight - boxRight).isEqualTo(right)
+    }
 }
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/IntervalList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/IntervalList.kt
index 27d591e..505ec96 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/IntervalList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/IntervalList.kt
@@ -20,7 +20,12 @@
     val startIndex: Int,
     val size: Int,
     val content: T
-)
+) {
+    init {
+        require(startIndex >= 0) { "startIndex should be non-negative but was $startIndex" }
+        require(size > 0) { "size should be positive but was $size" }
+    }
+}
 
 internal interface IntervalList<T> {
     val intervals: List<IntervalHolder<T>>
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
index 5aadf90..1ba93dd 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/CoreText.kt
@@ -360,8 +360,8 @@
                     LastBaseline to layoutResult.lastBaseline.roundToInt()
                 )
             ) {
-                placeables.fastForEach { placeable ->
-                    placeable.first.placeRelative(placeable.second)
+                placeables.fastForEach { (placeable, position) ->
+                    placeable.place(position)
                 }
             }
         }
diff --git a/compose/integration-tests/material-catalog/build.gradle b/compose/integration-tests/material-catalog/build.gradle
index 65d3a75..feb57b5 100644
--- a/compose/integration-tests/material-catalog/build.gradle
+++ b/compose/integration-tests/material-catalog/build.gradle
@@ -45,6 +45,7 @@
     kotlinPlugin project(":compose:compiler:compiler")
     implementation(libs.kotlinStdlib)
     implementation project(":compose:runtime:runtime")
+    implementation project(":compose:foundation:foundation-layout")
     implementation project(":compose:ui:ui")
     implementation project(":compose:material:material")
     implementation project(":compose:material3:material3")
@@ -58,7 +59,6 @@
     // but it doesn't work in androidx.
     // See aosp/1804059
     implementation projectOrArtifact(":lifecycle:lifecycle-common-java8")
-    implementation "com.google.accompanist:accompanist-insets:0.18.0"
 }
 
 // We want to publish a release APK of this project for the Compose Material Catalog
diff --git a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/CatalogApp.kt b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/CatalogApp.kt
index 9f0ae0f..f776c70 100644
--- a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/CatalogApp.kt
+++ b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/CatalogApp.kt
@@ -18,13 +18,10 @@
 
 import androidx.compose.material.catalog.ui.theme.CatalogTheme
 import androidx.compose.runtime.Composable
-import com.google.accompanist.insets.ProvideWindowInsets
 
 @Composable
 fun CatalogApp() {
-    ProvideWindowInsets {
-        CatalogTheme {
-            NavGraph()
-        }
+    CatalogTheme {
+        NavGraph()
     }
 }
diff --git a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/Specification.kt b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/Specification.kt
index 49dbb09..86be2ef 100644
--- a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/Specification.kt
+++ b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/Specification.kt
@@ -17,10 +17,15 @@
 package androidx.compose.material.catalog.ui.specification
 
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.layout.BoxWithConstraints
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.asPaddingValues
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.material.catalog.R
@@ -31,8 +36,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 @OptIn(ExperimentalFoundationApi::class)
@@ -43,32 +46,35 @@
     SpecificationScaffold(
         topBarTitle = stringResource(id = R.string.compose_material_catalog)
     ) { paddingValues ->
-        BoxWithConstraints(modifier = Modifier.padding(paddingValues)) {
-            LazyColumn(
-                content = {
-                    item {
-                        Text(
-                            text = stringResource(id = R.string.specifications),
-                            style = MaterialTheme.typography.bodyLarge
-                        )
-                        Spacer(modifier = Modifier.height(SpecificationPadding))
-                    }
-                    items(specifications) { specification ->
-                        SpecificationItem(
-                            specification = specification,
-                            onClick = onSpecificationClick
-                        )
-                        Spacer(modifier = Modifier.height(SpecificationItemPadding))
-                    }
-                },
-                contentPadding = rememberInsetsPaddingValues(
-                    insets = LocalWindowInsets.current.navigationBars,
-                    additionalTop = SpecificationPadding,
-                    additionalStart = SpecificationPadding,
-                    additionalEnd = SpecificationPadding
+        LazyColumn(
+            content = {
+                item {
+                    Text(
+                        text = stringResource(id = R.string.specifications),
+                        style = MaterialTheme.typography.bodyLarge
+                    )
+                    Spacer(modifier = Modifier.height(SpecificationPadding))
+                }
+                items(specifications) { specification ->
+                    SpecificationItem(
+                        specification = specification,
+                        onClick = onSpecificationClick
+                    )
+                    Spacer(modifier = Modifier.height(SpecificationItemPadding))
+                }
+            },
+            contentPadding = WindowInsets.safeDrawing
+                .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)
+                .add(
+                    WindowInsets(
+                        left = SpecificationPadding,
+                        top = SpecificationPadding,
+                        right = SpecificationPadding,
+                    )
                 )
-            )
-        }
+                .asPaddingValues(),
+            modifier = Modifier.padding(paddingValues)
+        )
     }
 }
 
diff --git a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
index 313f65b..e22a36e 100644
--- a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
+++ b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
@@ -16,6 +16,11 @@
 
 package androidx.compose.material.catalog.ui.specification
 
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.only
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.material3.CenterAlignedTopAppBar
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
@@ -25,8 +30,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.text.style.TextOverflow
-import com.google.accompanist.insets.navigationBarsPadding
-import com.google.accompanist.insets.statusBarsPadding
 
 @Composable
 fun SpecificationTopAppBar(
@@ -54,9 +57,9 @@
             },
             scrollBehavior = scrollBehavior,
             colors = foregroundColors,
-            modifier = Modifier
-                .statusBarsPadding()
-                .navigationBarsPadding(bottom = false)
+            modifier = Modifier.windowInsetsPadding(
+                WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)
+            )
         )
     }
 }
diff --git a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ModifierInspectorInfoDetector.kt b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ModifierInspectorInfoDetector.kt
index 6483d90..23f9a14 100644
--- a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ModifierInspectorInfoDetector.kt
+++ b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ModifierInspectorInfoDetector.kt
@@ -501,14 +501,15 @@
          */
         private inner class ModifierVisitor : UnexpectedVisitor({ wrongLambda(it) }) {
             override fun visitCallExpression(node: UCallExpression): Boolean {
-                val info = if (isInspectableModifier(node)) node.valueArguments.firstOrNull()
-                else node.valueArguments.lastOrNull()
-                if (isInspectorInfoLambdaType(info?.getExpressionType())) {
-                    info!!.accept(debugInspectorVisitor)
+                val info: UExpression? = node.valueArguments.firstOrNull {
+                    isInspectorInfoLambdaType(it.getExpressionType())
+                }
+                if (info != null) {
+                    info.accept(debugInspectorVisitor)
                     return true
                 }
                 if (isRememberFunctionCall(node)) {
-                    val lambda = info as? ULambdaExpression
+                    val lambda = node.valueArguments.singleOrNull() as? ULambdaExpression
                     val body = lambda?.body as? UBlockExpression
                     val ret = body?.expressions?.firstOrNull() as? UReturnExpression
                     val definition = ret?.returnExpression ?: return super.visitCallExpression(node)
diff --git a/compose/lint/internal-lint-checks/src/test/java/androidx/compose/lint/ModifierInspectorInfoDetectorTest.kt b/compose/lint/internal-lint-checks/src/test/java/androidx/compose/lint/ModifierInspectorInfoDetectorTest.kt
index 60a2359..ab8faf7 100644
--- a/compose/lint/internal-lint-checks/src/test/java/androidx/compose/lint/ModifierInspectorInfoDetectorTest.kt
+++ b/compose/lint/internal-lint-checks/src/test/java/androidx/compose/lint/ModifierInspectorInfoDetectorTest.kt
@@ -1397,4 +1397,42 @@
                 """
             )
     }
+
+    @Test
+    fun passInspectorInfoAtSecondLastParameter() {
+        lint().files(
+            Stubs.Modifier,
+            composedStub,
+            inspectableInfoStub,
+            kotlin(
+                """
+                package androidx.compose.ui
+
+                import androidx.compose.ui.Modifier
+                import androidx.compose.ui.platform.InspectorInfo
+                import androidx.compose.ui.platform.InspectorValueInfo
+                import androidx.compose.ui.platform.debugInspectorInfo
+
+                inline class Dp(val value: Float)
+
+                fun Modifier.width1(width: Dp, height: Dp) =
+                    this.then(SizeModifier1(width, inspectorInfo = debugInspectorInfo {
+                        name = "width1"
+                        properties["width"] = width
+                        properties["height"] = height
+                    }, height))
+
+                private class SizeModifier1(
+                    val width: Dp,
+                    inspectorInfo: InspectorInfo.() -> Unit,
+                    val height: Dp
+                ): Modifier.Element, InspectorValueInfo(inspectorInfo)
+
+                """
+            ).indented()
+        )
+            .testModes(TestMode.DEFAULT)
+            .run()
+            .expectClean()
+    }
 }
diff --git a/compose/material/material/integration-tests/material-catalog/build.gradle b/compose/material/material/integration-tests/material-catalog/build.gradle
index e7d62f0..c7aa189 100644
--- a/compose/material/material/integration-tests/material-catalog/build.gradle
+++ b/compose/material/material/integration-tests/material-catalog/build.gradle
@@ -29,11 +29,11 @@
     implementation(libs.kotlinStdlib)
     implementation project(":core:core")
     implementation project(":compose:runtime:runtime")
+    implementation project(":compose:foundation:foundation-layout")
     implementation project(":compose:ui:ui")
     implementation project(":compose:material:material")
     implementation project(":compose:material:material:material-samples")
     implementation project(":navigation:navigation-compose")
-    implementation "com.google.accompanist:accompanist-insets:0.18.0"
 }
 
 androidx {
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/common/CatalogTopAppBar.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/common/CatalogTopAppBar.kt
index 6132c51..80688a3 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/common/CatalogTopAppBar.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/common/CatalogTopAppBar.kt
@@ -18,6 +18,11 @@
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.only
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.material.AppBarDefaults
 import androidx.compose.material.Divider
 import androidx.compose.material.DropdownMenu
@@ -44,8 +49,6 @@
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.navigationBarsPadding
-import com.google.accompanist.insets.statusBarsPadding
 
 @Composable
 fun CatalogTopAppBar(
@@ -140,9 +143,9 @@
             },
             backgroundColor = Color.Transparent,
             elevation = 0.dp,
-            modifier = Modifier
-                .statusBarsPadding()
-                .navigationBarsPadding(bottom = false)
+            modifier = Modifier.windowInsetsPadding(
+                WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top)
+            )
         )
     }
 }
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/component/Component.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/component/Component.kt
index 791dfa8..d311df8 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/component/Component.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/component/Component.kt
@@ -19,9 +19,14 @@
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
@@ -42,8 +47,6 @@
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 fun Component(
@@ -67,9 +70,9 @@
             modifier = Modifier
                 .padding(paddingValues)
                 .padding(horizontal = ComponentPadding),
-            contentPadding = rememberInsetsPaddingValues(
-                insets = LocalWindowInsets.current.navigationBars
-            )
+            contentPadding = WindowInsets.safeDrawing
+                .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                .asPaddingValues()
         ) {
             item {
                 Box(
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/example/Example.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/example/Example.kt
index d6021c3..31fc61d 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/example/Example.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/example/Example.kt
@@ -17,8 +17,13 @@
 package androidx.compose.material.catalog.library.ui.example
 
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.material.catalog.library.model.Component
 import androidx.compose.material.catalog.library.model.Example
 import androidx.compose.material.catalog.library.model.Theme
@@ -26,7 +31,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import com.google.accompanist.insets.navigationBarsPadding
 
 @Composable
 fun Example(
@@ -50,7 +54,10 @@
             modifier = Modifier
                 .fillMaxSize()
                 .padding(paddingValues)
-                .navigationBarsPadding(),
+                .windowInsetsPadding(
+                    WindowInsets.safeDrawing
+                        .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                ),
             contentAlignment = Alignment.Center
         ) {
             example.content()
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/home/Home.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/home/Home.kt
index ff77567..9a23446 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/home/Home.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/home/Home.kt
@@ -18,7 +18,12 @@
 
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.lazy.GridCells
 import androidx.compose.foundation.lazy.LazyVerticalGrid
 import androidx.compose.foundation.lazy.itemsIndexed
@@ -31,8 +36,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 @OptIn(ExperimentalFoundationApi::class)
@@ -63,9 +66,9 @@
                         )
                     }
                 },
-                contentPadding = rememberInsetsPaddingValues(
-                    insets = LocalWindowInsets.current.navigationBars
-                )
+                contentPadding = WindowInsets.safeDrawing
+                    .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                    .asPaddingValues()
             )
         }
     }
diff --git a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/theme/ThemePicker.kt b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/theme/ThemePicker.kt
index 48c1770..c8a0638 100644
--- a/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/theme/ThemePicker.kt
+++ b/compose/material/material/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/library/ui/theme/ThemePicker.kt
@@ -20,9 +20,15 @@
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.asPaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyRow
@@ -60,8 +66,6 @@
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 fun ThemePicker(
@@ -69,12 +73,17 @@
     onThemeChange: (theme: Theme) -> Unit
 ) {
     var themeState by remember { mutableStateOf(theme) }
+
     LazyColumn(
-        contentPadding = rememberInsetsPaddingValues(
-            insets = LocalWindowInsets.current.navigationBars,
-            additionalTop = ThemePickerPadding,
-            additionalBottom = ThemePickerPadding
-        )
+        contentPadding = WindowInsets.safeDrawing
+            .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+            .add(
+                WindowInsets(
+                    top = ThemePickerPadding,
+                    bottom = ThemePickerPadding
+                )
+            )
+            .asPaddingValues()
     ) {
         item {
             Text(
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index 7ea8041..358f8cd 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -188,9 +188,13 @@
   }
 
   @androidx.compose.material3.ExperimentalMaterial3Api public final class DrawerDefaults {
-    method public float getElevation();
+    method public float getDismissibleDrawerElevation();
+    method public float getModalDrawerElevation();
+    method public float getPermanentDrawerElevation();
     method @androidx.compose.runtime.Composable public long getScrimColor();
-    property public final float Elevation;
+    property public final float DismissibleDrawerElevation;
+    property public final float ModalDrawerElevation;
+    property public final float PermanentDrawerElevation;
     property @androidx.compose.runtime.Composable public final long scrimColor;
     field public static final androidx.compose.material3.DrawerDefaults INSTANCE;
   }
@@ -323,8 +327,26 @@
     method @androidx.compose.runtime.Composable public static void NavigationBarItem(androidx.compose.foundation.layout.RowScope, boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, kotlin.jvm.functions.Function0<kotlin.Unit> icon, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional boolean alwaysShowLabel, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.material3.NavigationBarItemColors colors);
   }
 
+  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface NavigationDrawerItemColors {
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> badgeColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> containerColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> iconColor(boolean selected);
+    method @androidx.compose.runtime.Composable public androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> textColor(boolean selected);
+  }
+
+  @androidx.compose.material3.ExperimentalMaterial3Api public final class NavigationDrawerItemDefaults {
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.NavigationDrawerItemColors colors(optional long selectedContainerColor, optional long unselectedContainerColor, optional long selectedIconColor, optional long unselectedIconColor, optional long selectedTextColor, optional long unselectedTextColor, optional long selectedBadgeColor, optional long unselectedBadgeColor);
+    method public androidx.compose.foundation.layout.PaddingValues getItemPadding();
+    property public final androidx.compose.foundation.layout.PaddingValues ItemPadding;
+    field public static final androidx.compose.material3.NavigationDrawerItemDefaults INSTANCE;
+  }
+
   public final class NavigationDrawerKt {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void NavigationDrawer(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void DismissibleNavigationDrawer(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void ModalNavigationDrawer(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, optional long scrimColor, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @Deprecated @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void NavigationDrawer(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.DrawerState drawerState, optional boolean gesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, 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 PermanentNavigationDrawer(kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> drawerContent, 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.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/integration-tests/material3-catalog/build.gradle b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
index b2e7e22..77f1d0b 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/build.gradle
+++ b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
@@ -28,12 +28,12 @@
     implementation(libs.kotlinStdlib)
     implementation project(":core:core")
     implementation project(":compose:runtime:runtime")
+    implementation project(":compose:foundation:foundation-layout")
     implementation project(":compose:ui:ui")
     implementation project(":compose:material:material")
     implementation project(":compose:material3:material3")
     implementation project(":compose:material3:material3:material3-samples")
     implementation project(":navigation:navigation-compose")
-    implementation "com.google.accompanist:accompanist-insets:0.18.0"
 }
 
 androidx {
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index da40a13..ffa7dc5 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -31,6 +31,7 @@
 import androidx.compose.material3.samples.ClickableElevatedCardSample
 import androidx.compose.material3.samples.ClickableOutlinedCardSample
 import androidx.compose.material3.samples.ColorSchemeSample
+import androidx.compose.material3.samples.DismissibleNavigationDrawerSample
 import androidx.compose.material3.samples.ElevatedButtonSample
 import androidx.compose.material3.samples.ElevatedCardSample
 import androidx.compose.material3.samples.EnterAlwaysSmallTopAppBar
@@ -49,12 +50,13 @@
 import androidx.compose.material3.samples.MenuSample
 import androidx.compose.material3.samples.NavigationBarSample
 import androidx.compose.material3.samples.NavigationBarWithOnlySelectedLabelsSample
-import androidx.compose.material3.samples.NavigationDrawerSample
+import androidx.compose.material3.samples.ModalNavigationDrawerSample
 import androidx.compose.material3.samples.NavigationRailBottomAlignSample
 import androidx.compose.material3.samples.NavigationRailSample
 import androidx.compose.material3.samples.NavigationRailWithOnlySelectedLabelsSample
 import androidx.compose.material3.samples.OutlinedButtonSample
 import androidx.compose.material3.samples.OutlinedCardSample
+import androidx.compose.material3.samples.PermanentNavigationDrawerSample
 import androidx.compose.material3.samples.PinnedSmallTopAppBar
 import androidx.compose.material3.samples.RadioButtonSample
 import androidx.compose.material3.samples.RadioGroupSample
@@ -349,11 +351,25 @@
 private const val NavigationDrawerExampleSourceUrl = "$SampleSourceUrl/DrawerSamples.kt"
 val NavigationDrawerExamples = listOf(
     Example(
-        name = ::NavigationDrawerSample.name,
+        name = ::ModalNavigationDrawerSample.name,
         description = NavigationDrawerExampleDescription,
         sourceUrl = NavigationDrawerExampleSourceUrl
     ) {
-        NavigationDrawerSample()
+        ModalNavigationDrawerSample()
+    },
+    Example(
+        name = ::PermanentNavigationDrawerSample.name,
+        description = NavigationDrawerExampleDescription,
+        sourceUrl = NavigationDrawerExampleSourceUrl
+    ) {
+        PermanentNavigationDrawerSample()
+    },
+    Example(
+        name = ::DismissibleNavigationDrawerSample.name,
+        description = NavigationDrawerExampleDescription,
+        sourceUrl = NavigationDrawerExampleSourceUrl
+    ) {
+        DismissibleNavigationDrawerSample()
     }
 )
 
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/common/CatalogTopAppBar.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/common/CatalogTopAppBar.kt
index 14429a22..9cb326c 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/common/CatalogTopAppBar.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/common/CatalogTopAppBar.kt
@@ -18,6 +18,11 @@
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.only
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.material.Divider
 import androidx.compose.material.DropdownMenu
 import androidx.compose.material.DropdownMenuItem
@@ -43,8 +48,6 @@
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextOverflow
-import com.google.accompanist.insets.navigationBarsPadding
-import com.google.accompanist.insets.statusBarsPadding
 
 @Composable
 fun CatalogTopAppBar(
@@ -143,9 +146,11 @@
             },
             scrollBehavior = scrollBehavior,
             colors = foregroundColors,
-            modifier = Modifier
-                .statusBarsPadding()
-                .navigationBarsPadding(bottom = false)
+            modifier = Modifier.windowInsetsPadding(
+                WindowInsets.safeDrawing.only(
+                    WindowInsetsSides.Horizontal + WindowInsetsSides.Top
+                )
+            )
         )
     }
 }
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/component/Component.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/component/Component.kt
index b37f34a..8b16664 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/component/Component.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/component/Component.kt
@@ -19,9 +19,15 @@
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.asPaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
@@ -41,8 +47,6 @@
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 fun Component(
@@ -64,11 +68,15 @@
     ) { paddingValues ->
         LazyColumn(
             modifier = Modifier.padding(paddingValues),
-            contentPadding = rememberInsetsPaddingValues(
-                insets = LocalWindowInsets.current.navigationBars,
-                additionalStart = ComponentPadding,
-                additionalEnd = ComponentPadding
-            )
+            contentPadding = WindowInsets.safeDrawing
+                .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                .add(
+                    WindowInsets(
+                        left = ComponentPadding,
+                        right = ComponentPadding
+                    )
+                )
+                .asPaddingValues()
         ) {
             item {
                 Box(
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/example/Example.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/example/Example.kt
index 43dc1b6..4eefa74 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/example/Example.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/example/Example.kt
@@ -17,8 +17,13 @@
 package androidx.compose.material3.catalog.library.ui.example
 
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
+import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.material3.catalog.library.model.Component
 import androidx.compose.material3.catalog.library.model.Example
 import androidx.compose.material3.catalog.library.model.Theme
@@ -26,7 +31,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import com.google.accompanist.insets.navigationBarsPadding
 
 @Composable
 fun Example(
@@ -50,7 +54,10 @@
             modifier = Modifier
                 .fillMaxSize()
                 .padding(paddingValues)
-                .navigationBarsPadding(),
+                .windowInsetsPadding(
+                    WindowInsets.safeDrawing
+                        .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                ),
             contentAlignment = Alignment.Center
         ) {
             example.content()
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/home/Home.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/home/Home.kt
index db3c713..ae054b0 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/home/Home.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/home/Home.kt
@@ -17,8 +17,13 @@
 package androidx.compose.material3.catalog.library.ui.home
 
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.asPaddingValues
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.lazy.GridCells
 import androidx.compose.foundation.lazy.LazyVerticalGrid
 import androidx.compose.foundation.lazy.items
@@ -31,8 +36,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 @OptIn(ExperimentalFoundationApi::class)
@@ -47,27 +50,29 @@
         theme = theme,
         onThemeChange = onThemeChange
     ) { paddingValues ->
-        BoxWithConstraints(modifier = Modifier.padding(paddingValues)) {
-            LazyVerticalGrid(
-                modifier = Modifier.padding(paddingValues),
-                cells = GridCells.Adaptive(HomeCellMinSize),
-                content = {
-                    items(components) { component ->
-                        ComponentItem(
-                            component = component,
-                            onClick = onComponentClick
-                        )
-                    }
-                },
-                contentPadding = rememberInsetsPaddingValues(
-                    insets = LocalWindowInsets.current.navigationBars,
-                    additionalStart = HomePadding,
-                    additionalTop = HomePadding,
-                    additionalEnd = HomePadding,
-                    additionalBottom = HomePadding
+        LazyVerticalGrid(
+            modifier = Modifier.padding(paddingValues),
+            cells = GridCells.Adaptive(HomeCellMinSize),
+            content = {
+                items(components) { component ->
+                    ComponentItem(
+                        component = component,
+                        onClick = onComponentClick
+                    )
+                }
+            },
+            contentPadding = WindowInsets.safeDrawing
+                .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+                .add(
+                    WindowInsets(
+                        left = HomePadding,
+                        top = HomePadding,
+                        right = HomePadding,
+                        bottom = HomePadding
+                    )
                 )
-            )
-        }
+                .asPaddingValues()
+        )
     }
 }
 
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/theme/ThemePicker.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/theme/ThemePicker.kt
index 11fd26d..7a01f2b 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/theme/ThemePicker.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/ui/theme/ThemePicker.kt
@@ -20,8 +20,14 @@
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.WindowInsetsSides
+import androidx.compose.foundation.layout.add
+import androidx.compose.foundation.layout.asPaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawing
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.material.Divider
 import androidx.compose.material.RadioButton
@@ -46,8 +52,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import com.google.accompanist.insets.LocalWindowInsets
-import com.google.accompanist.insets.rememberInsetsPaddingValues
 
 @Composable
 fun ThemePicker(
@@ -55,11 +59,15 @@
     onThemeChange: (theme: Theme) -> Unit
 ) {
     LazyColumn(
-        contentPadding = rememberInsetsPaddingValues(
-            insets = LocalWindowInsets.current.navigationBars,
-            additionalTop = ThemePickerPadding,
-            additionalBottom = ThemePickerPadding
-        ),
+        contentPadding = WindowInsets.safeDrawing
+            .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
+            .add(
+                WindowInsets(
+                    top = ThemePickerPadding,
+                    bottom = ThemePickerPadding
+                )
+            )
+            .asPaddingValues(),
         verticalArrangement = Arrangement.spacedBy(ThemePickerPadding)
     ) {
         item {
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DrawerSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DrawerSamples.kt
index 3257fb5..58c4182 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DrawerSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/DrawerSamples.kt
@@ -22,13 +22,24 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Email
+import androidx.compose.material.icons.filled.Face
+import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.material3.Button
+import androidx.compose.material3.DismissibleNavigationDrawer
+import androidx.compose.material3.NavigationDrawerItem
 import androidx.compose.material3.DrawerValue
 import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.NavigationDrawer
+import androidx.compose.material3.Icon
+import androidx.compose.material3.ModalNavigationDrawer
+import androidx.compose.material3.NavigationDrawerItemDefaults
+import androidx.compose.material3.PermanentNavigationDrawer
 import androidx.compose.material3.Text
 import androidx.compose.material3.rememberDrawerState
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -38,17 +49,99 @@
 @OptIn(ExperimentalMaterial3Api::class)
 @Sampled
 @Composable
-fun NavigationDrawerSample() {
+fun ModalNavigationDrawerSample() {
     val drawerState = rememberDrawerState(DrawerValue.Closed)
     val scope = rememberCoroutineScope()
-    NavigationDrawer(
+    // icons to mimic drawer destinations
+    val items = listOf(Icons.Default.Favorite, Icons.Default.Face, Icons.Default.Email)
+    val selectedItem = remember { mutableStateOf(items[0]) }
+    ModalNavigationDrawer(
         drawerState = drawerState,
         drawerContent = {
-            Button(
-                modifier = Modifier.align(Alignment.CenterHorizontally).padding(top = 16.dp),
-                onClick = { scope.launch { drawerState.close() } },
-                content = { Text("Close Drawer") }
-            )
+            items.forEach { item ->
+                NavigationDrawerItem(
+                    icon = { Icon(item, contentDescription = null) },
+                    label = { Text(item.name) },
+                    selected = item == selectedItem.value,
+                    onClick = {
+                        scope.launch { drawerState.close() }
+                        selectedItem.value = item
+                    },
+                    modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
+                )
+            }
+        },
+        content = {
+            Column(
+                modifier = Modifier.fillMaxSize().padding(16.dp),
+                horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Text(text = if (drawerState.isClosed) ">>> Swipe >>>" else "<<< Swipe <<<")
+                Spacer(Modifier.height(20.dp))
+                Button(onClick = { scope.launch { drawerState.open() } }) {
+                    Text("Click to open")
+                }
+            }
+        }
+    )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Sampled
+@Composable
+fun PermanentNavigationDrawerSample() {
+    // icons to mimic drawer destinations
+    val items = listOf(Icons.Default.Favorite, Icons.Default.Face, Icons.Default.Email)
+    val selectedItem = remember { mutableStateOf(items[0]) }
+    PermanentNavigationDrawer(
+        drawerContent = {
+            items.forEach { item ->
+                NavigationDrawerItem(
+                    icon = { Icon(item, contentDescription = null) },
+                    label = { Text(item.name) },
+                    selected = item == selectedItem.value,
+                    onClick = {
+                        selectedItem.value = item
+                    },
+                    modifier = Modifier.padding(horizontal = 12.dp)
+                )
+            }
+        },
+        content = {
+            Column(
+                modifier = Modifier.fillMaxSize().padding(16.dp),
+                horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Text(text = "Application content")
+            }
+        }
+    )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Sampled
+@Composable
+fun DismissibleNavigationDrawerSample() {
+    val drawerState = rememberDrawerState(DrawerValue.Closed)
+    val scope = rememberCoroutineScope()
+    // icons to mimic drawer destinations
+    val items = listOf(Icons.Default.Favorite, Icons.Default.Face, Icons.Default.Email)
+    val selectedItem = remember { mutableStateOf(items[0]) }
+    DismissibleNavigationDrawer(
+        drawerState = drawerState,
+        drawerContent = {
+            items.forEach { item ->
+                NavigationDrawerItem(
+                    icon = { Icon(item, contentDescription = null) },
+                    label = { Text(item.name) },
+                    selected = item == selectedItem.value,
+                    onClick = {
+                        scope.launch { drawerState.close() }
+                        selectedItem.value = item
+                    },
+                    modifier = Modifier.padding(horizontal = 12.dp)
+                )
+            }
         },
         content = {
             Column(
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DismissibleNavigationDrawerTest.kt
similarity index 64%
copy from compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt
copy to compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DismissibleNavigationDrawerTest.kt
index ec056ca..377cce0 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DismissibleNavigationDrawerTest.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.
@@ -31,12 +31,10 @@
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
-import androidx.compose.ui.test.assertHasClickAction
 import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onParent
 import androidx.compose.ui.test.performClick
@@ -52,7 +50,6 @@
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -60,22 +57,18 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 @OptIn(ExperimentalMaterial3Api::class)
-class NavigationDrawerTest {
+class DismissibleNavigationDrawerTest {
 
     @get:Rule
     val rule = createComposeRule()
 
-    private fun advanceClock() {
-        rule.mainClock.advanceTimeBy(100_000L)
-    }
-
     val NavigationDrawerWidth = NavigationDrawerTokens.ContainerWidth
 
     @Test
-    fun navigationDrawer_testOffset_whenOpen() {
+    fun dismissibleNavigationDrawer_testOffset_whenOpen() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Open)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -89,10 +82,10 @@
     }
 
     @Test
-    fun navigationDrawer_testOffset_whenClosed() {
+    fun dismissibleNavigationDrawer_testOffset_whenClosed() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -106,10 +99,10 @@
     }
 
     @Test
-    fun navigationDrawer_testWidth_whenOpen() {
+    fun dismissibleNavigationDrawer_testWidth_whenOpen() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Open)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -119,15 +112,15 @@
         }
 
         rule.onNodeWithTag("content")
-            .assertWidthIsEqualTo(NavigationDrawerTokens.ContainerWidth)
+            .assertWidthIsEqualTo(NavigationDrawerWidth)
     }
 
     @Test
     @SmallTest
-    fun navigationDrawer_hasPaneTitle() {
+    fun dismissibleNavigationDrawer_hasPaneTitle() {
         lateinit var navigationMenu: String
         rule.setMaterialContent(lightColorScheme()) {
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = rememberDrawerState(DrawerValue.Open),
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("navigationDrawerTag"))
@@ -144,11 +137,11 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_openAndClose(): Unit = runBlocking(AutoTestFrameClock()) {
+    fun dismissibleNavigationDrawer_openAndClose(): Unit = runBlocking(AutoTestFrameClock()) {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -173,11 +166,11 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_animateTo(): Unit = runBlocking(AutoTestFrameClock()) {
+    fun dismissibleNavigationDrawer_animateTo(): Unit = runBlocking(AutoTestFrameClock()) {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -202,11 +195,11 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_snapTo(): Unit = runBlocking(AutoTestFrameClock()) {
+    fun dismissibleNavigationDrawer_snapTo(): Unit = runBlocking(AutoTestFrameClock()) {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -231,11 +224,11 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_currentValue(): Unit = runBlocking(AutoTestFrameClock()) {
+    fun dismissibleNavigationDrawer_currentValue(): Unit = runBlocking(AutoTestFrameClock()) {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            DismissibleNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -260,90 +253,51 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_bodyContent_clickable(): Unit = runBlocking(AutoTestFrameClock()) {
-        var drawerClicks = 0
-        var bodyClicks = 0
-        lateinit var drawerState: DrawerState
-        rule.setMaterialContent(lightColorScheme()) {
-            drawerState = rememberDrawerState(DrawerValue.Closed)
-            // emulate click on the screen
-            NavigationDrawer(
-                drawerState = drawerState,
-                drawerContent = {
-                    Box(Modifier.fillMaxSize().clickable { drawerClicks += 1 })
-                },
-                content = {
-                    Box(Modifier.testTag(DrawerTestTag).fillMaxSize().clickable { bodyClicks += 1 })
-                }
-            )
-        }
+    fun dismissibleNavigationDrawer_drawerContent_doesntPropagateClicksWhenOpen(): Unit =
+        runBlocking(
+            AutoTestFrameClock()
+        ) {
+            var bodyClicks = 0
+            lateinit var drawerState: DrawerState
+            rule.setMaterialContent(lightColorScheme()) {
+                drawerState = rememberDrawerState(DrawerValue.Closed)
+                DismissibleNavigationDrawer(
+                    drawerState = drawerState,
+                    drawerContent = {
+                        Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
+                    },
+                    content = {
+                        Box(Modifier.fillMaxSize().clickable { bodyClicks += 1 })
+                    }
+                )
+            }
 
-        // Click in the middle of the drawer (which is the middle of the body)
-        rule.onNodeWithTag(DrawerTestTag).performTouchInput { click() }
+            // Click in the middle of the drawer
+            rule.onNodeWithTag(DrawerTestTag).performClick()
 
-        rule.runOnIdle {
-            assertThat(drawerClicks).isEqualTo(0)
-            assertThat(bodyClicks).isEqualTo(1)
-        }
-        drawerState.open()
+            rule.runOnIdle {
+                assertThat(bodyClicks).isEqualTo(1)
+            }
+            drawerState.open()
 
-        // Click on the left-center pixel of the drawer
-        rule.onNodeWithTag(DrawerTestTag).performTouchInput {
-            click(centerLeft)
-        }
+            // Click on the left-center pixel of the drawer
+            rule.onNodeWithTag(DrawerTestTag).performTouchInput {
+                click(centerLeft)
+            }
 
-        rule.runOnIdle {
-            assertThat(drawerClicks).isEqualTo(1)
-            assertThat(bodyClicks).isEqualTo(1)
+            rule.runOnIdle {
+                assertThat(bodyClicks).isEqualTo(1)
+            }
         }
-    }
 
     @Test
     @LargeTest
-    fun navigationDrawer_drawerContent_doesntPropagateClicksWhenOpen(): Unit = runBlocking(
-        AutoTestFrameClock()
-    ) {
-        var bodyClicks = 0
-        lateinit var drawerState: DrawerState
-        rule.setMaterialContent(lightColorScheme()) {
-            drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
-                drawerState = drawerState,
-                drawerContent = {
-                    Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
-                },
-                content = {
-                    Box(Modifier.fillMaxSize().clickable { bodyClicks += 1 })
-                }
-            )
-        }
-
-        // Click in the middle of the drawer
-        rule.onNodeWithTag(DrawerTestTag).performClick()
-
-        rule.runOnIdle {
-            assertThat(bodyClicks).isEqualTo(1)
-        }
-        drawerState.open()
-
-        // Click on the left-center pixel of the drawer
-        rule.onNodeWithTag(DrawerTestTag).performTouchInput {
-            click(centerLeft)
-        }
-
-        rule.runOnIdle {
-            assertThat(bodyClicks).isEqualTo(1)
-        }
-    }
-
-    @Test
-    @LargeTest
-    fun navigationDrawer_openBySwipe() {
+    fun dismissibleNavigationDrawer_openBySwipe() {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
             Box(Modifier.testTag(DrawerTestTag)) {
-                NavigationDrawer(
+                DismissibleNavigationDrawer(
                     drawerState = drawerState,
                     drawerContent = {
                         Box(Modifier.fillMaxSize().background(color = Color.Magenta))
@@ -372,7 +326,7 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_confirmStateChangeRespect() {
+    fun dismissibleNavigationDrawer_confirmStateChangeRespect() {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(
@@ -382,7 +336,7 @@
                 }
             )
             Box(Modifier.testTag(DrawerTestTag)) {
-                NavigationDrawer(
+                DismissibleNavigationDrawer(
                     drawerState = drawerState,
                     drawerContent = {
                         Box(
@@ -417,14 +371,14 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_openBySwipe_rtl() {
+    fun dismissibleNavigationDrawer_openBySwipe_rtl() {
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
             // emulate click on the screen
             CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                 Box(Modifier.testTag(DrawerTestTag)) {
-                    NavigationDrawer(
+                    DismissibleNavigationDrawer(
                         drawerState = drawerState,
                         drawerContent = {
                             Box(Modifier.fillMaxSize().background(color = Color.Magenta))
@@ -454,76 +408,43 @@
 
     @Test
     @LargeTest
-    fun navigationDrawer_noDismissActionWhenClosed_hasDissmissActionWhenOpen(): Unit = runBlocking(
-        AutoTestFrameClock()
-    ) {
-        lateinit var drawerState: DrawerState
-        rule.setMaterialContent(lightColorScheme()) {
-            drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
-                drawerState = drawerState,
-                drawerContent = {
-                    Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
-                },
-                content = {}
-            )
+    fun dismissibleNavigationDrawer_noDismissActionWhenClosed_hasDissmissActionWhenOpen(): Unit =
+        runBlocking(
+            AutoTestFrameClock()
+        ) {
+            lateinit var drawerState: DrawerState
+            rule.setMaterialContent(lightColorScheme()) {
+                drawerState = rememberDrawerState(DrawerValue.Closed)
+                DismissibleNavigationDrawer(
+                    drawerState = drawerState,
+                    drawerContent = {
+                        Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
+                    },
+                    content = {}
+                )
+            }
+
+            // Drawer should start in closed state and have no dismiss action
+            rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
+                .onParent()
+                .assert(SemanticsMatcher.keyNotDefined(SemanticsActions.Dismiss))
+
+            // When the drawer state is set to Opened
+            drawerState.open()
+            // Then the drawer should be opened and have dismiss action
+            rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
+                .onParent()
+                .assert(SemanticsMatcher.keyIsDefined(SemanticsActions.Dismiss))
+
+            // When the drawer state is set to Closed using dismiss action
+            rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
+                .onParent()
+                .performSemanticsAction(SemanticsActions.Dismiss)
+            // Then the drawer should be closed and have no dismiss action
+            rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
+                .onParent()
+                .assert(SemanticsMatcher.keyNotDefined(SemanticsActions.Dismiss))
         }
-
-        // Drawer should start in closed state and have no dismiss action
-        rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
-            .onParent()
-            .assert(SemanticsMatcher.keyNotDefined(SemanticsActions.Dismiss))
-
-        // When the drawer state is set to Opened
-        drawerState.open()
-        // Then the drawer should be opened and have dismiss action
-        rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
-            .onParent()
-            .assert(SemanticsMatcher.keyIsDefined(SemanticsActions.Dismiss))
-
-        // When the drawer state is set to Closed using dismiss action
-        rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
-            .onParent()
-            .performSemanticsAction(SemanticsActions.Dismiss)
-        // Then the drawer should be closed and have no dismiss action
-        rule.onNodeWithTag(DrawerTestTag, useUnmergedTree = true)
-            .onParent()
-            .assert(SemanticsMatcher.keyNotDefined(SemanticsActions.Dismiss))
-    }
-
-    @Test
-    fun navigationDrawer_scrimNode_reportToSemanticsWhenOpen_notReportToSemanticsWhenClosed() {
-        val topTag = "navigationDrawer"
-        lateinit var closeDrawer: String
-        rule.setMaterialContent(lightColorScheme()) {
-            NavigationDrawer(
-                modifier = Modifier.testTag(topTag),
-                drawerState = rememberDrawerState(DrawerValue.Open),
-                drawerContent = {
-                    Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
-                },
-                content = {
-                    Box(Modifier.fillMaxSize().testTag("body"))
-                }
-            )
-            closeDrawer = getString(Strings.CloseDrawer)
-        }
-
-        // The drawer should be opened
-        rule.onNodeWithTag(DrawerTestTag).assertLeftPositionInRootIsEqualTo(0.dp)
-
-        var topNode = rule.onNodeWithTag(topTag).fetchSemanticsNode()
-        assertEquals(3, topNode.children.size)
-        rule.onNodeWithContentDescription(closeDrawer)
-            .assertHasClickAction()
-            .performSemanticsAction(SemanticsActions.OnClick)
-
-        // Then the drawer should be closed
-        rule.onNodeWithTag(DrawerTestTag).assertLeftPositionInRootIsEqualTo(-NavigationDrawerWidth)
-
-        topNode = rule.onNodeWithTag(topTag).fetchSemanticsNode()
-        assertEquals(2, topNode.children.size)
-    }
 }
 
 private val DrawerTestTag = "drawer"
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerScreenshotTest.kt
similarity index 96%
rename from compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerScreenshotTest.kt
rename to compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerScreenshotTest.kt
index d4f5273..175d8e5 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerScreenshotTest.kt
@@ -41,7 +41,7 @@
 @RunWith(AndroidJUnit4::class)
 @OptIn(ExperimentalMaterial3Api::class)
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-class NavigationDrawerScreenshotTest {
+class ModalNavigationDrawerScreenshotTest {
 
     @Suppress("DEPRECATION")
     @get:Rule
@@ -53,7 +53,7 @@
     private fun ComposeContentTestRule.setnavigationDrawer(drawerValue: DrawerValue) {
         setMaterialContent(lightColorScheme()) {
             Box(Modifier.requiredSize(400.dp, 32.dp).testTag(ContainerTestTag)) {
-                NavigationDrawer(
+                ModalNavigationDrawer(
                     drawerState = rememberDrawerState(drawerValue),
                     drawerContent = {},
                     content = {
@@ -70,7 +70,7 @@
         setMaterialContent(darkColorScheme()) {
             Surface {
                 Box(Modifier.requiredSize(400.dp, 32.dp).testTag(ContainerTestTag)) {
-                    NavigationDrawer(
+                    ModalNavigationDrawer(
                         drawerState = rememberDrawerState(drawerValue),
                         drawerContent = {},
                         content = {
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerTest.kt
similarity index 96%
rename from compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt
rename to compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerTest.kt
index ec056ca..03fefeb 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalNavigationDrawerTest.kt
@@ -60,7 +60,7 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 @OptIn(ExperimentalMaterial3Api::class)
-class NavigationDrawerTest {
+class ModalNavigationDrawerTest {
 
     @get:Rule
     val rule = createComposeRule()
@@ -75,7 +75,7 @@
     fun navigationDrawer_testOffset_whenOpen() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Open)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -92,7 +92,7 @@
     fun navigationDrawer_testOffset_whenClosed() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -109,7 +109,7 @@
     fun navigationDrawer_testWidth_whenOpen() {
         rule.setMaterialContent(lightColorScheme()) {
             val drawerState = rememberDrawerState(DrawerValue.Open)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("content"))
@@ -127,7 +127,7 @@
     fun navigationDrawer_hasPaneTitle() {
         lateinit var navigationMenu: String
         rule.setMaterialContent(lightColorScheme()) {
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = rememberDrawerState(DrawerValue.Open),
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag("navigationDrawerTag"))
@@ -148,7 +148,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -177,7 +177,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -206,7 +206,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -235,7 +235,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -267,7 +267,7 @@
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
             // emulate click on the screen
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().clickable { drawerClicks += 1 })
@@ -307,7 +307,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -343,7 +343,7 @@
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
             Box(Modifier.testTag(DrawerTestTag)) {
-                NavigationDrawer(
+                ModalNavigationDrawer(
                     drawerState = drawerState,
                     drawerContent = {
                         Box(Modifier.fillMaxSize().background(color = Color.Magenta))
@@ -382,7 +382,7 @@
                 }
             )
             Box(Modifier.testTag(DrawerTestTag)) {
-                NavigationDrawer(
+                ModalNavigationDrawer(
                     drawerState = drawerState,
                     drawerContent = {
                         Box(
@@ -424,7 +424,7 @@
             // emulate click on the screen
             CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                 Box(Modifier.testTag(DrawerTestTag)) {
-                    NavigationDrawer(
+                    ModalNavigationDrawer(
                         drawerState = drawerState,
                         drawerContent = {
                             Box(Modifier.fillMaxSize().background(color = Color.Magenta))
@@ -460,7 +460,7 @@
         lateinit var drawerState: DrawerState
         rule.setMaterialContent(lightColorScheme()) {
             drawerState = rememberDrawerState(DrawerValue.Closed)
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 drawerState = drawerState,
                 drawerContent = {
                     Box(Modifier.fillMaxSize().testTag(DrawerTestTag))
@@ -496,7 +496,7 @@
         val topTag = "navigationDrawer"
         lateinit var closeDrawer: String
         rule.setMaterialContent(lightColorScheme()) {
-            NavigationDrawer(
+            ModalNavigationDrawer(
                 modifier = Modifier.testTag(topTag),
                 drawerState = rememberDrawerState(DrawerValue.Open),
                 drawerContent = {
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemScreenshotTest.kt
new file mode 100644
index 0000000..c1c847e
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemScreenshotTest.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
+import androidx.compose.foundation.layout.Column
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Face
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalTestApi::class)
+class NavigationDrawerItemScreenshotTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
+
+    @Test
+    fun lightTheme_defaultColors() {
+        val interactionSource = MutableInteractionSource()
+
+        var scope: CoroutineScope? = null
+
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            scope = rememberCoroutineScope()
+            DefaultDrawerItems(interactionSource)
+        }
+
+        assertDrawerItemMatches(
+            scope = scope!!,
+            interactionSource = interactionSource,
+            interaction = null,
+            goldenIdentifier = "drawerItem_lightTheme_defaultColors"
+        )
+    }
+
+    @Test
+    fun lightTheme_defaultColors_pressed() {
+        val interactionSource = MutableInteractionSource()
+
+        var scope: CoroutineScope? = null
+
+        composeTestRule.setMaterialContent(lightColorScheme()) {
+            scope = rememberCoroutineScope()
+            DefaultDrawerItems(interactionSource)
+        }
+
+        assertDrawerItemMatches(
+            scope = scope!!,
+            interactionSource = interactionSource,
+            interaction = PressInteraction.Press(Offset(10f, 10f)),
+            goldenIdentifier = "drawerItem_lightTheme_defaultColors_pressed"
+        )
+    }
+
+    @Test
+    fun darkTheme_defaultColors() {
+        val interactionSource = MutableInteractionSource()
+
+        var scope: CoroutineScope? = null
+
+        composeTestRule.setMaterialContent(darkColorScheme()) {
+            scope = rememberCoroutineScope()
+            DefaultDrawerItems(interactionSource)
+        }
+
+        assertDrawerItemMatches(
+            scope = scope!!,
+            interactionSource = interactionSource,
+            interaction = null,
+            goldenIdentifier = "drawerItem_darkTheme_defaultColors"
+        )
+    }
+
+    @Test
+    fun darkTheme_defaultColors_pressed() {
+        val interactionSource = MutableInteractionSource()
+
+        var scope: CoroutineScope? = null
+
+        composeTestRule.setMaterialContent(darkColorScheme()) {
+            scope = rememberCoroutineScope()
+            DefaultDrawerItems(interactionSource)
+        }
+
+        assertDrawerItemMatches(
+            scope = scope!!,
+            interactionSource = interactionSource,
+            interaction = PressInteraction.Press(Offset(10f, 10f)),
+            goldenIdentifier = "drawerItem_darkTheme_defaultColors_pressed"
+        )
+    }
+
+    /**
+     * Asserts that the NavigationDrawerItem matches the screenshot with identifier
+     * [goldenIdentifier].
+     *
+     * @param scope [CoroutineScope] used to interact with [MutableInteractionSource]
+     * @param interactionSource the [MutableInteractionSource] used for the first
+     * [NavigationDrawerItem]
+     * @param interaction the [Interaction] to assert for, or `null` if no [Interaction].
+     * @param goldenIdentifier the identifier for the corresponding screenshot
+     */
+    private fun assertDrawerItemMatches(
+        scope: CoroutineScope,
+        interactionSource: MutableInteractionSource,
+        interaction: Interaction? = null,
+        goldenIdentifier: String
+    ) {
+        if (interaction != null) {
+            composeTestRule.runOnIdle {
+                // Start ripple
+                scope.launch {
+                    interactionSource.emit(interaction)
+                }
+            }
+
+            composeTestRule.waitForIdle()
+            // Ripples are drawn on the RenderThread, not the main (UI) thread, so we can't
+            // properly wait for synchronization. Instead just wait until after the ripples are
+            // finished animating.
+            Thread.sleep(300)
+        }
+
+        // Capture and compare screenshots
+        composeTestRule.onNodeWithTag(Tag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenIdentifier)
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun DefaultDrawerItems(
+    interactionSource: MutableInteractionSource,
+) {
+    Column(modifier = Modifier.semantics(mergeDescendants = true) {}.testTag(Tag)) {
+        NavigationDrawerItem(
+            icon = { Icon(Icons.Filled.Favorite, null) },
+            label = { Text("Favorites") },
+            selected = true,
+            onClick = {},
+            interactionSource = interactionSource
+        )
+        NavigationDrawerItem(
+            label = { Text("Favorites") },
+            selected = true,
+            onClick = {},
+            interactionSource = interactionSource
+        )
+        NavigationDrawerItem(
+            icon = { Icon(Icons.Filled.Face, null) },
+            label = { Text("Face") },
+            selected = false,
+            onClick = {},
+            interactionSource = interactionSource
+        )
+        NavigationDrawerItem(
+            icon = { Icon(Icons.Filled.Face, null) },
+            label = { Text("Face") },
+            badge = { Text("100+") },
+            selected = false,
+            onClick = {},
+            interactionSource = interactionSource
+        )
+    }
+}
+
+private const val Tag = "NavigationDrawerItem"
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemTest.kt
new file mode 100644
index 0000000..f2c4bda
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/NavigationDrawerItemTest.kt
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Face
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.material3.tokens.NavigationDrawerTokens
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertHasClickAction
+import androidx.compose.ui.test.assertHeightIsAtLeast
+import androidx.compose.ui.test.assertIsNotSelected
+import androidx.compose.ui.test.assertIsSelected
+import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.getBoundsInRoot
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterial3Api::class)
+class NavigationDrawerItemTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    val DrawerItemTag = "drawer_item_tag"
+
+    @Test
+    fun navigationDrawerItem_sizes() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Column(Modifier.width(264.dp)) {
+                NavigationDrawerItem(
+                    icon = {},
+                    label = {},
+                    selected = true,
+                    onClick = {},
+                    modifier = Modifier.testTag(DrawerItemTag)
+                )
+            }
+        }
+
+        rule.onNodeWithTag(DrawerItemTag)
+            .assertWidthIsEqualTo(264.dp)
+            .assertHeightIsAtLeast(NavigationDrawerTokens.ActiveIndicatorHeight)
+    }
+
+    @Test
+    fun navigationDrawerItem_paddings() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Column(Modifier.width(264.dp)) {
+                NavigationDrawerItem(
+                    icon = {
+                        Icon(
+                            Icons.Default.Face,
+                            contentDescription = null,
+                            modifier = Modifier.testTag("icon")
+                        )
+                    },
+                    label = {
+                        Text("Label")
+                    },
+                    badge = {
+                        Text("Badge")
+                    },
+                    selected = true,
+                    onClick = {},
+                    modifier = Modifier.testTag(DrawerItemTag)
+                )
+            }
+        }
+
+        rule.onNodeWithTag("icon", useUnmergedTree = true)
+            // should be 16dp padding from the start
+            .assertLeftPositionInRootIsEqualTo(16.dp)
+
+        val iconLabelPadding =
+            rule.onNodeWithText("Label", useUnmergedTree = true).getBoundsInRoot().left -
+                rule.onNodeWithTag("icon", useUnmergedTree = true).getBoundsInRoot().right
+        // should be 12dp padding between an icon and a label, also rounding error
+        assertThat(iconLabelPadding - 12.dp).isLessThan(0.5.dp)
+
+        val badgePadding =
+            rule.onRoot().getBoundsInRoot().right -
+                rule.onNodeWithText("Badge", useUnmergedTree = true).getBoundsInRoot().right
+        // 24 at the end
+        assertThat(badgePadding).isEqualTo(24.dp)
+    }
+
+    @Test
+    fun navigationDrawerItem_labelOnly_paddings() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Column(Modifier.width(264.dp)) {
+                NavigationDrawerItem(
+                    label = {
+                        Text("Label")
+                    },
+                    selected = true,
+                    onClick = {},
+                    modifier = Modifier.testTag(DrawerItemTag)
+                )
+            }
+        }
+
+        rule.onNodeWithText("Label", useUnmergedTree = true)
+            // should be 16dp padding from the start
+            .assertLeftPositionInRootIsEqualTo(16.dp)
+    }
+
+    @Test
+    fun defaultSemantics() {
+        rule.setMaterialContent(lightColorScheme()) {
+            PermanentNavigationDrawer(
+                drawerContent = {
+                    NavigationDrawerItem(
+                        modifier = Modifier.testTag("selected_item"),
+                        icon = {
+                            Icon(Icons.Filled.Favorite, null)
+                        },
+                        label = {
+                            Text("ItemText")
+                        },
+                        selected = true,
+                        onClick = {}
+                    )
+                    NavigationDrawerItem(
+                        modifier = Modifier.testTag("unselected_item"),
+                        icon = {
+                            Icon(Icons.Filled.Favorite, null)
+                        },
+                        label = {
+                            Text("ItemText")
+                        },
+                        selected = false,
+                        onClick = {}
+                    )
+                }
+            ) {
+            }
+        }
+
+        rule.onNodeWithTag("selected_item")
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Tab))
+            .assertIsSelected()
+            .assertHasClickAction()
+        rule.onNodeWithTag("unselected_item")
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, Role.Tab))
+            .assertIsNotSelected()
+            .assertHasClickAction()
+    }
+}
\ No newline at end of file
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/PermanentNavigationDrawerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/PermanentNavigationDrawerTest.kt
new file mode 100644
index 0000000..ca9a847
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/PermanentNavigationDrawerTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.tokens.NavigationDrawerTokens
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.semantics.SemanticsProperties
+import androidx.compose.ui.test.SemanticsMatcher
+import androidx.compose.ui.test.assert
+import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onParent
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SmallTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalMaterial3Api::class)
+class PermanentNavigationDrawerTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun permanentNavigationDrawer_testOffset() {
+        rule.setMaterialContent(lightColorScheme()) {
+            PermanentNavigationDrawer(
+                drawerContent = {
+                    Box(Modifier.fillMaxSize().testTag("content"))
+                },
+                content = {}
+            )
+        }
+
+        rule.onNodeWithTag("content")
+            .assertLeftPositionInRootIsEqualTo(0.dp)
+    }
+
+    @Test
+    fun permanentNavigationDrawer_testOffset_rtl() {
+        rule.setMaterialContent(lightColorScheme()) {
+            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                PermanentNavigationDrawer(
+                    drawerContent = {
+                        Box(Modifier.fillMaxSize().testTag("content"))
+                    },
+                    content = {}
+                )
+            }
+        }
+
+        rule.onNodeWithTag("content")
+            .assertLeftPositionInRootIsEqualTo(
+                rule.rootWidth() - NavigationDrawerTokens.ContainerWidth
+            )
+    }
+
+    @Test
+    fun permanentNavigationDrawer_testWidth() {
+        rule.setMaterialContent(lightColorScheme()) {
+            PermanentNavigationDrawer(
+                drawerContent = {
+                    Box(Modifier.fillMaxSize().testTag("content"))
+                },
+                content = {}
+            )
+        }
+
+        rule.onNodeWithTag("content")
+            .assertWidthIsEqualTo(NavigationDrawerTokens.ContainerWidth)
+    }
+
+    @Test
+    @SmallTest
+    fun permanentNavigationDrawer_hasPaneTitle() {
+        lateinit var navigationMenu: String
+        rule.setMaterialContent(lightColorScheme()) {
+            PermanentNavigationDrawer(
+                drawerContent = {
+                    Box(Modifier.fillMaxSize().testTag("navigationDrawerTag"))
+                },
+                content = {}
+            )
+            navigationMenu = getString(Strings.NavigationMenu)
+        }
+
+        rule.onNodeWithTag("navigationDrawerTag", useUnmergedTree = true)
+            .onParent()
+            .assert(SemanticsMatcher.expectValue(SemanticsProperties.PaneTitle, navigationMenu))
+    }
+}
+
+private val DrawerTestTag = "drawer"
\ No newline at end of file
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 44707f5..82741fb 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
@@ -21,28 +21,44 @@
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.tokens.NavigationDrawerTokens
 import androidx.compose.material3.tokens.PaletteTokens
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.contentDescription
 import androidx.compose.ui.semantics.dismiss
 import androidx.compose.ui.semantics.onClick
@@ -73,7 +89,7 @@
 }
 
 /**
- * State of the [NavigationDrawer] composable.
+ * State of the [ModalNavigationDrawer] and [DismissibleNavigationDrawer] composable.
  *
  * @param initialValue The initial value of the state.
  * @param confirmStateChange Optional callback invoked to confirm or veto a pending state change.
@@ -177,7 +193,7 @@
         get() = swipeableState.targetValue
 
     /**
-     * The current position (in pixels) of the drawer sheet.
+     * The current position (in pixels) of the drawer container.
      */
     @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET")
     @ExperimentalMaterial3Api
@@ -222,33 +238,31 @@
  * Modal navigation drawers block interaction with the rest of an app’s content with a scrim.
  * They are elevated above most of the app’s UI and don’t affect the screen’s layout grid.
  *
- * @sample androidx.compose.material3.samples.NavigationDrawerSample
+ * @sample androidx.compose.material3.samples.ModalNavigationDrawerSample
  *
  * @param drawerContent composable that represents content inside the drawer
  * @param modifier optional modifier for the drawer
  * @param drawerState state of the drawer
  * @param gesturesEnabled whether or not drawer can be interacted by gestures
- * @param drawerShape shape of the drawer sheet
+ * @param drawerShape shape of the drawer container
  * @param drawerTonalElevation Affects the alpha of the color overlay applied on the container color
- * of the drawer sheet.
- * @param drawerContainerColor container color to be used for the drawer sheet
- * @param drawerContentColor color of the content to use inside the drawer sheet. Defaults to
+ * of the drawer container.
+ * @param drawerContainerColor container color to be used for the drawer container
+ * @param drawerContentColor color of the content to use inside the drawer container. Defaults to
  * either the matching content color for [drawerContainerColor], or, if it is not a color from
  * the theme, this will keep the same value set above this Surface.
  * @param scrimColor color of the scrim that obscures content when the drawer is open
  * @param content content of the rest of the UI
- *
- * @throws IllegalStateException when parent has [Float.POSITIVE_INFINITY] width
  */
 @Composable
 @ExperimentalMaterial3Api
-fun NavigationDrawer(
+fun ModalNavigationDrawer(
     drawerContent: @Composable ColumnScope.() -> Unit,
     modifier: Modifier = Modifier,
     drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
     gesturesEnabled: Boolean = true,
     drawerShape: Shape = RoundedCornerShape(0.dp, 16.dp, 16.dp, 0.dp),
-    drawerTonalElevation: Dp = DrawerDefaults.Elevation,
+    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
     drawerContainerColor: Color = NavigationDrawerTokens.ContainerColor.toColor(),
     drawerContentColor: Color = contentColorFor(drawerContainerColor),
     scrimColor: Color = DrawerDefaults.scrimColor,
@@ -318,22 +332,454 @@
     }
 }
 
+@Composable
+@ExperimentalMaterial3Api
+@Deprecated(
+    "NavigationDrawer has been renamed to ModalNavigationDrawer to better specify " +
+        "its modal nature", replaceWith = ReplaceWith(
+        "ModalNavigationDrawer(drawerContent,\n" +
+            "        modifier,\n" +
+            "        drawerState,\n" +
+            "        gesturesEnabled,\n" +
+            "        drawerShape,\n" +
+            "        drawerTonalElevation,\n" +
+            "        drawerContainerColor,\n" +
+            "        drawerContentColor,\n" +
+            "        scrimColor,\n" +
+            "        content)"
+    )
+)
+fun NavigationDrawer(
+    drawerContent: @Composable ColumnScope.() -> Unit,
+    modifier: Modifier = Modifier,
+    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
+    gesturesEnabled: Boolean = true,
+    drawerShape: Shape = RoundedCornerShape(0.dp, 16.dp, 16.dp, 0.dp),
+    drawerTonalElevation: Dp = DrawerDefaults.ModalDrawerElevation,
+    drawerContainerColor: Color = NavigationDrawerTokens.ContainerColor.toColor(),
+    drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    scrimColor: Color = DrawerDefaults.scrimColor,
+    content: @Composable () -> Unit
+) {
+    ModalNavigationDrawer(
+        drawerContent,
+        modifier,
+        drawerState,
+        gesturesEnabled,
+        drawerShape,
+        drawerTonalElevation,
+        drawerContainerColor,
+        drawerContentColor,
+        scrimColor,
+        content
+    )
+}
+
+// TODO(b/218286829): Add spec image
 /**
- * Object to hold default values for [NavigationDrawer]
+ * Material Design navigation drawer.
+ *
+ * Standard navigation drawers provide access to drawer destinations and app content on desktop and
+ * tablet screens. They’re often next to app content and affect the screen’s layout grid.
+ *
+ * Dismissible standard drawers can be used for layouts that prioritize content (such as a
+ * photo gallery) or for apps where users are unlikely to switch destinations often. They should
+ * use a visible navigation menu icon to open and close the drawer.
+ *
+ * @sample androidx.compose.material3.samples.DismissibleNavigationDrawerSample
+ *
+ * @param drawerContent composable that represents content inside the drawer
+ * @param modifier optional modifier for the drawer
+ * @param drawerState state of the drawer
+ * @param gesturesEnabled whether or not drawer can be interacted by gestures
+ * @param drawerShape shape of the drawer container
+ * @param drawerTonalElevation Affects the alpha of the color overlay applied on the container color
+ * of the drawer container.
+ * @param drawerContainerColor container color to be used for the drawer container
+ * @param drawerContentColor color of the content to use inside the drawer container. Defaults to
+ * either the matching content color for [drawerContainerColor], or, if it is not a color from
+ * the theme, this will keep the same value set above this Surface.
+ * @param content content of the rest of the UI
+ */
+@Composable
+@ExperimentalMaterial3Api
+fun DismissibleNavigationDrawer(
+    drawerContent: @Composable ColumnScope.() -> Unit,
+    modifier: Modifier = Modifier,
+    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
+    gesturesEnabled: Boolean = true,
+    drawerShape: Shape = RectangleShape,
+    drawerTonalElevation: Dp = DrawerDefaults.DismissibleDrawerElevation,
+    drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
+    drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    content: @Composable () -> Unit
+) {
+    val scope = rememberCoroutineScope()
+    val drawerWidth = NavigationDrawerTokens.ContainerWidth
+    val drawerWidthPx = with(LocalDensity.current) { drawerWidth.toPx() }
+    val minValue = -drawerWidthPx
+    val maxValue = 0f
+
+    val anchors = mapOf(minValue to DrawerValue.Closed, maxValue to DrawerValue.Open)
+    val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
+    Box(
+        modifier.swipeable(
+            state = drawerState.swipeableState,
+            anchors = anchors,
+            thresholds = { _, _ -> FractionalThreshold(0.5f) },
+            orientation = Orientation.Horizontal,
+            enabled = gesturesEnabled,
+            reverseDirection = isRtl,
+            velocityThreshold = DrawerVelocityThreshold,
+            resistance = null
+        )
+    ) {
+        Layout(content = {
+            val navigationMenu = getString(Strings.NavigationMenu)
+            Surface(
+                modifier = Modifier
+                    .sizeIn(maxWidth = drawerWidth)
+                    .semantics {
+                        paneTitle = navigationMenu
+                        if (drawerState.isOpen) {
+                            dismiss {
+                                if (
+                                    drawerState.swipeableState
+                                        .confirmStateChange(DrawerValue.Closed)
+                                ) {
+                                    scope.launch { drawerState.close() }
+                                }; true
+                            }
+                        }
+                    },
+                shape = drawerShape,
+                color = drawerContainerColor,
+                contentColor = drawerContentColor,
+                tonalElevation = drawerTonalElevation
+            ) {
+                Column(Modifier.fillMaxSize(), content = drawerContent)
+            }
+            Box {
+                content()
+            }
+        }) { measurables, constraints ->
+            val sheetPlaceable = measurables[0].measure(constraints)
+            val contentPlaceable = measurables[1].measure(constraints)
+            layout(contentPlaceable.width, contentPlaceable.height) {
+                contentPlaceable.placeRelative(
+                    sheetPlaceable.width + drawerState.offset.value.roundToInt(),
+                    0
+                )
+                sheetPlaceable.placeRelative(drawerState.offset.value.roundToInt(), 0)
+            }
+        }
+    }
+}
+
+// TODO(b/218286829): Add spec image
+/**
+ * Material Design navigation permanent drawer.
+ *
+ * Standard navigation drawers provide access to drawer destinations and app content on desktop
+ * and tablet screens. They’re often next to app content and affect the screen’s layout grid.
+ *
+ * The permanent navigation drawer is always visible and usually used for frequently switching
+ * destinations. On mobile screens, use [ModalNavigationDrawer] instead.
+ *
+ * @sample androidx.compose.material3.samples.PermanentNavigationDrawerSample
+ *
+ * @param drawerContent composable that represents content inside the drawer
+ * @param modifier optional modifier for the drawer
+ * @param drawerShape shape of the drawer container
+ * @param drawerTonalElevation Affects the alpha of the color overlay applied on the container color
+ * of the drawer container.
+ * @param drawerContainerColor container color to be used for the drawer container
+ * @param drawerContentColor color of the content to use inside the drawer container. Defaults to
+ * either the matching content color for [drawerContainerColor], or, if it is not a color from
+ * the theme, this will keep the same value set above this Surface.
+ * @param content content of the rest of the UI
+ */
+@ExperimentalMaterial3Api
+@Composable
+fun PermanentNavigationDrawer(
+    drawerContent: @Composable ColumnScope.() -> Unit,
+    modifier: Modifier = Modifier,
+    drawerShape: Shape = RectangleShape,
+    drawerTonalElevation: Dp = DrawerDefaults.PermanentDrawerElevation,
+    drawerContainerColor: Color = MaterialTheme.colorScheme.surface,
+    drawerContentColor: Color = contentColorFor(drawerContainerColor),
+    content: @Composable () -> Unit
+) {
+    val drawerWidth = NavigationDrawerTokens.ContainerWidth
+    Row(modifier.fillMaxSize()) {
+        val navigationMenu = getString(Strings.NavigationMenu)
+        Surface(
+            modifier = Modifier
+                .sizeIn(maxWidth = drawerWidth)
+                .semantics {
+                    paneTitle = navigationMenu
+                },
+            shape = drawerShape,
+            color = drawerContainerColor,
+            contentColor = drawerContentColor,
+            tonalElevation = drawerTonalElevation
+        ) {
+            Column(Modifier.fillMaxSize(), content = drawerContent)
+        }
+        Box {
+            content()
+        }
+    }
+}
+
+/**
+ * Object to hold default values for [ModalNavigationDrawer]
  */
 @ExperimentalMaterial3Api
 object DrawerDefaults {
 
     /**
-     * Default Elevation for drawer sheet as specified in material specs
+     * Default Elevation for drawer container in the [ModalNavigationDrawer] as specified in
+     * material specs
      */
-    val Elevation = NavigationDrawerTokens.ModalContainerElevation
+    val ModalDrawerElevation = NavigationDrawerTokens.ModalContainerElevation
+
+    /**
+     * Default Elevation for drawer container in the [PermanentNavigationDrawer] as specified in
+     * material specs
+     */
+    val PermanentDrawerElevation = NavigationDrawerTokens.StandardContainerElevation
+
+    /**
+     * Default Elevation for drawer container in the [DismissibleNavigationDrawer] as specified in
+     * material specs
+     */
+    val DismissibleDrawerElevation = NavigationDrawerTokens.StandardContainerElevation
 
     val scrimColor: Color
         @Composable
         get() = PaletteTokens.NeutralVariant0.copy(alpha = NavigationDrawerTokens.ScrimOpacity)
 }
 
+/**
+ * Material Design navigation drawer item.
+ *
+ * A [NavigationDrawerItem] represents a destination within drawers, either [ModalNavigationDrawer],
+ * [PermanentNavigationDrawer] or [DismissibleNavigationDrawer].
+ *
+ * @sample androidx.compose.material3.samples.ModalNavigationDrawerSample
+ *
+ * @param label text label for this item
+ * @param selected whether this item is selected
+ * @param onClick the callback to be invoked when this item is clicked
+ * @param modifier optional [Modifier] for this item
+ * @param icon optional icon for this item, typically an [Icon]
+ * @param badge optional badge to show on this item from the end side
+ * @param colors the various colors used in elements of this item
+ * @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
+ * for this item. You can create and pass in your own remembered [MutableInteractionSource] if
+ * you want to observe [Interaction]s and customize the appearance / behavior of this item in
+ * different [Interaction]s.
+ */
+@Composable
+@ExperimentalMaterial3Api
+fun NavigationDrawerItem(
+    label: @Composable () -> Unit,
+    selected: Boolean,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    icon: (@Composable () -> Unit)? = null,
+    badge: (@Composable () -> Unit)? = null,
+    shape: Shape = NavigationDrawerTokens.ActiveIndicatorShape,
+    colors: NavigationDrawerItemColors = NavigationDrawerItemDefaults.colors(),
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
+) {
+    Surface(
+        shape = shape,
+        color = colors.containerColor(selected).value,
+        interactionSource = interactionSource,
+        modifier = modifier
+            .height(NavigationDrawerTokens.ActiveIndicatorHeight)
+            .fillMaxWidth()
+            .selectable(
+                selected = selected,
+                onClick = onClick,
+                interactionSource = interactionSource,
+                role = Role.Tab,
+                indication = null
+            )
+    ) {
+        Row(
+            Modifier.padding(start = 16.dp, end = 24.dp),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            if (icon != null) {
+                val iconColor = colors.iconColor(selected).value
+                CompositionLocalProvider(LocalContentColor provides iconColor, content = icon)
+                Spacer(Modifier.width(12.dp))
+            }
+            Box(Modifier.weight(1f)) {
+                val labelColor = colors.textColor(selected).value
+                CompositionLocalProvider(LocalContentColor provides labelColor, content = label)
+            }
+            if (badge != null) {
+                Spacer(Modifier.width(12.dp))
+                val badgeColor = colors.badgeColor(selected).value
+                CompositionLocalProvider(LocalContentColor provides badgeColor, content = badge)
+            }
+        }
+    }
+}
+
+/** Represents the colors of the various elements of a drawer item. */
+@Stable
+@ExperimentalMaterial3Api
+interface NavigationDrawerItemColors {
+
+    /**
+     * Represents the icon color for this item, depending on whether it is [selected].
+     *
+     * @param selected whether the item is selected
+     */
+    @Composable
+    fun iconColor(selected: Boolean): State<Color>
+
+    /**
+     * Represents the text color for this item, depending on whether it is [selected].
+     *
+     * @param selected whether the item is selected
+     */
+    @Composable
+    fun textColor(selected: Boolean): State<Color>
+
+    /**
+     * Represents the badge color for this item, depending on whether it is [selected].
+     *
+     * @param selected whether the item is selected
+     */
+    @Composable
+    fun badgeColor(selected: Boolean): State<Color>
+
+    /**
+     * Represents the container color for this item, depending on whether it is [selected].
+     *
+     * @param selected whether the item is selected
+     */
+    @Composable
+    fun containerColor(selected: Boolean): State<Color>
+}
+
+/** Defaults used in [NavigationDrawerItem]. */
+@ExperimentalMaterial3Api
+object NavigationDrawerItemDefaults {
+
+    /**
+     * Creates a [NavigationDrawerItemColors] with the provided colors according to the Material
+     * specification.
+     *
+     * @param selectedContainerColor the color to use for the background of the item when selected
+     * @param unselectedContainerColor the color to use for the background of the item when
+     * unselected
+     * @param selectedIconColor the color to use for the icon when the item is selected.
+     * @param unselectedIconColor the color to use for the icon when the item is unselected.
+     * @param selectedTextColor the color to use for the text label when the item is selected.
+     * @param unselectedTextColor the color to use for the text label when the item is unselected.
+     * @param selectedBadgeColor the color to use for the badge when the item is selected.
+     * @param unselectedBadgeColor the color to use for the badge when the item is unselected.
+     *
+     * @return the resulting [NavigationDrawerItemColors] used for [NavigationDrawerItem]
+     */
+    @Composable
+    fun colors(
+        selectedContainerColor: Color = NavigationDrawerTokens.ActiveIndicatorColor.toColor(),
+        unselectedContainerColor: Color = NavigationDrawerTokens.ContainerColor.toColor(),
+        selectedIconColor: Color = NavigationDrawerTokens.ActiveIconColor.toColor(),
+        unselectedIconColor: Color = NavigationDrawerTokens.InactiveIconColor.toColor(),
+        selectedTextColor: Color = NavigationDrawerTokens.ActiveLabelTextColor.toColor(),
+        unselectedTextColor: Color = NavigationDrawerTokens.InactiveLabelTextColor.toColor(),
+        selectedBadgeColor: Color = selectedTextColor,
+        unselectedBadgeColor: Color = unselectedTextColor,
+    ): NavigationDrawerItemColors = DefaultDrawerItemsColor(
+        selectedIconColor,
+        unselectedIconColor,
+        selectedTextColor,
+        unselectedTextColor,
+        selectedContainerColor,
+        unselectedContainerColor,
+        selectedBadgeColor,
+        unselectedBadgeColor
+    )
+
+    /**
+     * Default external padding for a [NavigationDrawerItem] according to material spec.
+     */
+    val ItemPadding = PaddingValues(horizontal = 12.dp)
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+private class DefaultDrawerItemsColor(
+    val selectedIconColor: Color,
+    val unselectedIconColor: Color,
+    val selectedTextColor: Color,
+    val unselectedTextColor: Color,
+    val selectedContainerColor: Color,
+    val unselectedContainerColor: Color,
+    val selectedBadgeColor: Color,
+    val unselectedBadgeColor: Color
+) : NavigationDrawerItemColors {
+    @Composable
+    override fun iconColor(selected: Boolean): State<Color> {
+        return rememberUpdatedState(if (selected) selectedIconColor else unselectedIconColor)
+    }
+
+    @Composable
+    override fun textColor(selected: Boolean): State<Color> {
+        return rememberUpdatedState(if (selected) selectedTextColor else unselectedTextColor)
+    }
+
+    @Composable
+    override fun containerColor(selected: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (selected) selectedContainerColor else unselectedContainerColor
+        )
+    }
+
+    @Composable
+    override fun badgeColor(selected: Boolean): State<Color> {
+        return rememberUpdatedState(
+            if (selected) selectedBadgeColor else unselectedBadgeColor
+        )
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is DefaultDrawerItemsColor) return false
+
+        if (selectedIconColor != other.selectedIconColor) return false
+        if (unselectedIconColor != other.unselectedIconColor) return false
+        if (selectedTextColor != other.selectedTextColor) return false
+        if (unselectedTextColor != other.unselectedTextColor) return false
+        if (selectedContainerColor != other.selectedContainerColor) return false
+        if (unselectedContainerColor != other.unselectedContainerColor) return false
+        if (selectedBadgeColor != other.selectedBadgeColor) return false
+        if (unselectedBadgeColor != other.unselectedBadgeColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = selectedIconColor.hashCode()
+        result = 31 * result + unselectedIconColor.hashCode()
+        result = 31 * result + selectedTextColor.hashCode()
+        result = 31 * result + unselectedTextColor.hashCode()
+        result = 31 * result + selectedContainerColor.hashCode()
+        result = 31 * result + unselectedContainerColor.hashCode()
+        result = 31 * result + selectedBadgeColor.hashCode()
+        result = 31 * result + unselectedBadgeColor.hashCode()
+        return result
+    }
+}
+
 private fun calculateFraction(a: Float, b: Float, pos: Float) =
     ((pos - a) / (b - a)).coerceIn(0f, 1f)
 
@@ -365,7 +811,6 @@
     }
 }
 
-private val EndDrawerPadding = 56.dp
 private val DrawerVelocityThreshold = 400.dp
 
 // TODO: b/177571613 this should be a proper decay settling
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index fe0d2ec..fe009d6 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -71,7 +71,7 @@
         testImplementation(libs.truth)
         testImplementation(libs.mockitoCore)
         testImplementation(libs.mockitoKotlin)
-        testImplementation("org.robolectric:robolectric:4.6.1") // TODO(b/209063122): fix tests to work with SDK 31 and robolectric 4.7
+        testImplementation(libs.robolectric)
         testImplementation(project(":compose:ui:ui-test-junit4"))
         testImplementation(project(":compose:test-utils"))
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
index dc297f4..f929af9 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
@@ -1797,6 +1797,26 @@
         }
     }
 
+    @Test
+    fun disposeSecondPrecomposedItem() {
+        // it is a regression from b/218668336. the assertion was incorrectly checking
+        // for the ranges so disposing the second active precomposed node was crashing.
+        val state = SubcomposeLayoutState(SubcomposeSlotReusePolicy(0))
+
+        composeItems(state, mutableStateOf(emptyList()))
+
+        rule.runOnIdle {
+            state.precompose(0) { ItemContent(0) }
+            val handle = state.precompose(1) { ItemContent(1) }
+            handle.dispose()
+        }
+
+        assertNodes(
+            exists = /*prefetch*/ listOf(0),
+            doesNotExist = /*disposed*/ listOf(1)
+        )
+    }
+
     private fun composeItems(
         state: SubcomposeLayoutState,
         items: MutableState<List<Int>>
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
index 703064d..b2847d2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
@@ -565,7 +565,8 @@
                 if (node != null) {
                     check(precomposedCount > 0)
                     val itemIndex = root.foldedChildren.indexOf(node)
-                    check(itemIndex <= root.foldedChildren.size - precomposedCount)
+                    // make sure this item is in the precomposed items range
+                    check(itemIndex >= root.foldedChildren.size - precomposedCount)
                     // move this item into the reusable section
                     reusableCount++
                     precomposedCount--
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
index 17a1516..c4f4c9a 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
@@ -104,6 +104,7 @@
                 }
             }
         }
+        onMeasured()
         return this
     }
 
@@ -145,6 +146,4 @@
     override fun minIntrinsicHeight(width: Int) = wrapped.minIntrinsicHeight(width)
 
     override fun maxIntrinsicHeight(width: Int) = wrapped.maxIntrinsicHeight(width)
-
-    override val parentData: Any? get() = wrapped.parentData
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/EntityList.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/EntityList.kt
index 588d2a9..a573ee2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/EntityList.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/EntityList.kt
@@ -16,9 +16,13 @@
 
 package androidx.compose.ui.node
 
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.DrawModifier
 import androidx.compose.ui.input.pointer.PointerInputModifier
+import androidx.compose.ui.layout.OnPlacedModifier
+import androidx.compose.ui.layout.OnRemeasuredModifier
+import androidx.compose.ui.layout.ParentDataModifier
 import androidx.compose.ui.semantics.SemanticsEntity
 import androidx.compose.ui.semantics.SemanticsModifier
 
@@ -46,6 +50,16 @@
         if (modifier is SemanticsModifier) {
             add(SemanticsEntity(layoutNodeWrapper, modifier), SemanticsEntityType.index)
         }
+        if (modifier is ParentDataModifier) {
+            add(SimpleEntity(layoutNodeWrapper, modifier), ParentDataEntityType.index)
+        }
+        @OptIn(ExperimentalComposeUiApi::class)
+        if (modifier is OnPlacedModifier) {
+            add(SimpleEntity(layoutNodeWrapper, modifier), OnPlacedEntityType.index)
+        }
+        if (modifier is OnRemeasuredModifier) {
+            add(SimpleEntity(layoutNodeWrapper, modifier), RemeasureEntityType.index)
+        }
     }
 
     private fun <T : LayoutNodeEntity<T, *>> add(entity: T, index: Int) {
@@ -122,7 +136,14 @@
         val DrawEntityType = EntityType<DrawEntity, DrawModifier>(0)
         val PointerInputEntityType = EntityType<PointerInputEntity, PointerInputModifier>(1)
         val SemanticsEntityType = EntityType<SemanticsEntity, SemanticsModifier>(2)
+        val ParentDataEntityType =
+            EntityType<SimpleEntity<ParentDataModifier>, ParentDataModifier>(3)
+        @OptIn(ExperimentalComposeUiApi::class)
+        val OnPlacedEntityType =
+            EntityType<SimpleEntity<OnPlacedModifier>, OnPlacedModifier>(4)
+        val RemeasureEntityType =
+            EntityType<SimpleEntity<OnRemeasuredModifier>, OnRemeasuredModifier>(5)
 
-        private const val TypeCount = 3
+        private const val TypeCount = 6
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
index f72742d..3afa7f0 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
@@ -54,12 +54,10 @@
             layoutNode.measureScope.measure(layoutNode.children, constraints)
         }
         layoutNode.handleMeasureResult(measureResult)
+        onMeasured()
         return this
     }
 
-    override val parentData: Any?
-        get() = null
-
     override fun findPreviousFocusWrapper() = wrappedBy?.findPreviousFocusWrapper()
 
     override fun findNextFocusWrapper(excludeDeactivated: Boolean): ModifiedFocusNode? = null
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index be57631..7fc5587 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -43,9 +43,6 @@
 import androidx.compose.ui.layout.MeasureScope
 import androidx.compose.ui.layout.ModifierInfo
 import androidx.compose.ui.layout.OnGloballyPositionedModifier
-import androidx.compose.ui.layout.OnPlacedModifier
-import androidx.compose.ui.layout.OnRemeasuredModifier
-import androidx.compose.ui.layout.ParentDataModifier
 import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.Remeasurement
 import androidx.compose.ui.layout.RemeasurementModifier
@@ -666,6 +663,10 @@
 
                 toWrap.entities.add(toWrap, mod)
 
+                if (mod is OnGloballyPositionedModifier) {
+                    getOrCreateOnPositionedCallbacks() += toWrap to mod
+                }
+
                 // Re-use the layoutNodeWrapper if possible.
                 reuseLayoutNodeWrapper(mod, toWrap)?.let {
                     return@foldOut it
@@ -727,26 +728,6 @@
                         .initialize()
                         .assignChained(toWrap)
                 }
-                if (mod is ParentDataModifier) {
-                    wrapper = ModifiedParentDataNode(wrapper, mod)
-                        .initialize()
-                        .assignChained(toWrap)
-                }
-                if (mod is OnRemeasuredModifier) {
-                    wrapper = RemeasureModifierWrapper(wrapper, mod)
-                        .initialize()
-                        .assignChained(toWrap)
-                }
-                if (mod is OnPlacedModifier) {
-                    wrapper = OnPlacedModifierWrapper(wrapper, mod)
-                        .initialize()
-                        .assignChained(toWrap)
-                }
-                if (mod is OnGloballyPositionedModifier) {
-                    wrapper = OnGloballyPositionedModifierWrapper(wrapper, mod)
-                        .initialize()
-                        .assignChained(toWrap)
-                }
                 wrapper
             }
 
@@ -816,10 +797,11 @@
     /**
      * List of all OnPositioned callbacks in the modifier chain.
      */
-    private var onPositionedCallbacks: MutableVector<OnGloballyPositionedModifierWrapper>? = null
+    private var onPositionedCallbacks:
+        MutableVector<Pair<LayoutNodeWrapper, OnGloballyPositionedModifier>>? = null
 
     internal fun getOrCreateOnPositionedCallbacks() = onPositionedCallbacks
-        ?: mutableVectorOf<OnGloballyPositionedModifierWrapper>().also {
+        ?: mutableVectorOf<Pair<LayoutNodeWrapper, OnGloballyPositionedModifier>>().also {
             onPositionedCallbacks = it
         }
 
@@ -913,7 +895,7 @@
         val onPositionedCallbacks = onPositionedCallbacks
         return modifier.foldOut(false) { mod, hasNewCallback ->
             hasNewCallback || mod is OnGloballyPositionedModifier &&
-                (onPositionedCallbacks?.firstOrNull { mod == it.modifier } == null)
+                (onPositionedCallbacks?.firstOrNull { mod == it.second } == null)
         }
     }
 
@@ -1179,7 +1161,7 @@
             return // it hasn't been placed, so don't make a call
         }
         onPositionedCallbacks?.forEach {
-            it.modifier.onGloballyPositioned(it)
+            it.second.onGloballyPositioned(it.first)
         }
     }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
index 3e1c26c..94d7eef 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
@@ -122,7 +122,7 @@
                 position = wrapper.toParentPosition(position)
                 wrapper = wrapper.wrappedBy!!
                 if (wrapper == layoutNode.innerLayoutNodeWrapper) break
-                if (alignmentLine in wrapper.providedAlignmentLines) {
+                if (alignmentLine in wrapper.measureResult.alignmentLines) {
                     val newPosition = wrapper[alignmentLine]
                     position = Offset(newPosition.toFloat(), newPosition.toFloat())
                 }
@@ -157,7 +157,7 @@
             // Add alignment lines on the modifier of the child.
             var wrapper = child.innerLayoutNodeWrapper.wrappedBy!!
             while (wrapper != layoutNode.innerLayoutNodeWrapper) {
-                wrapper.providedAlignmentLines.forEach { childLine ->
+                wrapper.measureResult.alignmentLines.keys.forEach { childLine ->
                     addAlignmentLine(childLine, wrapper[childLine], wrapper)
                 }
                 wrapper = wrapper.wrappedBy!!
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
index 8ba9c81..9086834 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
@@ -18,6 +18,7 @@
 
 package androidx.compose.ui.node
 
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusOrder
 import androidx.compose.ui.focus.FocusState
@@ -40,6 +41,7 @@
 import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.layout.ParentDataModifier
 import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.VerticalAlignmentLine
 import androidx.compose.ui.layout.findRoot
@@ -143,7 +145,21 @@
     private var oldAlignmentLines: MutableMap<AlignmentLine, Int>? = null
 
     override val providedAlignmentLines: Set<AlignmentLine>
-        get() = _measureResult?.alignmentLines?.keys ?: emptySet()
+        get() {
+            var set: MutableSet<AlignmentLine>? = null
+            var wrapper: LayoutNodeWrapper? = this
+            while (wrapper != null) {
+                val alignmentLines = wrapper._measureResult?.alignmentLines
+                if (alignmentLines?.isNotEmpty() == true) {
+                    if (set == null) {
+                        set = mutableSetOf()
+                    }
+                    set.addAll(alignmentLines.keys)
+                }
+                wrapper = wrapper.wrapped
+            }
+            return set ?: emptySet()
+        }
 
     /**
      * Called when the width or height of [measureResult] change. The object instance pointed to
@@ -167,6 +183,22 @@
     var zIndex: Float = 0f
         protected set
 
+    override val parentData: Any?
+        get() = entities.head(EntityList.ParentDataEntityType).parentData
+
+    private val SimpleEntity<ParentDataModifier>?.parentData: Any?
+        get() = if (this == null) {
+            wrapped?.parentData
+        } else {
+            with(modifier) {
+                /**
+                 * ParentData provided through the parentData node will override the data provided
+                 * through a modifier.
+                 */
+                measureScope.modifyParentData(next.parentData)
+            }
+        }
+
     final override val parentLayoutCoordinates: LayoutCoordinates?
         get() {
             check(isAttached) { ExpectAttachedLayoutCoordinates }
@@ -210,6 +242,19 @@
         return result
     }
 
+    fun onMeasured() {
+        if (entities.has(EntityList.RemeasureEntityType)) {
+            val invokeRemeasureCallbacks = {
+                entities.forEach(EntityList.RemeasureEntityType) {
+                    it.modifier.onRemeasured(measuredSize)
+                }
+            }
+            layoutNode.owner?.snapshotObserver?.withNoSnapshotReadObservation(
+                invokeRemeasureCallbacks
+            ) ?: invokeRemeasureCallbacks()
+        }
+    }
+
     abstract fun calculateAlignmentLine(alignmentLine: AlignmentLine): Int
 
     final override fun get(alignmentLine: AlignmentLine): Int {
@@ -288,7 +333,12 @@
         wrapped?.draw(canvas)
     }
 
-    open fun onPlaced() {}
+    fun onPlaced() {
+        @OptIn(ExperimentalComposeUiApi::class)
+        entities.forEach(EntityList.OnPlacedEntityType) {
+            it.modifier.onPlaced(this)
+        }
+    }
 
     // implementation of draw block passed to the OwnedLayer
     @Suppress("LiftReturnOrAssignment")
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
index 69a1192..fae672fa 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
@@ -34,11 +34,15 @@
     modifier: LayoutModifier
 ) : DelegatingLayoutNodeWrapper<LayoutModifier>(wrapped, modifier) {
 
-    override fun measure(constraints: Constraints): Placeable = performingMeasure(constraints) {
-        with(modifier) {
-            measureResult = measureScope.measure(wrapped, constraints)
-            this@ModifiedLayoutNode
+    override fun measure(constraints: Constraints): Placeable {
+        val placeable = performingMeasure(constraints) {
+            with(modifier) {
+                measureResult = measureScope.measure(wrapped, constraints)
+                this@ModifiedLayoutNode
+            }
         }
+        onMeasured()
+        return placeable
     }
 
     override fun minIntrinsicWidth(height: Int): Int =
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedParentDataNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedParentDataNode.kt
deleted file mode 100644
index 521c2c0..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedParentDataNode.kt
+++ /dev/null
@@ -1,33 +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.node
-
-import androidx.compose.ui.layout.ParentDataModifier
-
-internal class ModifiedParentDataNode(
-    wrapped: LayoutNodeWrapper,
-    parentDataModifier: ParentDataModifier
-) : DelegatingLayoutNodeWrapper<ParentDataModifier>(wrapped, parentDataModifier) {
-    override val parentData: Any?
-        get() = with(modifier) {
-            /**
-             * ParentData provided through the parentData node will override the data provided
-             * through a modifier
-             */
-            layoutNode.measureScope.modifyParentData(wrapped.parentData)
-        }
-}
\ No newline at end of file
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt
deleted file mode 100644
index 930985e..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.node
-
-import androidx.compose.ui.layout.AlignmentLine
-import androidx.compose.ui.layout.OnGloballyPositionedModifier
-
-/**
- * Wrapper around the [OnGloballyPositionedModifier].
- */
-internal class OnGloballyPositionedModifierWrapper(
-    wrapped: LayoutNodeWrapper,
-    modifier: OnGloballyPositionedModifier
-) : DelegatingLayoutNodeWrapper<OnGloballyPositionedModifier>(wrapped, modifier) {
-
-    override fun onInitialize() {
-        super.onInitialize()
-        layoutNode.getOrCreateOnPositionedCallbacks() += this
-    }
-
-    override val providedAlignmentLines: Set<AlignmentLine>
-        get() {
-            val result = mutableSetOf<AlignmentLine>()
-            layoutNode
-            var wrapper = wrapped as LayoutNodeWrapper?
-            while (wrapper != null) {
-                result += wrapper.providedAlignmentLines
-                if (wrapper == layoutNode.innerLayoutNodeWrapper) break
-                wrapper = wrapper.wrapped
-            }
-            return result
-        }
-}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnPlacedModifierWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnPlacedModifierWrapper.kt
deleted file mode 100644
index 86e7928..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnPlacedModifierWrapper.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.node
-
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.layout.AlignmentLine
-import androidx.compose.ui.layout.OnPlacedModifier
-
-/**
- * Wrapper around the [OnPlacedModifier].
- */
-@OptIn(ExperimentalComposeUiApi::class)
-internal class OnPlacedModifierWrapper constructor(
-    wrapped: LayoutNodeWrapper,
-    modifier: OnPlacedModifier
-) : DelegatingLayoutNodeWrapper<OnPlacedModifier>(wrapped, modifier) {
-    override val providedAlignmentLines: Set<AlignmentLine>
-        get() {
-            val result = mutableSetOf<AlignmentLine>()
-            layoutNode
-            var wrapper = wrapped as LayoutNodeWrapper?
-            while (wrapper != null) {
-                result += wrapper.providedAlignmentLines
-                if (wrapper == layoutNode.innerLayoutNodeWrapper) break
-                wrapper = wrapper.wrapped
-            }
-            return result
-        }
-
-    override fun onPlaced() {
-        // Invoke the onPlaced callback.
-        modifier.onPlaced(this)
-    }
-}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt
deleted file mode 100644
index fdb9840..0000000
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/RemeasureModifierWrapper.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.node
-
-import androidx.compose.ui.layout.OnRemeasuredModifier
-import androidx.compose.ui.layout.Placeable
-import androidx.compose.ui.unit.Constraints
-
-/**
- * Wrapper around the [OnRemeasuredModifier] to notify whenever a remeasurement happens.
- */
-internal class RemeasureModifierWrapper(
-    wrapped: LayoutNodeWrapper,
-    modifier: OnRemeasuredModifier
-) : DelegatingLayoutNodeWrapper<OnRemeasuredModifier>(wrapped, modifier) {
-    override fun measure(constraints: Constraints): Placeable {
-        val placeable = super.measure(constraints)
-        val invokeRemeasureCallbacks = {
-            modifier.onRemeasured(measuredSize)
-        }
-        layoutNode.owner?.snapshotObserver?.withNoSnapshotReadObservation(invokeRemeasureCallbacks)
-            ?: invokeRemeasureCallbacks.invoke()
-        return placeable
-    }
-}
\ No newline at end of file
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SimpleEntity.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SimpleEntity.kt
new file mode 100644
index 0000000..4c471ff
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SimpleEntity.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.node
+
+import androidx.compose.ui.Modifier
+
+/**
+ * A [LayoutNodeEntity] that only contains a [Modifier] and no logic
+ */
+internal class SimpleEntity<M : Modifier>(
+    layoutNodeWrapper: LayoutNodeWrapper,
+    modifier: M
+) : LayoutNodeEntity<SimpleEntity<M>, M>(layoutNodeWrapper, modifier)
\ No newline at end of file
diff --git a/core/OWNERS b/core/OWNERS
index 3a3ca6d..6a8e25d 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -8,7 +8,6 @@
 # For fingerprint related files
 jaggies@google.com
 joshmccloskey@google.com
-kchyn@google.com
 curtislb@google.com
 
 # For text related files
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index abd8918..4bed9ff 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -840,17 +840,17 @@
   }
 
   public final class RemoteInput {
-    method public static void addDataResultToIntent(androidx.core.app.RemoteInput!, android.content.Intent!, java.util.Map<java.lang.String!,android.net.Uri!>!);
-    method public static void addResultsToIntent(androidx.core.app.RemoteInput![]!, android.content.Intent!, android.os.Bundle!);
+    method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+    method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
     method public boolean getAllowFreeFormInput();
-    method public java.util.Set<java.lang.String!>! getAllowedDataTypes();
-    method public CharSequence![]! getChoices();
-    method public static java.util.Map<java.lang.String!,android.net.Uri!>! getDataResultsFromIntent(android.content.Intent!, String!);
+    method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+    method public CharSequence![]? getChoices();
+    method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
     method public int getEditChoicesBeforeSending();
-    method public android.os.Bundle! getExtras();
-    method public CharSequence! getLabel();
-    method public String! getResultKey();
-    method public static android.os.Bundle! getResultsFromIntent(android.content.Intent!);
+    method public android.os.Bundle getExtras();
+    method public CharSequence? getLabel();
+    method public String getResultKey();
+    method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
     method public static int getResultsSource(android.content.Intent);
     method public boolean isDataOnly();
     method public static void setResultsSource(android.content.Intent, int);
@@ -962,7 +962,7 @@
     method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
     method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
     method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
-    method public androidx.core.app.TaskStackBuilder! addParentStack(android.content.ComponentName!);
+    method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
     method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
     method public android.content.Intent? editIntentAt(int);
     method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
@@ -971,7 +971,7 @@
     method public android.content.Intent![] getIntents();
     method public android.app.PendingIntent? getPendingIntent(int, int);
     method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
-    method @Deprecated public java.util.Iterator<android.content.Intent!>! iterator();
+    method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
     method public void startActivities();
     method public void startActivities(android.os.Bundle?);
   }
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index 832cbba..8554f3b 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -840,17 +840,17 @@
   }
 
   public final class RemoteInput {
-    method public static void addDataResultToIntent(androidx.core.app.RemoteInput!, android.content.Intent!, java.util.Map<java.lang.String!,android.net.Uri!>!);
-    method public static void addResultsToIntent(androidx.core.app.RemoteInput![]!, android.content.Intent!, android.os.Bundle!);
+    method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+    method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
     method public boolean getAllowFreeFormInput();
-    method public java.util.Set<java.lang.String!>! getAllowedDataTypes();
-    method public CharSequence![]! getChoices();
-    method public static java.util.Map<java.lang.String!,android.net.Uri!>! getDataResultsFromIntent(android.content.Intent!, String!);
+    method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+    method public CharSequence![]? getChoices();
+    method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
     method public int getEditChoicesBeforeSending();
-    method public android.os.Bundle! getExtras();
-    method public CharSequence! getLabel();
-    method public String! getResultKey();
-    method public static android.os.Bundle! getResultsFromIntent(android.content.Intent!);
+    method public android.os.Bundle getExtras();
+    method public CharSequence? getLabel();
+    method public String getResultKey();
+    method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
     method public static int getResultsSource(android.content.Intent);
     method public boolean isDataOnly();
     method public static void setResultsSource(android.content.Intent, int);
@@ -962,7 +962,7 @@
     method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
     method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
     method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
-    method public androidx.core.app.TaskStackBuilder! addParentStack(android.content.ComponentName!);
+    method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
     method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
     method public android.content.Intent? editIntentAt(int);
     method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
@@ -971,7 +971,7 @@
     method public android.content.Intent![] getIntents();
     method public android.app.PendingIntent? getPendingIntent(int, int);
     method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
-    method @Deprecated public java.util.Iterator<android.content.Intent!>! iterator();
+    method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
     method public void startActivities();
     method public void startActivities(android.os.Bundle?);
   }
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index ce1b4a2..d008d07 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -930,26 +930,26 @@
     method public void setShouldShowIcon(boolean);
     method public boolean shouldShowIcon();
     method @RequiresApi(26) public android.app.RemoteAction toRemoteAction();
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(4) public android.app.PendingIntent! mActionIntent;
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(3) public CharSequence! mContentDescription;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(4) public android.app.PendingIntent mActionIntent;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(3) public CharSequence mContentDescription;
     field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(5) public boolean mEnabled;
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(1) public androidx.core.graphics.drawable.IconCompat! mIcon;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(1) public androidx.core.graphics.drawable.IconCompat mIcon;
     field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(6) public boolean mShouldShowIcon;
-    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(2) public CharSequence! mTitle;
+    field @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) @androidx.versionedparcelable.ParcelField(2) public CharSequence mTitle;
   }
 
   public final class RemoteInput {
-    method public static void addDataResultToIntent(androidx.core.app.RemoteInput!, android.content.Intent!, java.util.Map<java.lang.String!,android.net.Uri!>!);
-    method public static void addResultsToIntent(androidx.core.app.RemoteInput![]!, android.content.Intent!, android.os.Bundle!);
+    method public static void addDataResultToIntent(androidx.core.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String!,android.net.Uri!>);
+    method public static void addResultsToIntent(androidx.core.app.RemoteInput![], android.content.Intent, android.os.Bundle);
     method public boolean getAllowFreeFormInput();
-    method public java.util.Set<java.lang.String!>! getAllowedDataTypes();
-    method public CharSequence![]! getChoices();
-    method public static java.util.Map<java.lang.String!,android.net.Uri!>! getDataResultsFromIntent(android.content.Intent!, String!);
+    method public java.util.Set<java.lang.String!>? getAllowedDataTypes();
+    method public CharSequence![]? getChoices();
+    method public static java.util.Map<java.lang.String!,android.net.Uri!>? getDataResultsFromIntent(android.content.Intent, String);
     method @androidx.core.app.RemoteInput.EditChoicesBeforeSending public int getEditChoicesBeforeSending();
-    method public android.os.Bundle! getExtras();
-    method public CharSequence! getLabel();
-    method public String! getResultKey();
-    method public static android.os.Bundle! getResultsFromIntent(android.content.Intent!);
+    method public android.os.Bundle getExtras();
+    method public CharSequence? getLabel();
+    method public String getResultKey();
+    method public static android.os.Bundle? getResultsFromIntent(android.content.Intent);
     method @androidx.core.app.RemoteInput.Source public static int getResultsSource(android.content.Intent);
     method public boolean isDataOnly();
     method public static void setResultsSource(android.content.Intent, @androidx.core.app.RemoteInput.Source int);
@@ -1070,7 +1070,7 @@
     method public androidx.core.app.TaskStackBuilder addNextIntentWithParentStack(android.content.Intent);
     method public androidx.core.app.TaskStackBuilder addParentStack(android.app.Activity);
     method public androidx.core.app.TaskStackBuilder addParentStack(Class<?>);
-    method public androidx.core.app.TaskStackBuilder! addParentStack(android.content.ComponentName!);
+    method public androidx.core.app.TaskStackBuilder addParentStack(android.content.ComponentName);
     method public static androidx.core.app.TaskStackBuilder create(android.content.Context);
     method public android.content.Intent? editIntentAt(int);
     method @Deprecated public static androidx.core.app.TaskStackBuilder! from(android.content.Context!);
@@ -1079,7 +1079,7 @@
     method public android.content.Intent![] getIntents();
     method public android.app.PendingIntent? getPendingIntent(int, int);
     method public android.app.PendingIntent? getPendingIntent(int, int, android.os.Bundle?);
-    method @Deprecated public java.util.Iterator<android.content.Intent!>! iterator();
+    method @Deprecated public java.util.Iterator<android.content.Intent!> iterator();
     method public void startActivities();
     method public void startActivities(android.os.Bundle?);
   }
diff --git a/core/core/lint-baseline.xml b/core/core/lint-baseline.xml
index 9a02222..0864e15 100644
--- a/core/core/lint-baseline.xml
+++ b/core/core/lint-baseline.xml
@@ -1225,50 +1225,6 @@
     <issue
         id="BanUncheckedReflection"
         message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (int) icon.getClass().getMethod(&quot;getType&quot;).invoke(icon);"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="1104"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (String) icon.getClass().getMethod(&quot;getResPackage&quot;).invoke(icon);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="1132"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (int) icon.getClass().getMethod(&quot;getResId&quot;).invoke(icon);"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="1161"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Uri) icon.getClass().getMethod(&quot;getUri&quot;).invoke(icon);"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="1189"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
         errorLine1="                Object value = sActionBarOnMenuKeyMethod.invoke(actionBar, event);"
         errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -6823,292 +6779,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setName(bundle.getString(NAME_KEY))"
-        errorLine2="                                ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="71"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setUri(bundle.getString(URI_KEY))"
-        errorLine2="                               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="72"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setKey(bundle.getString(KEY_KEY))"
-        errorLine2="                               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="73"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 22; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setBot(bundle.getBoolean(IS_BOT_KEY))"
-        errorLine2="                               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="74"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 22; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setImportant(bundle.getBoolean(IS_IMPORTANT_KEY))"
-        errorLine2="                                     ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="75"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setName(person.getName())"
-        errorLine2="                                ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="89"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        (person.getIcon() != null)"
-        errorLine2="                                ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="91"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                ? IconCompat.createFromIcon(person.getIcon())"
-        errorLine2="                                                                   ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="92"
-            column="68"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setUri(person.getUri())"
-        errorLine2="                               ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="94"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setKey(person.getKey())"
-        errorLine2="                               ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="95"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setBot(person.isBot())"
-        errorLine2="                               ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="96"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setImportant(person.isImportant())"
-        errorLine2="                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="97"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        PersistableBundle result = new PersistableBundle();"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="151"
-            column="36"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        result.putString(NAME_KEY, mName != null ? mName.toString() : null);"
-        errorLine2="               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="152"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        result.putString(URI_KEY, mUri);"
-        errorLine2="               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="153"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        result.putString(KEY_KEY, mKey);"
-        errorLine2="               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="154"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 22; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        result.putBoolean(IS_BOT_KEY, mIsBot);"
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="155"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 22; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        result.putBoolean(IS_IMPORTANT_KEY, mIsImportant);"
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="156"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        return new android.app.Person.Builder()"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="175"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setName(getName())"
-        errorLine2="                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="176"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setIcon((getIcon() != null) ? getIcon().toIcon() : null)"
-        errorLine2="                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="177"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setUri(getUri())"
-        errorLine2="                 ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="178"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setKey(getKey())"
-        errorLine2="                 ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="179"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setBot(isBot())"
-        errorLine2="                 ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="180"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .setImportant(isImportant())"
-        errorLine2="                 ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="181"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.Person is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                .build();"
-        errorLine2="                 ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/Person.java"
-            line="182"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 28; however, the containing class androidx.core.text.PrecomputedTextCompat.Params is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="                mWrapped = new PrecomputedText.Params.Builder(paint)"
         errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -7538,391 +7208,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                IconCompat.createFromIcon(remoteAction.getIcon()), remoteAction.getTitle(),"
-        errorLine2="                                                       ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="117"
-            column="56"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                IconCompat.createFromIcon(remoteAction.getIcon()), remoteAction.getTitle(),"
-        errorLine2="                                                                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="117"
-            column="81"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                remoteAction.getContentDescription(), remoteAction.getActionIntent());"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="118"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                remoteAction.getContentDescription(), remoteAction.getActionIntent());"
-        errorLine2="                                                                   ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="118"
-            column="68"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        action.setEnabled(remoteAction.isEnabled());"
-        errorLine2="                                       ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="119"
-            column="40"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            action.setShouldShowIcon(remoteAction.shouldShowIcon());"
-        errorLine2="                                                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="121"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        RemoteAction action = new RemoteAction(mIcon.toIcon(), mTitle, mContentDescription,"
-        errorLine2="                              ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="190"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        action.setEnabled(isEnabled());"
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="192"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.RemoteActionCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            action.setShouldShowIcon(shouldShowIcon());"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="194"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return android.app.RemoteInput.getDataResultsFromIntent(intent, remoteInputResultKey);"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="339"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return android.app.RemoteInput.getResultsFromIntent(intent);"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="377"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            android.app.RemoteInput.addResultsToIntent(fromCompat(remoteInputs), intent, results);"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="403"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                android.app.RemoteInput.addResultsToIntent("
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="426"
-            column="41"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));"
-        errorLine2="                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="452"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            android.app.RemoteInput.addDataResultToIntent(fromCompat(remoteInput), intent, results);"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="467"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));"
-        errorLine2="                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="487"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            android.app.RemoteInput.setResultsSource(intent, source);"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="506"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));"
-        errorLine2="                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="513"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return android.app.RemoteInput.getResultsSource(intent);"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="531"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                new android.app.RemoteInput.Builder(src.getResultKey())"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="562"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setLabel(src.getLabel())"
-        errorLine2="                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="563"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setChoices(src.getChoices())"
-        errorLine2="                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="564"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setAllowFreeFormInput(src.getAllowFreeFormInput())"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="565"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .addExtras(src.getExtras());"
-        errorLine2="                         ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="566"
-            column="26"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    builder.setAllowDataType(allowedDataType, true);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="571"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="576"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        return builder.build();"
-        errorLine2="                       ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="578"
-            column="24"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                new RemoteInput.Builder(src.getResultKey())"
-        errorLine2="                                            ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="584"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setLabel(src.getLabel())"
-        errorLine2="                                      ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="585"
-            column="39"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setChoices(src.getChoices())"
-        errorLine2="                                        ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="586"
-            column="41"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setAllowFreeFormInput(src.getAllowFreeFormInput())"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="587"
-            column="52"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .addExtras(src.getExtras());"
-        errorLine2="                                       ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="588"
-            column="40"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            Set&lt;String> allowedDataTypes = src.getAllowedDataTypes();"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="590"
-            column="48"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());"
-        errorLine2="                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="598"
-            column="53"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.RemoteInput is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        ClipData clipData = intent.getClipData();"
-        errorLine2="                                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="605"
-            column="36"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 28; however, the containing class androidx.core.database.sqlite.SQLiteCursorCompat is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="            cursor.setFillWindowForwardOnly(fillWindowForwardOnly);"
         errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -7934,17 +7219,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.ServiceCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            service.stopForeground(flags);"
-        errorLine2="                    ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ServiceCompat.java"
-            line="100"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 16; however, the containing class androidx.core.app.ShareCompat.IntentReader is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="                        result = Html.escapeHtml(text);"
         errorLine2="                                      ~~~~~~~~~~">
@@ -9100,17 +8374,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.TaskStackBuilder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags,"
-        errorLine2="                                 ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="341"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 23; however, the containing class androidx.core.widget.TextViewCompat is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="            textView.setTextAppearance(resId);"
         errorLine2="                     ~~~~~~~~~~~~~~~~~">
@@ -9366,17 +8629,6 @@
 
     <issue
         id="KotlinPropertyAccess"
-        message="This method should be called `getShouldShowIcon` such that `shouldShowIcon` can be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public boolean shouldShowIcon() {"
-        errorLine2="                   ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="150"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
         message="This method should be called `getMipMap` such that `mipMap` can be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
         errorLine1="    public boolean hasMipMap() {"
         errorLine2="                   ~~~~~~~~~">
@@ -10896,281 +10148,6 @@
     <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public byte[]          mData = null;"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="176"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public Parcelable      mParcelable = null;"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="182"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public ColorStateList  mTintList = null;"
-        errorLine2="           ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="206"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public String mTintModeStr = null;"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="216"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public String mString1;"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="223"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithResource(Context context, @DrawableRes int resId) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="232"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithResource(Context context, @DrawableRes int resId) {"
-        errorLine2="                                                ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="232"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithResource(Resources r, String pkg, @DrawableRes int resId) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="243"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithResource(Resources r, String pkg, @DrawableRes int resId) {"
-        errorLine2="                                                ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="243"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithResource(Resources r, String pkg, @DrawableRes int resId) {"
-        errorLine2="                                                             ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="243"
-            column="62"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithBitmap(Bitmap bits) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="270"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithBitmap(Bitmap bits) {"
-        errorLine2="                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="270"
-            column="47"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithAdaptiveBitmap(Bitmap bits) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="285"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithAdaptiveBitmap(Bitmap bits) {"
-        errorLine2="                                                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="285"
-            column="55"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithData(byte[] data, int offset, int length) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="303"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithData(byte[] data, int offset, int length) {"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="303"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithContentUri(String uri) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="320"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithContentUri(String uri) {"
-        errorLine2="                                                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="320"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithContentUri(Uri uri) {"
-        errorLine2="                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="335"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static IconCompat createWithContentUri(Uri uri) {"
-        errorLine2="                                                  ~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="335"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat setTint(@ColorInt int tint) {"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="496"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat setTintList(ColorStateList tintList) {"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="506"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat setTintList(ColorStateList tintList) {"
-        errorLine2="                                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="506"
-            column="35"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat setTintMode(PorterDuff.Mode mode) {"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="517"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat setTintMode(PorterDuff.Mode mode) {"
-        errorLine2="                                  ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/IconCompat.java"
-            line="517"
-            column="35"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
         errorLine1="    public Locale get(int index) {"
         errorLine2="           ~~~~~~">
         <location
@@ -12095,226 +11072,6 @@
     <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public IconCompat mIcon;"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="47"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public CharSequence mTitle;"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="53"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public CharSequence mContentDescription;"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="59"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public PendingIntent mActionIntent;"
-        errorLine2="           ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteActionCompat.java"
-            line="65"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public String getResultKey() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="115"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public CharSequence getLabel() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="122"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public CharSequence[] getChoices() {"
-        errorLine2="           ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="129"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public Set&lt;String> getAllowedDataTypes() {"
-        errorLine2="           ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="133"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public Bundle getExtras() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="170"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static Map&lt;String, Uri> getDataResultsFromIntent("
-        errorLine2="                  ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="336"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="            Intent intent, String remoteInputResultKey) {"
-        errorLine2="            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="337"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="            Intent intent, String remoteInputResultKey) {"
-        errorLine2="                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="337"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static Bundle getResultsFromIntent(Intent intent) {"
-        errorLine2="                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="375"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static Bundle getResultsFromIntent(Intent intent) {"
-        errorLine2="                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="375"
-            column="47"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,"
-        errorLine2="                                          ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="400"
-            column="43"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,"
-        errorLine2="                                                                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="400"
-            column="71"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="            Bundle results) {"
-        errorLine2="            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="401"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static void addDataResultToIntent(RemoteInput remoteInput, Intent intent,"
-        errorLine2="                                             ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="464"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public static void addDataResultToIntent(RemoteInput remoteInput, Intent intent,"
-        errorLine2="                                                                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="464"
-            column="71"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="            Map&lt;String, Uri> results) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="465"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
         errorLine1="    public ResultReceiver(Handler handler) {"
         errorLine2="                          ~~~~~~~">
         <location
@@ -12975,28 +11732,6 @@
     <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public TaskStackBuilder addParentStack(ComponentName sourceActivityName) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="200"
-            column="12"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
-        errorLine1="    public TaskStackBuilder addParentStack(ComponentName sourceActivityName) {"
-        errorLine2="                                           ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="200"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://android.github.io/kotlin-guides/interop.html#nullability-annotations"
         errorLine1="    boolean isRtl(char[] array, int start, int count);"
         errorLine2="                  ~~~~~~">
         <location
diff --git a/core/core/src/androidTest/java/androidx/core/database/sqlite/SQLiteCursorCompatTest.java b/core/core/src/androidTest/java/androidx/core/database/sqlite/SQLiteCursorCompatTest.java
index b06bc3c..1a78245 100644
--- a/core/core/src/androidTest/java/androidx/core/database/sqlite/SQLiteCursorCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/database/sqlite/SQLiteCursorCompatTest.java
@@ -18,11 +18,8 @@
 
 import static org.junit.Assert.assertTrue;
 
-import android.database.Cursor;
 import android.database.sqlite.SQLiteCursor;
-import android.database.sqlite.SQLiteCursorDriver;
 import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteQuery;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -36,18 +33,14 @@
     @Test
     public void setFillWindowForwardOnly() {
         final Boolean[] calledSetter = { false };
-        SQLiteDatabase db = SQLiteDatabase.create(new SQLiteDatabase.CursorFactory() {
-            @Override
-            public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver primaryQuery,
-                    String editTable, SQLiteQuery query) {
-                SQLiteCursor cursor = new SQLiteCursor(primaryQuery, editTable, query);
-                SQLiteCursorCompat.setFillWindowForwardOnly(cursor, true);
+        SQLiteDatabase db = SQLiteDatabase.create((db1, primaryQuery, editTable, query) -> {
+            SQLiteCursor cursor = new SQLiteCursor(primaryQuery, editTable, query);
+            SQLiteCursorCompat.setFillWindowForwardOnly(cursor, true);
 
-                // no easy way to read whether setter worked, so
-                // we just validate it can be called successfully
-                calledSetter[0] = true;
-                return cursor;
-            }
+            // no easy way to read whether setter worked, so
+            // we just validate it can be called successfully
+            calledSetter[0] = true;
+            return cursor;
         });
         db.execSQL("CREATE TABLE foo (num INTEGER);");
         db.query("foo", new String[] {"*"}, null, null, null, null, null);
diff --git a/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTest.java b/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTest.java
index facc1a3..a1222df 100644
--- a/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTest.java
@@ -21,8 +21,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.graphics.BlendMode;
-import android.graphics.BlendModeColorFilter;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.PorterDuff;
@@ -37,22 +35,11 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
+@SdkSuppress(maxSdkVersion = 28)
 @SmallTest
 public class BlendModeColorFilterCompatTest {
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
-    public void testNullBlendModeRemovesBlendModeColorFilter() {
-        ColorFilter filter = createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.CLEAR);
-        assertTrue(filter instanceof BlendModeColorFilter);
-
-        BlendModeColorFilter blendModeFilter = (BlendModeColorFilter) filter;
-        assertEquals(Color.RED, blendModeFilter.getColor());
-        assertEquals(BlendMode.CLEAR, blendModeFilter.getMode());
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.P)
     public void testNullBlendModeRemovesPorterDuffColorFilter() {
         ColorFilter filter = createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.CLEAR);
         assertTrue(filter instanceof PorterDuffColorFilter);
diff --git a/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTestApi29.java b/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTestApi29.java
new file mode 100644
index 0000000..b0ad3b0
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/graphics/BlendModeColorFilterCompatTestApi29.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.graphics;
+
+import static androidx.core.graphics.BlendModeColorFilterCompat.createBlendModeColorFilterCompat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SdkSuppress(minSdkVersion = 29)
+@SmallTest
+public class BlendModeColorFilterCompatTestApi29 {
+
+    @Test
+    public void testNullBlendModeRemovesBlendModeColorFilter() {
+        ColorFilter filter = createBlendModeColorFilterCompat(Color.RED, BlendModeCompat.CLEAR);
+        assertTrue(filter instanceof BlendModeColorFilter);
+
+        BlendModeColorFilter blendModeFilter = (BlendModeColorFilter) filter;
+        assertEquals(Color.RED, blendModeFilter.getColor());
+        assertEquals(BlendMode.CLEAR, blendModeFilter.getMode());
+    }
+}
diff --git a/core/core/src/androidTest/java/androidx/core/graphics/PaintTest.java b/core/core/src/androidTest/java/androidx/core/graphics/PaintTest.java
index f6858e3..acbb9cf 100644
--- a/core/core/src/androidTest/java/androidx/core/graphics/PaintTest.java
+++ b/core/core/src/androidTest/java/androidx/core/graphics/PaintTest.java
@@ -17,17 +17,16 @@
 package androidx.core.graphics;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.graphics.BlendMode;
+import android.annotation.SuppressLint;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Xfermode;
-import android.os.Build;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SdkSuppress;
@@ -37,45 +36,12 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
+@SdkSuppress(maxSdkVersion = 28)
 @SmallTest
 public class PaintTest {
 
+    @SuppressLint("NewApi") // due to BlendModeCompat's RequiresApi annotations
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
-    public void testBlendModeCompatMatchesPlatform() {
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.CLEAR, BlendMode.CLEAR);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC, BlendMode.SRC);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST, BlendMode.DST);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_OVER, BlendMode.SRC_OVER);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_OVER, BlendMode.DST_OVER);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_IN, BlendMode.SRC_IN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_IN, BlendMode.DST_IN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_OUT, BlendMode.SRC_OUT);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_OUT, BlendMode.DST_OUT);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_ATOP, BlendMode.SRC_ATOP);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_ATOP, BlendMode.DST_ATOP);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.XOR, BlendMode.XOR);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.PLUS, BlendMode.PLUS);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.MODULATE, BlendMode.MODULATE);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SCREEN, BlendMode.SCREEN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.OVERLAY, BlendMode.OVERLAY);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DARKEN, BlendMode.DARKEN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.LIGHTEN, BlendMode.LIGHTEN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR_DODGE, BlendMode.COLOR_DODGE);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR_BURN, BlendMode.COLOR_BURN);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.HARD_LIGHT, BlendMode.HARD_LIGHT);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SOFT_LIGHT, BlendMode.SOFT_LIGHT);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DIFFERENCE, BlendMode.DIFFERENCE);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.EXCLUSION, BlendMode.EXCLUSION);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.MULTIPLY, BlendMode.MULTIPLY);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.HUE, BlendMode.HUE);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SATURATION, BlendMode.SATURATION);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR, BlendMode.COLOR);
-        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.LUMINOSITY, BlendMode.LUMINOSITY);
-    }
-
-    @Test
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.P)
     public void testBlendModeCompatMatchesPorterDuff() {
         verifyPorterDuffMatchesCompat(BlendModeCompat.CLEAR, PorterDuff.Mode.CLEAR);
         verifyPorterDuffMatchesCompat(BlendModeCompat.SRC, PorterDuff.Mode.SRC);
@@ -113,19 +79,6 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
-    public void testNullBlendModeRemovesBlendMode() {
-        Paint p = new Paint();
-        assertTrue(PaintCompat.setBlendMode(p, BlendModeCompat.CLEAR));
-        assertEquals(BlendMode.CLEAR, p.getBlendMode());
-
-        assertTrue(PaintCompat.setBlendMode(p, null));
-        assertNull(p.getBlendMode());
-    }
-
-
-    @Test
-    @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.P)
     public void testNullBlendModeRemovesXfermode() {
         Paint p = new Paint();
         assertTrue(PaintCompat.setBlendMode(p, BlendModeCompat.CLEAR));
@@ -135,19 +88,6 @@
     }
 
     /**
-     * Helper test class to hide usages of new APIs and avoid ClassNotFoundExceptions
-     * in tests
-     */
-    private static class TestHelper {
-        private static void verifyBlendModeMatchesCompat(@NonNull BlendModeCompat compat,
-                                                         @NonNull BlendMode blendMode) {
-            Paint p = new Paint();
-            PaintCompat.setBlendMode(p, compat);
-            assertEquals(blendMode, p.getBlendMode());
-        }
-    }
-
-    /**
      * Helper method to verify that the provided {@link BlendModeCompat} instance
      * matches the given {@link PorterDuff.Mode} which may be null if there is no
      * equivalent PorterDuff.Mode for the BlendMode
@@ -159,7 +99,7 @@
         if (compat != null && mode == null) {
             // If there is not a compatible PorterDuff mode for this BlendMode, configuration
             // of the blend mode should return false
-            assertTrue(!result);
+            assertFalse(result);
         } else if (compat != null) {
             // .. otherwise if there is a corresponding PorterDuff mode with the given BlendMode
             // then the assignment should complete successfully
diff --git a/core/core/src/androidTest/java/androidx/core/graphics/PaintTestApi29.java b/core/core/src/androidTest/java/androidx/core/graphics/PaintTestApi29.java
new file mode 100644
index 0000000..df91c96
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/graphics/PaintTestApi29.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 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.core.graphics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.BlendMode;
+import android.graphics.Paint;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SdkSuppress(minSdkVersion = 29)
+@SmallTest
+public class PaintTestApi29 {
+
+    @Test
+    public void testBlendModeCompatMatchesPlatform() {
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.CLEAR, BlendMode.CLEAR);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC, BlendMode.SRC);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST, BlendMode.DST);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_OVER, BlendMode.SRC_OVER);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_OVER, BlendMode.DST_OVER);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_IN, BlendMode.SRC_IN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_IN, BlendMode.DST_IN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_OUT, BlendMode.SRC_OUT);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_OUT, BlendMode.DST_OUT);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SRC_ATOP, BlendMode.SRC_ATOP);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DST_ATOP, BlendMode.DST_ATOP);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.XOR, BlendMode.XOR);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.PLUS, BlendMode.PLUS);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.MODULATE, BlendMode.MODULATE);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SCREEN, BlendMode.SCREEN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.OVERLAY, BlendMode.OVERLAY);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DARKEN, BlendMode.DARKEN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.LIGHTEN, BlendMode.LIGHTEN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR_DODGE, BlendMode.COLOR_DODGE);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR_BURN, BlendMode.COLOR_BURN);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.HARD_LIGHT, BlendMode.HARD_LIGHT);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SOFT_LIGHT, BlendMode.SOFT_LIGHT);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.DIFFERENCE, BlendMode.DIFFERENCE);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.EXCLUSION, BlendMode.EXCLUSION);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.MULTIPLY, BlendMode.MULTIPLY);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.HUE, BlendMode.HUE);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.SATURATION, BlendMode.SATURATION);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.COLOR, BlendMode.COLOR);
+        TestHelper.verifyBlendModeMatchesCompat(BlendModeCompat.LUMINOSITY, BlendMode.LUMINOSITY);
+    }
+
+    @Test
+    public void testNullBlendModeRemovesBlendMode() {
+        Paint p = new Paint();
+        assertTrue(PaintCompat.setBlendMode(p, BlendModeCompat.CLEAR));
+        assertEquals(BlendMode.CLEAR, p.getBlendMode());
+
+        assertTrue(PaintCompat.setBlendMode(p, null));
+        assertNull(p.getBlendMode());
+    }
+
+    /**
+     * Helper test class to hide usages of new APIs and avoid ClassNotFoundExceptions
+     * in tests
+     */
+    private static class TestHelper {
+        private static void verifyBlendModeMatchesCompat(@NonNull BlendModeCompat compat,
+                                                         @NonNull BlendMode blendMode) {
+            Paint p = new Paint();
+            PaintCompat.setBlendMode(p, compat);
+            assertEquals(blendMode, p.getBlendMode());
+        }
+    }
+}
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
index 88dec5b..04000e8 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsAnimationCompatActivityTest.kt
@@ -31,6 +31,7 @@
 import androidx.test.espresso.Espresso.onView
 import androidx.test.espresso.action.ViewActions
 import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import androidx.testutils.withActivity
@@ -404,6 +405,50 @@
     }
 
     @Test
+    public fun check_view_on_apply_called() {
+        val container = scenario.withActivity { findViewById(R.id.container) }
+        val onApplyLatch = CountDownLatch(1)
+        val customView = object : View(scenario.withActivity { this }) {
+            override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
+                onApplyLatch.countDown()
+                return insets
+            }
+        }
+        scenario.onActivity { (container as ViewGroup).addView(customView) }
+        val stopCallback = createCallback()
+        ViewCompat.setWindowInsetsAnimationCallback(customView, stopCallback)
+        triggerInsetAnimation(container)
+        assertTrue(
+            "The View.onApplyWindowInsets has not been called",
+            onApplyLatch.await(2, TimeUnit.SECONDS)
+        )
+    }
+
+    private fun createCallback(
+        dispatchMode: Int = DISPATCH_MODE_CONTINUE_ON_SUBTREE,
+        onPrepare: ((WindowInsetsAnimationCompat) -> Unit)? = null,
+        onEnd: ((WindowInsetsAnimationCompat) -> Unit)? = null
+    ): WindowInsetsAnimationCompat.Callback {
+        return object :
+            WindowInsetsAnimationCompat.Callback(dispatchMode) {
+
+            override fun onPrepare(animation: WindowInsetsAnimationCompat) {
+                onPrepare?.invoke(animation)
+            }
+
+            override fun onProgress(
+                insets: WindowInsetsCompat,
+                runningAnimations: MutableList<WindowInsetsAnimationCompat>
+            ): WindowInsetsCompat = insets
+
+            override fun onEnd(animation: WindowInsetsAnimationCompat) {
+                onEnd?.invoke(animation)
+            }
+        }
+    }
+
+    @Test
+    @FlakyTest(bugId = 196917541)
     public fun child_callback_not_called_when_dispatch_stop() {
         assumeNotCuttlefish()
 
@@ -473,49 +518,6 @@
         )
     }
 
-    @Test
-    public fun check_view_on_apply_called() {
-        val container = scenario.withActivity { findViewById(R.id.container) }
-        val onApplyLatch = CountDownLatch(1)
-        val customView = object : View(scenario.withActivity { this }) {
-            override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
-                onApplyLatch.countDown()
-                return insets
-            }
-        }
-        scenario.onActivity { (container as ViewGroup).addView(customView) }
-        val stopCallback = createCallback()
-        ViewCompat.setWindowInsetsAnimationCallback(customView, stopCallback)
-        triggerInsetAnimation(container)
-        assertTrue(
-            "The View.onApplyWindowInsets has not been called",
-            onApplyLatch.await(2, TimeUnit.SECONDS)
-        )
-    }
-
-    private fun createCallback(
-        dispatchMode: Int = DISPATCH_MODE_CONTINUE_ON_SUBTREE,
-        onPrepare: ((WindowInsetsAnimationCompat) -> Unit)? = null,
-        onEnd: ((WindowInsetsAnimationCompat) -> Unit)? = null
-    ): WindowInsetsAnimationCompat.Callback {
-        return object :
-            WindowInsetsAnimationCompat.Callback(dispatchMode) {
-
-            override fun onPrepare(animation: WindowInsetsAnimationCompat) {
-                onPrepare?.invoke(animation)
-            }
-
-            override fun onProgress(
-                insets: WindowInsetsCompat,
-                runningAnimations: MutableList<WindowInsetsAnimationCompat>
-            ): WindowInsetsCompat = insets
-
-            override fun onEnd(animation: WindowInsetsAnimationCompat) {
-                onEnd?.invoke(animation)
-            }
-        }
-    }
-
     private fun assumeNotCuttlefish() {
         // TODO: remove this if b/159103848 is resolved
         Assume.assumeFalse(
diff --git a/core/core/src/main/java/androidx/core/app/Person.java b/core/core/src/main/java/androidx/core/app/Person.java
index cb95bb7..32bfb95 100644
--- a/core/core/src/main/java/androidx/core/app/Person.java
+++ b/core/core/src/main/java/androidx/core/app/Person.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -67,13 +68,7 @@
     @NonNull
     @RequiresApi(22)
     public static Person fromPersistableBundle(@NonNull PersistableBundle bundle) {
-        return new Builder()
-                .setName(bundle.getString(NAME_KEY))
-                .setUri(bundle.getString(URI_KEY))
-                .setKey(bundle.getString(KEY_KEY))
-                .setBot(bundle.getBoolean(IS_BOT_KEY))
-                .setImportant(bundle.getBoolean(IS_IMPORTANT_KEY))
-                .build();
+        return Api22Impl.fromPersistableBundle(bundle);
     }
 
     /**
@@ -85,17 +80,7 @@
     @RequiresApi(28)
     @NonNull
     public static Person fromAndroidPerson(@NonNull android.app.Person person) {
-        return new Builder()
-                .setName(person.getName())
-                .setIcon(
-                        (person.getIcon() != null)
-                                ? IconCompat.createFromIcon(person.getIcon())
-                                : null)
-                .setUri(person.getUri())
-                .setKey(person.getKey())
-                .setBot(person.isBot())
-                .setImportant(person.isImportant())
-                .build();
+        return Api28Impl.fromAndroidPerson(person);
     }
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
@@ -148,13 +133,7 @@
     @NonNull
     @RequiresApi(22)
     public PersistableBundle toPersistableBundle() {
-        PersistableBundle result = new PersistableBundle();
-        result.putString(NAME_KEY, mName != null ? mName.toString() : null);
-        result.putString(URI_KEY, mUri);
-        result.putString(KEY_KEY, mKey);
-        result.putBoolean(IS_BOT_KEY, mIsBot);
-        result.putBoolean(IS_IMPORTANT_KEY, mIsImportant);
-        return result;
+        return Api22Impl.toPersistableBundle(this);
     }
 
     /** Creates and returns a new {@link Builder} initialized with this Person's data. */
@@ -172,14 +151,7 @@
     @NonNull
     @RequiresApi(28)
     public android.app.Person toAndroidPerson() {
-        return new android.app.Person.Builder()
-                .setName(getName())
-                .setIcon((getIcon() != null) ? getIcon().toIcon() : null)
-                .setUri(getUri())
-                .setKey(getKey())
-                .setBot(isBot())
-                .setImportant(isImportant())
-                .build();
+        return Api28Impl.toAndroidPerson(this);
     }
 
     /**
@@ -356,4 +328,68 @@
             return new Person(this);
         }
     }
+
+    @RequiresApi(22)
+    static class Api22Impl {
+        private Api22Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static Person fromPersistableBundle(PersistableBundle bundle) {
+            return new Builder()
+                    .setName(bundle.getString(NAME_KEY))
+                    .setUri(bundle.getString(URI_KEY))
+                    .setKey(bundle.getString(KEY_KEY))
+                    .setBot(bundle.getBoolean(IS_BOT_KEY))
+                    .setImportant(bundle.getBoolean(IS_IMPORTANT_KEY))
+                    .build();
+        }
+
+        @DoNotInline
+        static PersistableBundle toPersistableBundle(Person person) {
+            PersistableBundle result = new PersistableBundle();
+            result.putString(NAME_KEY, person.mName != null ? person.mName.toString() : null);
+            result.putString(URI_KEY, person.mUri);
+            result.putString(KEY_KEY, person.mKey);
+            result.putBoolean(IS_BOT_KEY, person.mIsBot);
+            result.putBoolean(IS_IMPORTANT_KEY, person.mIsImportant);
+            return result;
+        }
+    }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static Person fromAndroidPerson(android.app.Person person) {
+            return new Builder()
+                    .setName(person.getName())
+                    .setIcon(
+                            (person.getIcon() != null)
+                                    ? IconCompat.createFromIcon(person.getIcon())
+                                    : null)
+                    .setUri(person.getUri())
+                    .setKey(person.getKey())
+                    .setBot(person.isBot())
+                    .setImportant(person.isImportant())
+                    .build();
+        }
+
+        @SuppressWarnings("deprecation")
+        @DoNotInline
+        static android.app.Person toAndroidPerson(Person person) {
+            return new android.app.Person.Builder()
+                    .setName(person.getName())
+                    .setIcon((person.getIcon() != null) ? person.getIcon().toIcon() : null)
+                    .setUri(person.getUri())
+                    .setKey(person.getKey())
+                    .setBot(person.isBot())
+                    .setImportant(person.isImportant())
+                    .build();
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/RemoteActionCompat.java b/core/core/src/main/java/androidx/core/app/RemoteActionCompat.java
index 8363a1a..9023394 100644
--- a/core/core/src/main/java/androidx/core/app/RemoteActionCompat.java
+++ b/core/core/src/main/java/androidx/core/app/RemoteActionCompat.java
@@ -18,10 +18,13 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
+import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.app.RemoteAction;
+import android.graphics.drawable.Icon;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
@@ -42,24 +45,32 @@
     /**
      * @hide
      */
+    @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field.
+    @NonNull
     @RestrictTo(LIBRARY_GROUP)
     @ParcelField(1)
     public IconCompat mIcon;
     /**
      * @hide
      */
+    @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field.
+    @NonNull
     @RestrictTo(LIBRARY_GROUP)
     @ParcelField(2)
     public CharSequence mTitle;
     /**
      * @hide
      */
+    @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field.
+    @NonNull
     @RestrictTo(LIBRARY_GROUP)
     @ParcelField(3)
     public CharSequence mContentDescription;
     /**
      * @hide
      */
+    @SuppressWarnings("NotNullFieldNotInitialized") // VersionedParceleble inits this field.
+    @NonNull
     @RestrictTo(LIBRARY_GROUP)
     @ParcelField(4)
     public PendingIntent mActionIntent;
@@ -113,12 +124,14 @@
     @NonNull
     public static RemoteActionCompat createFromRemoteAction(@NonNull RemoteAction remoteAction) {
         Preconditions.checkNotNull(remoteAction);
-        RemoteActionCompat action = new RemoteActionCompat(
-                IconCompat.createFromIcon(remoteAction.getIcon()), remoteAction.getTitle(),
-                remoteAction.getContentDescription(), remoteAction.getActionIntent());
-        action.setEnabled(remoteAction.isEnabled());
+        RemoteActionCompat action = new RemoteActionCompat(IconCompat.createFromIcon(
+                Api26Impl.getIcon(remoteAction)),
+                Api26Impl.getTitle(remoteAction),
+                Api26Impl.getContentDescription(remoteAction),
+                Api26Impl.getActionIntent(remoteAction));
+        action.setEnabled(Api26Impl.isEnabled(remoteAction));
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-            action.setShouldShowIcon(remoteAction.shouldShowIcon());
+            action.setShouldShowIcon(Api28Impl.shouldShowIcon(remoteAction));
         }
         return action;
     }
@@ -147,6 +160,7 @@
     /**
      * Return whether the icon should be shown.
      */
+    @SuppressLint("KotlinPropertyAccess")
     public boolean shouldShowIcon() {
         return mShouldShowIcon;
     }
@@ -184,15 +198,76 @@
      *
      * @return {@link RemoteAction} object
      */
+    @SuppressWarnings("deprecation")
     @RequiresApi(26)
     @NonNull
     public RemoteAction toRemoteAction() {
-        RemoteAction action = new RemoteAction(mIcon.toIcon(), mTitle, mContentDescription,
-                mActionIntent);
-        action.setEnabled(isEnabled());
+        RemoteAction action = Api26Impl.createRemoteAction(mIcon.toIcon(), mTitle,
+                mContentDescription, mActionIntent);
+        Api26Impl.setEnabled(action, isEnabled());
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-            action.setShouldShowIcon(shouldShowIcon());
+            Api28Impl.setShouldShowIcon(action, shouldShowIcon());
         }
         return action;
     }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static boolean shouldShowIcon(RemoteAction remoteAction) {
+            return remoteAction.shouldShowIcon();
+        }
+
+        @DoNotInline
+        static void setShouldShowIcon(RemoteAction remoteAction, boolean shouldShowIcon) {
+            remoteAction.setShouldShowIcon(shouldShowIcon);
+        }
+    }
+
+    @RequiresApi(26)
+    static class Api26Impl {
+        private Api26Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static CharSequence getContentDescription(RemoteAction remoteAction) {
+            return remoteAction.getContentDescription();
+        }
+
+        @DoNotInline
+        static PendingIntent getActionIntent(RemoteAction remoteAction) {
+            return remoteAction.getActionIntent();
+        }
+
+        @DoNotInline
+        static CharSequence getTitle(RemoteAction remoteAction) {
+            return remoteAction.getTitle();
+        }
+
+        @DoNotInline
+        static Icon getIcon(RemoteAction remoteAction) {
+            return remoteAction.getIcon();
+        }
+
+        @DoNotInline
+        static boolean isEnabled(RemoteAction remoteAction) {
+            return remoteAction.isEnabled();
+        }
+
+        @DoNotInline
+        static RemoteAction createRemoteAction(Icon icon, CharSequence title,
+                CharSequence contentDescription, PendingIntent intent) {
+            return new RemoteAction(icon, title, contentDescription, intent);
+        }
+
+        @DoNotInline
+        static void setEnabled(RemoteAction remoteAction, boolean enabled) {
+            remoteAction.setEnabled(enabled);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/RemoteInput.java b/core/core/src/main/java/androidx/core/app/RemoteInput.java
index ecbe7de..924e084 100644
--- a/core/core/src/main/java/androidx/core/app/RemoteInput.java
+++ b/core/core/src/main/java/androidx/core/app/RemoteInput.java
@@ -23,6 +23,7 @@
 import android.os.Build;
 import android.os.Bundle;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -40,7 +41,6 @@
  * Helper for using the {@link android.app.RemoteInput}.
  */
 public final class RemoteInput {
-    private static final String TAG = "RemoteInput";
 
     /** Label used to denote the clip data type used for remote input transport */
     public static final String RESULTS_CLIP_LABEL = "android.remoteinput.results";
@@ -112,6 +112,7 @@
      * Get the key that the result of this input will be set in from the Bundle returned by
      * {@link #getResultsFromIntent} when the {@link android.app.PendingIntent} is sent.
      */
+    @NonNull
     public String getResultKey() {
         return mResultKey;
     }
@@ -119,6 +120,7 @@
     /**
      * Get the label to display to users when collecting this input.
      */
+    @Nullable
     public CharSequence getLabel() {
         return mLabel;
     }
@@ -126,10 +128,14 @@
     /**
      * Get possible input choices. This can be {@code null} if there are no choices to present.
      */
+    @SuppressWarnings("NullableCollection") // Look, it's not the best API.
+    @Nullable
     public CharSequence[] getChoices() {
         return mChoices;
     }
 
+    @SuppressWarnings("NullableCollection") // That's just how it was defined.
+    @Nullable
     public Set<String> getAllowedDataTypes() {
         return mAllowedDataTypes;
     }
@@ -167,6 +173,7 @@
     /**
      * Get additional metadata carried around with this remote input.
      */
+    @NonNull
     public Bundle getExtras() {
         return mExtras;
     }
@@ -333,10 +340,12 @@
      *               which also had one or more remote input requested.
      * @param remoteInputResultKey The result key for the RemoteInput you want results for.
      */
+    @SuppressWarnings("NullableCollection") // This is what the platform API does.
+    @Nullable
     public static Map<String, Uri> getDataResultsFromIntent(
-            Intent intent, String remoteInputResultKey) {
+            @NonNull Intent intent, @NonNull String remoteInputResultKey) {
         if (Build.VERSION.SDK_INT >= 26) {
-            return android.app.RemoteInput.getDataResultsFromIntent(intent, remoteInputResultKey);
+            return Api26Impl.getDataResultsFromIntent(intent, remoteInputResultKey);
         } else if (Build.VERSION.SDK_INT >= 16) {
             Intent clipDataIntent = getClipDataIntentFromIntent(intent);
             if (clipDataIntent == null) {
@@ -372,9 +381,11 @@
      * @param intent The intent object that fired in response to an action or content intent
      *               which also had one or more remote input requested.
      */
-    public static Bundle getResultsFromIntent(Intent intent) {
+    @SuppressWarnings("NullableCollection") // This is on purpose.
+    @Nullable
+    public static Bundle getResultsFromIntent(@NonNull Intent intent) {
         if (Build.VERSION.SDK_INT >= 20) {
-            return android.app.RemoteInput.getResultsFromIntent(intent);
+            return Api20Impl.getResultsFromIntent(intent);
         } else if (Build.VERSION.SDK_INT >= 16) {
             Intent clipDataIntent = getClipDataIntentFromIntent(intent);
             if (clipDataIntent == null) {
@@ -397,16 +408,16 @@
      *                be populated with keys matching the result keys specified in
      *                {@code remoteInputs} with values being the result per key.
      */
-    public static void addResultsToIntent(RemoteInput[] remoteInputs, Intent intent,
-            Bundle results) {
+    public static void addResultsToIntent(@NonNull RemoteInput[] remoteInputs,
+            @NonNull Intent intent, @NonNull Bundle results) {
         if (Build.VERSION.SDK_INT >= 26) {
-            android.app.RemoteInput.addResultsToIntent(fromCompat(remoteInputs), intent, results);
+            Api20Impl.addResultsToIntent(fromCompat(remoteInputs), intent, results);
         } else if (Build.VERSION.SDK_INT >= 20) {
             // Implementations of RemoteInput#addResultsToIntent prior to SDK 26 don't actually add
             // results, they wipe out old results and insert the new one. Work around that by
             // preserving old results.
             Bundle existingTextResults =
-                    androidx.core.app.RemoteInput.getResultsFromIntent(intent);
+                    RemoteInput.getResultsFromIntent(intent);
 
             // We also need to preserve the results source, as it is also cleared.
             int resultsSource = getResultsSource(intent);
@@ -419,12 +430,11 @@
             for (RemoteInput input : remoteInputs) {
                 // Data results are also wiped out. So grab them and add them back in.
                 Map<String, Uri> existingDataResults =
-                        androidx.core.app.RemoteInput.getDataResultsFromIntent(
+                        RemoteInput.getDataResultsFromIntent(
                                 intent, input.getResultKey());
                 RemoteInput[] arr = new RemoteInput[1];
                 arr[0] = input;
-                android.app.RemoteInput.addResultsToIntent(
-                        fromCompat(arr), intent, existingTextResults);
+                Api20Impl.addResultsToIntent(fromCompat(arr), intent, existingTextResults);
                 if (existingDataResults != null) {
                     RemoteInput.addDataResultToIntent(input, intent, existingDataResults);
                 }
@@ -449,7 +459,8 @@
                 }
             }
             clipDataIntent.putExtra(RemoteInput.EXTRA_RESULTS_DATA, resultsBundle);
-            intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
+            Api16Impl.setClipData(intent,
+                    ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
         }
     }
 
@@ -457,14 +468,14 @@
      * Same as {@link #addResultsToIntent} but for setting data results.
      * @param remoteInput The remote input for which results are being provided
      * @param intent The intent to add remote input results to. The
-     *               {@link android.content.ClipData} field of the intent will be
+     *               {@link ClipData} field of the intent will be
      *               modified to contain the results.
      * @param results A map of mime type to the Uri result for that mime type.
      */
-    public static void addDataResultToIntent(RemoteInput remoteInput, Intent intent,
-            Map<String, Uri> results) {
+    public static void addDataResultToIntent(@NonNull RemoteInput remoteInput,
+            @NonNull Intent intent, @NonNull Map<String, Uri> results) {
         if (Build.VERSION.SDK_INT >= 26) {
-            android.app.RemoteInput.addDataResultToIntent(fromCompat(remoteInput), intent, results);
+            Api26Impl.addDataResultToIntent(remoteInput, intent, results);
         } else if (Build.VERSION.SDK_INT >= 16) {
             Intent clipDataIntent = getClipDataIntentFromIntent(intent);
             if (clipDataIntent == null) {
@@ -484,7 +495,8 @@
                 resultsBundle.putString(remoteInput.getResultKey(), uri.toString());
                 clipDataIntent.putExtra(getExtraResultsKeyForData(mimeType), resultsBundle);
             }
-            intent.setClipData(ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
+            Api16Impl.setClipData(intent,
+                    ClipData.newIntent(RemoteInput.RESULTS_CLIP_LABEL, clipDataIntent));
         }
     }
 
@@ -503,14 +515,14 @@
      */
     public static void setResultsSource(@NonNull Intent intent, @Source int source) {
         if (Build.VERSION.SDK_INT >= 28) {
-            android.app.RemoteInput.setResultsSource(intent, source);
+            Api28Impl.setResultsSource(intent, source);
         } else if (Build.VERSION.SDK_INT >= 16) {
             Intent clipDataIntent = getClipDataIntentFromIntent(intent);
             if (clipDataIntent == null) {
                 clipDataIntent = new Intent();  // First time we've added a result.
             }
             clipDataIntent.putExtra(EXTRA_RESULTS_SOURCE, source);
-            intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
+            Api16Impl.setClipData(intent, ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
         }
     }
 
@@ -528,7 +540,7 @@
     @Source
     public static int getResultsSource(@NonNull Intent intent) {
         if (Build.VERSION.SDK_INT >= 28) {
-            return android.app.RemoteInput.getResultsSource(intent);
+            return Api28Impl.getResultsSource(intent);
         } else if (Build.VERSION.SDK_INT >= 16) {
             Intent clipDataIntent = getClipDataIntentFromIntent(intent);
             if (clipDataIntent == null) {
@@ -558,51 +570,17 @@
 
     @RequiresApi(20)
     static android.app.RemoteInput fromCompat(RemoteInput src) {
-        android.app.RemoteInput.Builder builder =
-                new android.app.RemoteInput.Builder(src.getResultKey())
-                        .setLabel(src.getLabel())
-                        .setChoices(src.getChoices())
-                        .setAllowFreeFormInput(src.getAllowFreeFormInput())
-                        .addExtras(src.getExtras());
-        if (Build.VERSION.SDK_INT >= 26) {
-            Set<String> allowedDataTypes = src.getAllowedDataTypes();
-            if (allowedDataTypes != null) {
-                for (String allowedDataType : allowedDataTypes) {
-                    builder.setAllowDataType(allowedDataType, true);
-                }
-            }
-        }
-        if (Build.VERSION.SDK_INT >= 29) {
-            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());
-        }
-        return builder.build();
+        return Api20Impl.fromCompat(src);
     }
 
     @RequiresApi(20)
     static RemoteInput fromPlatform(android.app.RemoteInput src) {
-        RemoteInput.Builder builder =
-                new RemoteInput.Builder(src.getResultKey())
-                        .setLabel(src.getLabel())
-                        .setChoices(src.getChoices())
-                        .setAllowFreeFormInput(src.getAllowFreeFormInput())
-                        .addExtras(src.getExtras());
-        if (Build.VERSION.SDK_INT >= 26) {
-            Set<String> allowedDataTypes = src.getAllowedDataTypes();
-            if (allowedDataTypes != null) {
-                for (String allowedDataType : allowedDataTypes) {
-                    builder.setAllowDataType(allowedDataType, true);
-                }
-            }
-        }
-        if (Build.VERSION.SDK_INT >= 29) {
-            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());
-        }
-        return builder.build();
+        return Api20Impl.fromPlatform(src);
     }
 
     @RequiresApi(16)
     private static Intent getClipDataIntentFromIntent(Intent intent) {
-        ClipData clipData = intent.getClipData();
+        ClipData clipData = Api16Impl.getClipData(intent);
         if (clipData == null) {
             return null;
         }
@@ -615,4 +593,147 @@
         }
         return clipData.getItemAt(0).getIntent();
     }
+
+    @RequiresApi(26)
+    static class Api26Impl {
+        private Api26Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static Map<String, Uri> getDataResultsFromIntent(Intent intent,
+                String remoteInputResultKey) {
+            return android.app.RemoteInput.getDataResultsFromIntent(intent, remoteInputResultKey);
+        }
+
+        @DoNotInline
+        static Set<String> getAllowedDataTypes(Object remoteInput) {
+            return ((android.app.RemoteInput) remoteInput).getAllowedDataTypes();
+        }
+
+        @DoNotInline
+        static void addDataResultToIntent(RemoteInput remoteInput, Intent intent,
+                Map<String, Uri> results) {
+            android.app.RemoteInput.addDataResultToIntent(fromCompat(remoteInput), intent, results);
+        }
+
+        @DoNotInline
+        static android.app.RemoteInput.Builder setAllowDataType(
+                android.app.RemoteInput.Builder builder, String mimeType, boolean doAllow) {
+            return builder.setAllowDataType(mimeType, doAllow);
+        }
+    }
+
+    @RequiresApi(20)
+    static class Api20Impl {
+        private Api20Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static Bundle getResultsFromIntent(Intent intent) {
+            return android.app.RemoteInput.getResultsFromIntent(intent);
+        }
+
+        @DoNotInline
+        static void addResultsToIntent(Object remoteInputs, Intent intent, Bundle results) {
+            android.app.RemoteInput.addResultsToIntent((android.app.RemoteInput[]) remoteInputs,
+                    intent, results);
+        }
+
+        static RemoteInput fromPlatform(Object srcObj) {
+            android.app.RemoteInput src = (android.app.RemoteInput) srcObj;
+            Builder builder =
+                    new Builder(src.getResultKey())
+                            .setLabel(src.getLabel())
+                            .setChoices(src.getChoices())
+                            .setAllowFreeFormInput(src.getAllowFreeFormInput())
+                            .addExtras(src.getExtras());
+            if (Build.VERSION.SDK_INT >= 26) {
+                Set<String> allowedDataTypes = Api26Impl.getAllowedDataTypes(src);
+                if (allowedDataTypes != null) {
+                    for (String allowedDataType : allowedDataTypes) {
+                        builder.setAllowDataType(allowedDataType, true);
+                    }
+                }
+            }
+            if (Build.VERSION.SDK_INT >= 29) {
+                builder.setEditChoicesBeforeSending(Api29Impl.getEditChoicesBeforeSending(src));
+            }
+            return builder.build();
+        }
+
+        public static android.app.RemoteInput fromCompat(RemoteInput src) {
+            android.app.RemoteInput.Builder builder =
+                    new android.app.RemoteInput.Builder(src.getResultKey())
+                            .setLabel(src.getLabel())
+                            .setChoices(src.getChoices())
+                            .setAllowFreeFormInput(src.getAllowFreeFormInput())
+                            .addExtras(src.getExtras());
+            if (Build.VERSION.SDK_INT >= 26) {
+                Set<String> allowedDataTypes = src.getAllowedDataTypes();
+                if (allowedDataTypes != null) {
+                    for (String allowedDataType : allowedDataTypes) {
+                        Api26Impl.setAllowDataType(builder, allowedDataType, true);
+                    }
+                }
+            }
+            if (Build.VERSION.SDK_INT >= 29) {
+                Api29Impl.setEditChoicesBeforeSending(builder, src.getEditChoicesBeforeSending());
+            }
+            return builder.build();
+        }
+    }
+
+    @RequiresApi(16)
+    static class Api16Impl {
+        private Api16Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static ClipData getClipData(Intent intent) {
+            return intent.getClipData();
+        }
+
+        @DoNotInline
+        static void setClipData(Intent intent, ClipData clip) {
+            intent.setClipData(clip);
+        }
+    }
+
+    @RequiresApi(29)
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static int getEditChoicesBeforeSending(Object remoteInput) {
+            return ((android.app.RemoteInput) remoteInput).getEditChoicesBeforeSending();
+        }
+
+        @DoNotInline
+        static android.app.RemoteInput.Builder setEditChoicesBeforeSending(
+                android.app.RemoteInput.Builder builder, int editChoicesBeforeSending) {
+            return builder.setEditChoicesBeforeSending(editChoicesBeforeSending);
+        }
+    }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void setResultsSource(Intent intent, int source) {
+            android.app.RemoteInput.setResultsSource(intent, source);
+        }
+
+        @DoNotInline
+        static int getResultsSource(Intent intent) {
+            return android.app.RemoteInput.getResultsSource(intent);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/ServiceCompat.java b/core/core/src/main/java/androidx/core/app/ServiceCompat.java
index 320ece3..e0ef45d 100644
--- a/core/core/src/main/java/androidx/core/app/ServiceCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ServiceCompat.java
@@ -22,8 +22,10 @@
 import android.app.Service;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 
 import java.lang.annotation.Retention;
@@ -97,9 +99,21 @@
     @SuppressWarnings("deprecation")
     public static void stopForeground(@NonNull Service service, @StopForegroundFlags int flags) {
         if (Build.VERSION.SDK_INT >= 24) {
-            service.stopForeground(flags);
+            Api24Impl.stopForeground(service, flags);
         } else {
             service.stopForeground((flags & ServiceCompat.STOP_FOREGROUND_REMOVE) != 0);
         }
     }
+
+    @RequiresApi(24)
+    static class Api24Impl {
+        private Api24Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void stopForeground(Service service, int flags) {
+            service.stopForeground(flags);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/ShareCompat.java b/core/core/src/main/java/androidx/core/app/ShareCompat.java
index 8d6b8ac..c209d4f 100644
--- a/core/core/src/main/java/androidx/core/app/ShareCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ShareCompat.java
@@ -38,6 +38,7 @@
 import android.view.MenuItem;
 import android.widget.ShareActionProvider;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -265,6 +266,7 @@
      *
      * @deprecated Use the system sharesheet. See https://developer.android.com/training/sharing/send
      */
+    @SuppressWarnings("deprecation")
     @Deprecated
     public static void configureMenuItem(@NonNull Menu menu, @IdRes int menuItemId,
             @NonNull IntentBuilder shareIntent) {
@@ -832,7 +834,7 @@
                     result = Html.toHtml((Spanned) text);
                 } else if (text != null) {
                     if (SDK_INT >= 16) {
-                        result = Html.escapeHtml(text);
+                        result = Api16Impl.escapeHtml(text);
                     } else {
                         StringBuilder out = new StringBuilder();
                         withinStyle(out, text, 0, text.length());
@@ -882,7 +884,7 @@
          */
         @Nullable
         public Uri getStream() {
-            return (Uri) mIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+            return mIntent.getParcelableExtra(Intent.EXTRA_STREAM);
         }
 
         /**
@@ -1080,9 +1082,11 @@
 
     @RequiresApi(16)
     private static class Api16Impl {
-        // Prevent instantiation.
-        private Api16Impl() {}
+        private Api16Impl() {
+            // This class is not instantiable.
+        }
 
+        @DoNotInline
         static void migrateExtraStreamToClipData(@NonNull Intent intent,
                 @NonNull ArrayList<Uri> streams) {
             CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_TEXT);
@@ -1101,9 +1105,15 @@
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         }
 
+        @DoNotInline
         static void removeClipData(@NonNull Intent intent) {
             intent.setClipData(null);
             intent.setFlags(intent.getFlags() & ~Intent.FLAG_GRANT_READ_URI_PERMISSION);
         }
+
+        @DoNotInline
+        static String escapeHtml(CharSequence text) {
+            return Html.escapeHtml(text);
+        }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/app/TaskStackBuilder.java b/core/core/src/main/java/androidx/core/app/TaskStackBuilder.java
index 3a881a6c..db30332 100644
--- a/core/core/src/main/java/androidx/core/app/TaskStackBuilder.java
+++ b/core/core/src/main/java/androidx/core/app/TaskStackBuilder.java
@@ -26,8 +26,10 @@
 import android.os.Bundle;
 import android.util.Log;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.core.content.ContextCompat;
 
 import java.util.ArrayList;
@@ -76,7 +78,7 @@
         Intent getSupportParentActivityIntent();
     }
 
-    private final ArrayList<Intent> mIntents = new ArrayList<Intent>();
+    private final ArrayList<Intent> mIntents = new ArrayList<>();
     private final Context mSourceContext;
 
     private TaskStackBuilder(Context a) {
@@ -197,7 +199,8 @@
      *                           this activity will be added
      * @return This TaskStackBuilder for method chaining
      */
-    public TaskStackBuilder addParentStack(ComponentName sourceActivityName) {
+    @NonNull
+    public TaskStackBuilder addParentStack(@NonNull ComponentName sourceActivityName) {
         final int insertAt = mIntents.size();
         try {
             Intent parent = NavUtils.getParentActivityIntent(mSourceContext, sourceActivityName);
@@ -250,6 +253,7 @@
     /**
      * @deprecated Use editIntentAt instead
      */
+    @NonNull
     @Override
     @Deprecated
     public Iterator<Intent> iterator() {
@@ -285,7 +289,7 @@
                     "No intents added to TaskStackBuilder; cannot startActivities");
         }
 
-        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+        Intent[] intents = mIntents.toArray(new Intent[0]);
         intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
         if (!ContextCompat.startActivities(mSourceContext, intents, options)) {
@@ -333,13 +337,12 @@
                     "No intents added to TaskStackBuilder; cannot getPendingIntent");
         }
 
-        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+        Intent[] intents = mIntents.toArray(new Intent[0]);
         intents[0] = new Intent(intents[0]).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
 
         if (Build.VERSION.SDK_INT >= 16) {
-            return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags,
-                    options);
+            return Api16Impl.getActivities(mSourceContext, requestCode, intents, flags, options);
         } else {
             return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags);
         }
@@ -364,4 +367,17 @@
         }
         return intents;
     }
+
+    @RequiresApi(16)
+    static class Api16Impl {
+        private Api16Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static PendingIntent getActivities(Context context, int requestCode, Intent[] intents,
+                int flags, Bundle options) {
+            return PendingIntent.getActivities(context, requestCode, intents, flags, options);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java b/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
index 07547c7..30b9a3d 100644
--- a/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
+++ b/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
@@ -69,6 +69,7 @@
 /**
  * Helper for accessing features in {@link Resources}.
  */
+@SuppressWarnings("unused")
 public final class ResourcesCompat {
     private static final String TAG = "ResourcesCompat";
     private static final ThreadLocal<TypedValue> sTempTypedValue = new ThreadLocal<>();
@@ -274,7 +275,8 @@
                 final ColorStateListCacheEntry entry = entries.get(resId);
                 if (entry != null) {
                     if (entry.mConfiguration.equals(key.mResources.getConfiguration())
-                            && entry.mThemeHash == key.mTheme.hashCode()) {
+                            && ((key.mTheme == null && entry.mThemeHash == 0)
+                            || (key.mTheme != null && entry.mThemeHash == key.mTheme.hashCode()))) {
                         // If the current configuration matches the entry's, we can use it
                         return entry.mValue;
                     } else {
diff --git a/core/core/src/main/java/androidx/core/database/CursorWindowCompat.java b/core/core/src/main/java/androidx/core/database/CursorWindowCompat.java
index 01a48df..03b0c8f 100644
--- a/core/core/src/main/java/androidx/core/database/CursorWindowCompat.java
+++ b/core/core/src/main/java/androidx/core/database/CursorWindowCompat.java
@@ -19,16 +19,18 @@
 import android.database.CursorWindow;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 /**
- * Helper for accessing features in {@link android.database.CursorWindow}
+ * Helper for accessing features in {@link CursorWindow}
  */
 public final class CursorWindowCompat {
 
     private CursorWindowCompat() {
-        /* Hide constructor */
+        // This class is not instantiable.
     }
 
     /**
@@ -40,11 +42,35 @@
     @NonNull
     public static CursorWindow create(@Nullable String name, long windowSizeBytes) {
         if (Build.VERSION.SDK_INT >= 28) {
-            return new CursorWindow(name, windowSizeBytes);
+            return Api28Impl.createCursorWindow(name, windowSizeBytes);
         } else if (Build.VERSION.SDK_INT >= 15) {
-            return new CursorWindow(name);
+            return Api15Impl.createCursorWindow(name);
         } else {
             return new CursorWindow(false);
         }
     }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static CursorWindow createCursorWindow(String name, long windowSizeBytes) {
+            return new CursorWindow(name, windowSizeBytes);
+        }
+    }
+
+    @RequiresApi(15)
+    static class Api15Impl {
+        private Api15Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static CursorWindow createCursorWindow(String name) {
+            return new CursorWindow(name);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java b/core/core/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java
index e46713c..1a2225e 100644
--- a/core/core/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java
+++ b/core/core/src/main/java/androidx/core/database/sqlite/SQLiteCursorCompat.java
@@ -16,18 +16,21 @@
 
 package androidx.core.database.sqlite;
 
+import android.database.AbstractWindowedCursor;
 import android.database.sqlite.SQLiteCursor;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 /**
- * Helper for accessing features in {@link android.database.AbstractWindowedCursor}
+ * Helper for accessing features in {@link AbstractWindowedCursor}
  */
 public final class SQLiteCursorCompat {
 
     private SQLiteCursorCompat() {
-        /* Hide constructor */
+        // This class is not instantiable.
     }
 
     /**
@@ -43,6 +46,18 @@
     public static void setFillWindowForwardOnly(
             @NonNull SQLiteCursor cursor, boolean fillWindowForwardOnly) {
         if (Build.VERSION.SDK_INT >= 28) {
+            Api28Impl.setFillWindowForwardOnly(cursor, fillWindowForwardOnly);
+        }
+    }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void setFillWindowForwardOnly(SQLiteCursor cursor, boolean fillWindowForwardOnly) {
             cursor.setFillWindowForwardOnly(fillWindowForwardOnly);
         }
     }
diff --git a/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java b/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
index 9902c00..aae8d3d 100644
--- a/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
@@ -18,38 +18,110 @@
 import android.graphics.Bitmap;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 
 /**
- * Helper for accessing features in {@link android.graphics.Bitmap}.
+ * Helper for accessing features in {@link Bitmap}.
  */
 public final class BitmapCompat {
+
+    /**
+     * Indicates whether the renderer responsible for drawing this
+     * bitmap should attempt to use mipmaps when this bitmap is drawn
+     * scaled down.
+     * <p>
+     * If you know that you are going to draw this bitmap at less than
+     * 50% of its original size, you may be able to obtain a higher
+     * quality
+     * <p>
+     * This property is only a suggestion that can be ignored by the
+     * renderer. It is not guaranteed to have any effect.
+     *
+     * @return true if the renderer should attempt to use mipmaps,
+     *         false otherwise
+     *
+     * @see Bitmap#hasMipMap()
+     */
     public static boolean hasMipMap(@NonNull Bitmap bitmap) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            return bitmap.hasMipMap();
+        if (Build.VERSION.SDK_INT >= 17) {
+            return Api17Impl.hasMipMap(bitmap);
         }
         return false;
     }
 
+    /**
+     * Set a hint for the renderer responsible for drawing this bitmap
+     * indicating that it should attempt to use mipmaps when this bitmap
+     * is drawn scaled down.
+     * <p>
+     * If you know that you are going to draw this bitmap at less than
+     * 50% of its original size, you may be able to obtain a higher
+     * quality by turning this property on.
+     * <p>
+     * Note that if the renderer respects this hint it might have to
+     * allocate extra memory to hold the mipmap levels for this bitmap.
+     * <p>
+     * This property is only a suggestion that can be ignored by the
+     * renderer. It is not guaranteed to have any effect.
+     *
+     * @param hasMipMap indicates whether the renderer should attempt
+     *                  to use mipmaps
+     *
+     * @see Bitmap#setHasMipMap(boolean)
+     *
+     */
     public static void setHasMipMap(@NonNull Bitmap bitmap, boolean hasMipMap) {
-        if (Build.VERSION.SDK_INT >= 18) {
-            bitmap.setHasMipMap(hasMipMap);
+        if (Build.VERSION.SDK_INT >= 17) {
+            Api17Impl.setHasMipMap(bitmap, hasMipMap);
         }
     }
 
     /**
-     * Returns the size of the allocated memory used to store this bitmap's pixels in a backwards
-     * compatible way.
+     * Returns the size of the allocated memory used to store this bitmap's pixels.
+     * <p>
+     * This value will not change over the lifetime of a Bitmap.
      *
-     * @param bitmap the bitmap in which to return its allocation size
-     * @return the allocation size in bytes
+     * @see Bitmap#getAllocationByteCount()
      */
     public static int getAllocationByteCount(@NonNull Bitmap bitmap) {
         if (Build.VERSION.SDK_INT >= 19) {
-            return bitmap.getAllocationByteCount();
+            return Api19Impl.getAllocationByteCount(bitmap);
         }
         return bitmap.getByteCount();
     }
 
-    private BitmapCompat() {}
+    private BitmapCompat() {
+        // This class is not instantiable.
+    }
+
+    @RequiresApi(17)
+    static class Api17Impl {
+        private Api17Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static boolean hasMipMap(Bitmap bitmap) {
+            return bitmap.hasMipMap();
+        }
+
+        @DoNotInline
+        static void setHasMipMap(Bitmap bitmap, boolean hasMipMap) {
+            bitmap.setHasMipMap(hasMipMap);
+        }
+    }
+
+    @RequiresApi(19)
+    static class Api19Impl {
+        private Api19Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static int getAllocationByteCount(Bitmap bitmap) {
+            return bitmap.getAllocationByteCount();
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/graphics/BlendModeColorFilterCompat.java b/core/core/src/main/java/androidx/core/graphics/BlendModeColorFilterCompat.java
index 1843c25..cff8d8f 100644
--- a/core/core/src/main/java/androidx/core/graphics/BlendModeColorFilterCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/BlendModeColorFilterCompat.java
@@ -23,8 +23,10 @@
 import android.graphics.PorterDuffColorFilter;
 import android.os.Build;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 /**
  * Helper for accessing ColorFilter APIs on various API levels of the platform
@@ -32,17 +34,19 @@
 public class BlendModeColorFilterCompat {
 
     /**
-     * Convenience method to create ColorFilter in a backward
-     * compatible way. This method falls back on PorterDuffColorFilter for API levels that
-     * do not support BlendModeColorFilter. This method returns null if the BlendMode provided is
-     * not supported on a given API level.
+     * Convenience method to create ColorFilter in a backward-compatible way.
+     *
+     * This method falls back on PorterDuffColorFilter for API levels that do not support
+     * BlendModeColorFilter. This method returns {@code null} if the BlendMode provided is not
+     * supported on a given API level.
      */
     public static @Nullable ColorFilter createBlendModeColorFilterCompat(int color,
             @NonNull BlendModeCompat blendModeCompat) {
         if (Build.VERSION.SDK_INT >= 29) {
-            BlendMode blendMode = BlendModeUtils.obtainBlendModeFromCompat(blendModeCompat);
+            Object blendMode =
+                    BlendModeUtils.Api29Impl.obtainBlendModeFromCompat(blendModeCompat);
             return blendMode != null
-                    ? new BlendModeColorFilter(color, blendMode) : null;
+                    ? Api29Impl.createBlendModeColorFilter(color, blendMode) : null;
         } else {
             PorterDuff.Mode porterDuffMode =
                     BlendModeUtils.obtainPorterDuffFromCompat(blendModeCompat);
@@ -51,5 +55,19 @@
         }
     }
 
-    private BlendModeColorFilterCompat() { }
+    private BlendModeColorFilterCompat() {
+        // This class is not instantiable.
+    }
+
+    @RequiresApi(29)
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static ColorFilter createBlendModeColorFilter(int color, Object mode) {
+            return new BlendModeColorFilter(color, (BlendMode) mode);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/graphics/BlendModeUtils.java b/core/core/src/main/java/androidx/core/graphics/BlendModeUtils.java
index a5188a5..feb339b 100644
--- a/core/core/src/main/java/androidx/core/graphics/BlendModeUtils.java
+++ b/core/core/src/main/java/androidx/core/graphics/BlendModeUtils.java
@@ -19,6 +19,7 @@
 import android.graphics.BlendMode;
 import android.graphics.PorterDuff;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -27,123 +28,131 @@
  * Utility class used to map BlendModeCompat parameters to the corresponding
  * PorterDuff mode or BlendMode depending on the API level of the platform
  */
-/* package */ class BlendModeUtils {
+class BlendModeUtils {
+    private BlendModeUtils() {
+        // This class is not instantiable.
+    }
 
     @RequiresApi(29)
-    /* package */ static @Nullable BlendMode obtainBlendModeFromCompat(
-            @NonNull BlendModeCompat blendModeCompat) {
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        @Nullable
+        static Object obtainBlendModeFromCompat(@NonNull BlendModeCompat blendModeCompat) {
+            switch (blendModeCompat) {
+                case CLEAR:
+                    return BlendMode.CLEAR;
+                case SRC:
+                    return BlendMode.SRC;
+                case DST:
+                    return BlendMode.DST;
+                case SRC_OVER:
+                    return BlendMode.SRC_OVER;
+                case DST_OVER:
+                    return BlendMode.DST_OVER;
+                case SRC_IN:
+                    return BlendMode.SRC_IN;
+                case DST_IN:
+                    return BlendMode.DST_IN;
+                case SRC_OUT:
+                    return BlendMode.SRC_OUT;
+                case DST_OUT:
+                    return BlendMode.DST_OUT;
+                case SRC_ATOP:
+                    return BlendMode.SRC_ATOP;
+                case DST_ATOP:
+                    return BlendMode.DST_ATOP;
+                case XOR:
+                    return BlendMode.XOR;
+                case PLUS:
+                    return BlendMode.PLUS;
+                case MODULATE:
+                    return BlendMode.MODULATE;
+                case SCREEN:
+                    return BlendMode.SCREEN;
+                case OVERLAY:
+                    return BlendMode.OVERLAY;
+                case DARKEN:
+                    return BlendMode.DARKEN;
+                case LIGHTEN:
+                    return BlendMode.LIGHTEN;
+                case COLOR_DODGE:
+                    return BlendMode.COLOR_DODGE;
+                case COLOR_BURN:
+                    return BlendMode.COLOR_BURN;
+                case HARD_LIGHT:
+                    return BlendMode.HARD_LIGHT;
+                case SOFT_LIGHT:
+                    return BlendMode.SOFT_LIGHT;
+                case DIFFERENCE:
+                    return BlendMode.DIFFERENCE;
+                case EXCLUSION:
+                    return BlendMode.EXCLUSION;
+                case MULTIPLY:
+                    return BlendMode.MULTIPLY;
+                case HUE:
+                    return BlendMode.HUE;
+                case SATURATION:
+                    return BlendMode.SATURATION;
+                case COLOR:
+                    return BlendMode.COLOR;
+                case LUMINOSITY:
+                    return BlendMode.LUMINOSITY;
+                default:
+                    return null;
+            }
+        }
+    }
+
+    static @Nullable PorterDuff.Mode obtainPorterDuffFromCompat(
+            @Nullable BlendModeCompat blendModeCompat) {
+        if (blendModeCompat == null) {
+            return null;
+        }
+
         switch (blendModeCompat) {
             case CLEAR:
-                return BlendMode.CLEAR;
+                return PorterDuff.Mode.CLEAR;
             case SRC:
-                return BlendMode.SRC;
+                return PorterDuff.Mode.SRC;
             case DST:
-                return BlendMode.DST;
+                return PorterDuff.Mode.DST;
             case SRC_OVER:
-                return BlendMode.SRC_OVER;
+                return PorterDuff.Mode.SRC_OVER;
             case DST_OVER:
-                return BlendMode.DST_OVER;
+                return PorterDuff.Mode.DST_OVER;
             case SRC_IN:
-                return BlendMode.SRC_IN;
+                return PorterDuff.Mode.SRC_IN;
             case DST_IN:
-                return BlendMode.DST_IN;
+                return PorterDuff.Mode.DST_IN;
             case SRC_OUT:
-                return BlendMode.SRC_OUT;
+                return PorterDuff.Mode.SRC_OUT;
             case DST_OUT:
-                return BlendMode.DST_OUT;
+                return PorterDuff.Mode.DST_OUT;
             case SRC_ATOP:
-                return BlendMode.SRC_ATOP;
+                return PorterDuff.Mode.SRC_ATOP;
             case DST_ATOP:
-                return BlendMode.DST_ATOP;
+                return PorterDuff.Mode.DST_ATOP;
             case XOR:
-                return BlendMode.XOR;
+                return PorterDuff.Mode.XOR;
             case PLUS:
-                return BlendMode.PLUS;
+                return PorterDuff.Mode.ADD;
+            // b/73224934 PorterDuff Multiply maps to Skia Modulate
             case MODULATE:
-                return BlendMode.MODULATE;
+                return PorterDuff.Mode.MULTIPLY;
             case SCREEN:
-                return BlendMode.SCREEN;
+                return PorterDuff.Mode.SCREEN;
             case OVERLAY:
-                return BlendMode.OVERLAY;
+                return PorterDuff.Mode.OVERLAY;
             case DARKEN:
-                return BlendMode.DARKEN;
+                return PorterDuff.Mode.DARKEN;
             case LIGHTEN:
-                return BlendMode.LIGHTEN;
-            case COLOR_DODGE:
-                return BlendMode.COLOR_DODGE;
-            case COLOR_BURN:
-                return BlendMode.COLOR_BURN;
-            case HARD_LIGHT:
-                return BlendMode.HARD_LIGHT;
-            case SOFT_LIGHT:
-                return BlendMode.SOFT_LIGHT;
-            case DIFFERENCE:
-                return BlendMode.DIFFERENCE;
-            case EXCLUSION:
-                return BlendMode.EXCLUSION;
-            case MULTIPLY:
-                return BlendMode.MULTIPLY;
-            case HUE:
-                return BlendMode.HUE;
-            case SATURATION:
-                return BlendMode.SATURATION;
-            case COLOR:
-                return BlendMode.COLOR;
-            case LUMINOSITY:
-                return BlendMode.LUMINOSITY;
+                return PorterDuff.Mode.LIGHTEN;
             default:
                 return null;
         }
     }
-
-    /* package */ static @Nullable PorterDuff.Mode obtainPorterDuffFromCompat(
-            @Nullable BlendModeCompat blendModeCompat) {
-        if (blendModeCompat != null) {
-            switch (blendModeCompat) {
-                case CLEAR:
-                    return PorterDuff.Mode.CLEAR;
-                case SRC:
-                    return PorterDuff.Mode.SRC;
-                case DST:
-                    return PorterDuff.Mode.DST;
-                case SRC_OVER:
-                    return PorterDuff.Mode.SRC_OVER;
-                case DST_OVER:
-                    return PorterDuff.Mode.DST_OVER;
-                case SRC_IN:
-                    return PorterDuff.Mode.SRC_IN;
-                case DST_IN:
-                    return PorterDuff.Mode.DST_IN;
-                case SRC_OUT:
-                    return PorterDuff.Mode.SRC_OUT;
-                case DST_OUT:
-                    return PorterDuff.Mode.DST_OUT;
-                case SRC_ATOP:
-                    return PorterDuff.Mode.SRC_ATOP;
-                case DST_ATOP:
-                    return PorterDuff.Mode.DST_ATOP;
-                case XOR:
-                    return PorterDuff.Mode.XOR;
-                case PLUS:
-                    return PorterDuff.Mode.ADD;
-                // b/73224934 PorterDuff Multiply maps to Skia Modulate
-                case MODULATE:
-                    return PorterDuff.Mode.MULTIPLY;
-                case SCREEN:
-                    return PorterDuff.Mode.SCREEN;
-                case OVERLAY:
-                    return PorterDuff.Mode.OVERLAY;
-                case DARKEN:
-                    return PorterDuff.Mode.DARKEN;
-                case LIGHTEN:
-                    return PorterDuff.Mode.LIGHTEN;
-                default:
-                    return null;
-            }
-        } else {
-            return null;
-        }
-    }
-
-    private BlendModeUtils() { }
 }
diff --git a/core/core/src/main/java/androidx/core/graphics/PaintCompat.java b/core/core/src/main/java/androidx/core/graphics/PaintCompat.java
index 73862de..4503d2c 100644
--- a/core/core/src/main/java/androidx/core/graphics/PaintCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/PaintCompat.java
@@ -16,7 +16,6 @@
 
 package androidx.core.graphics;
 
-import static androidx.core.graphics.BlendModeUtils.obtainBlendModeFromCompat;
 import static androidx.core.graphics.BlendModeUtils.obtainPorterDuffFromCompat;
 
 import android.graphics.BlendMode;
@@ -127,8 +126,9 @@
      */
     public static boolean setBlendMode(@NonNull Paint paint, @Nullable BlendModeCompat blendMode) {
         if (Build.VERSION.SDK_INT >= 29) {
-            Api29Impl.setBlendMode(paint,
-                    blendMode != null ? obtainBlendModeFromCompat(blendMode) : null);
+            Object blendModePlatform = blendMode != null
+                    ? BlendModeUtils.Api29Impl.obtainBlendModeFromCompat(blendMode) : null;
+            Api29Impl.setBlendMode(paint, blendModePlatform);
             // All blend modes supported in Q
             return true;
         } else if (blendMode != null) {
@@ -160,6 +160,18 @@
     private PaintCompat() {
     }
 
+    @RequiresApi(29)
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void setBlendMode(Paint paint, Object blendmode) {
+            paint.setBlendMode((BlendMode) blendmode);
+        }
+    }
+
     @RequiresApi(23)
     static class Api23Impl {
         private Api23Impl() {
@@ -171,16 +183,4 @@
             return paint.hasGlyph(string);
         }
     }
-
-    @RequiresApi(29)
-    static class Api29Impl {
-        private Api29Impl() {
-            // This class is not instantiable.
-        }
-
-        @DoNotInline
-        static void setBlendMode(Paint paint, BlendMode blendmode) {
-            paint.setBlendMode(blendmode);
-        }
-    }
 }
diff --git a/docs/api_guidelines.md b/docs/api_guidelines.md
index c60844cd..e732660 100644
--- a/docs/api_guidelines.md
+++ b/docs/api_guidelines.md
@@ -153,13 +153,13 @@
 library at the same time and release all libraries at the same time.
 
 Atomic groups are specified in
-[`LibraryGroups.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/public/src/main/kotlin/androidx/build/LibraryGroups.kt):
+[libraryversions.toml](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:libraryversions.toml):
 
-```kotlin
+```
 // Non-atomic library group
-val APPCOMPAT = LibraryGroup("androidx.appcompat", null)
+APPCOMPAT = { group = "androidx.appcompat" }
 // Atomic library group
-val APPSEARCH = LibraryGroup("androidx.appsearch", LibraryVersions.APPSEARCH)
+APPSEARCH = { group = "androidx.appsearch", atomicGroupVersion = "versions.APPSEARCH" }
 ```
 
 Libraries within an atomic group should not specify a version in their
diff --git a/docs/benchmarking.md b/docs/benchmarking.md
index c54786a..f138231 100644
--- a/docs/benchmarking.md
+++ b/docs/benchmarking.md
@@ -76,25 +76,46 @@
 
 ### I'm lazy and want to start quickly
 
-Start by copying one of the following projects:
+Start by copying one of the following non-Compose projects:
 
 *   [navigation-benchmark](https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-main/navigation/benchmark/)
 *   [recyclerview-benchmark](https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-main/recyclerview/recyclerview-benchmark/)
 
-### Compose
+Many Compose libraries already have benchmark modules:
 
-Compose builds the benchmark from source, so usage matches the rest of the
-AndroidX project. See existing Compose benchmark projects:
-
-*   [Compose UI benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/integration-tests/benchmark/)
-*   [Compose Runtime benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/runtime/runtime/compose-runtime-benchmark/)
+*   [Compose UI Benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui/benchmark/)
+*   [Compose Runtime Benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/runtime/runtime/compose-runtime-benchmark/)
+*   [Compose Material Benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/benchmark/)
+*   [Wear Compose Material Benchmarks](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:wear/compose/compose-material/benchmark/)
 
 ## Profiling
 
-### Command Line
+See the
+[public profiling guide](https://developer.android.com/studio/profile/benchmark#profiling)
+for more details.
 
-The benchmark library supports capturing profiling information - stack sampling
-and method tracing - from the command line. Here's an example which runs the
+Jetpack benchmark supports capturing profiling information by setting
+instrumentation arguments. Stack sampling and method tracing can be performed
+either from CLI or Studio invocation.
+
+### Set Arguments in Gradle
+
+Args can be set in your benchmark's `build.gradle`, which will affect both
+Studio / command-line gradlew runs. Runs from Studio will link result traces
+that can be opened directly from the IDE.
+
+```
+android {
+    defaultConfig {
+        // must be one of: 'None', 'StackSampling', or 'MethodTracing'
+        testInstrumentationRunnerArgument 'androidx.benchmark.profiling.mode', 'StackSampling'
+    }
+}
+```
+
+### Set Arguments on Command Line
+
+Args can also be passed from CLI. Here's an example which runs the
 `androidx.compose.material.benchmark.CheckboxesInRowsBenchmark#draw` method with
 `StackSampling` profiling:
 
@@ -130,16 +151,15 @@
 
 ![Sample flame chart](benchmarking_images/profiling_flame_chart.png "Sample flame chart")
 
-NOTE Simpleperf captures stack traces from all threads, so click the test thread
-in the left profiler panel, and select flame chart on the right to see just
-samples from the test.
+### Advanced: Connected Studio Profiler
 
-### Advanced: Studio Profiling
+Profiling for allocations requires Studio to capture. This can also be used for
+Sampled profiling, though it is instead recommended to use instrumentation
+argument profiling for that, as it's simpler, and doesn't require
+`debuggable=true`
 
-Profiling for allocations and simpleperf profiling requires Studio to capture.
-
-Studio profiling tools require `debuggable=true`. First, temporarily override it
-in your benchmark's `androidTest/AndroidManifest.xml`.
+Studio profiling tools currently require `debuggable=true`. First, temporarily
+override it in your benchmark's `androidTest/AndroidManifest.xml`.
 
 Next choose which profiling you want to do: Allocation, or Sampled (SimplePerf)
 
diff --git a/docs/lint_guide.md b/docs/lint_guide.md
index a3fc49f..9a0fdb7 100644
--- a/docs/lint_guide.md
+++ b/docs/lint_guide.md
@@ -446,15 +446,19 @@
 
 ```kotlin
 override fun visitElement(context: XmlContext, element: Element) {
-    context.report(
-        ISSUE,
-        context.getNameLocation(element),
-        "My issue message",
-        fix().replace()
-            .text(ELEMENT)
-            .with(REPLACEMENT TEXT)
-            .build()
-    )
+    val lintFix = fix().replace()
+        .text(ELEMENT)
+        .with(REPLACEMENT TEXT)
+        .build()
+
+    val incident = Incident(context)
+        .fix(lintFix)
+        .issue(ISSUE)
+        .location(context.getLocation(node))
+        .message("My issue message")
+        .scope(context.getNameLocation(element))
+
+    context.report(incident)
 }
 ```
 
diff --git a/docs/versioning.md b/docs/versioning.md
index 88250d7..42bec31 100644
--- a/docs/versioning.md
+++ b/docs/versioning.md
@@ -339,8 +339,7 @@
 
 ### How to update your version
 
-1.  Update the version listed in
-    `frameworks/support/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt`
+1.  Update the version listed in `frameworks/support/libraryversions.toml`
 1.  If your library is a `beta` or `rc01` version, run `./gradlew
     <your-lib>:updateApi`. This will create an API txt file for the new version
     of your library. For other versions, this step is not reqired
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml b/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml
index 8185c92..6e0b227 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml
@@ -186,5 +186,18 @@
                 android:name="android.appwidget.provider"
                 android:resource="@xml/default_app_widget_info" />
         </receiver>
+
+        <receiver
+            android:name="androidx.glance.appwidget.demos.ProgressIndicatorAppWidgetReceiver"
+            android:label="@string/progress_indicator_widget_name"
+            android:enabled="@bool/glance_appwidget_available"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data
+                android:name="android.appwidget.provider"
+                android:resource="@xml/default_app_widget_info" />
+        </receiver>
     </application>
 </manifest>
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ProgressIndicatorAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ProgressIndicatorAppWidget.kt
new file mode 100644
index 0000000..ed6e9b7
--- /dev/null
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ProgressIndicatorAppWidget.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.glance.appwidget.demos
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.dp
+import androidx.glance.GlanceModifier
+import androidx.glance.appwidget.CircularProgressIndicator
+import androidx.glance.appwidget.GlanceAppWidget
+import androidx.glance.appwidget.GlanceAppWidgetReceiver
+import androidx.glance.appwidget.LinearProgressIndicator
+import androidx.glance.background
+import androidx.glance.layout.Alignment
+import androidx.glance.layout.Column
+import androidx.glance.layout.Spacer
+import androidx.glance.layout.fillMaxSize
+import androidx.glance.layout.size
+
+class ProgressIndicatorAppWidget : GlanceAppWidget() {
+
+    @Composable
+    override fun Content() {
+        Column(
+            modifier = GlanceModifier.fillMaxSize().background(R.color.default_widget_background),
+            verticalAlignment = Alignment.CenterVertically,
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            LinearProgressIndicator()
+            Spacer(GlanceModifier.size(8.dp))
+            LinearProgressIndicator(0.5f)
+            Spacer(GlanceModifier.size(8.dp))
+            CircularProgressIndicator()
+        }
+    }
+}
+
+class ProgressIndicatorAppWidgetReceiver : GlanceAppWidgetReceiver() {
+    override val glanceAppWidget: GlanceAppWidget = ProgressIndicatorAppWidget()
+}
\ No newline at end of file
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ScrollableAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ScrollableAppWidget.kt
index d66af66..7de3980 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ScrollableAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ScrollableAppWidget.kt
@@ -39,16 +39,15 @@
 import androidx.glance.action.actionParametersOf
 import androidx.glance.action.clickable
 import androidx.glance.appwidget.CheckBox
-import androidx.glance.appwidget.CircularProgressIndicator
 import androidx.glance.appwidget.GlanceAppWidget
 import androidx.glance.appwidget.GlanceAppWidgetReceiver
-import androidx.glance.appwidget.LinearProgressIndicator
 import androidx.glance.appwidget.SizeMode
 import androidx.glance.appwidget.action.ActionCallback
 import androidx.glance.appwidget.action.ToggleableStateKey
 import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.appwidget.action.actionStartActivity
 import androidx.glance.appwidget.demos.ScrollableAppWidget.Companion.CheckboxKey
+import androidx.glance.appwidget.lazy.GridCells
 import androidx.glance.appwidget.lazy.LazyColumn
 import androidx.glance.appwidget.lazy.itemsIndexed
 import androidx.glance.appwidget.state.updateAppWidgetState
@@ -89,9 +88,6 @@
         Column(
             modifier = GlanceModifier.fillMaxSize().background(R.color.default_widget_background)
         ) {
-            LinearProgressIndicator()
-            LinearProgressIndicator(0.5f)
-            CircularProgressIndicator()
             Text(
                 text = "Fix header",
                 modifier = GlanceModifier
@@ -100,16 +96,14 @@
                     .background(Color(0x0a000000))
             )
             val width = LocalSize.current.width
-            if (width <= singleColumn.width) {
-                ScrollColumn(GlanceModifier.fillMaxSize())
-            } else {
-                Row {
+            when {
+                width <= singleColumn.width -> ScrollColumn(GlanceModifier.fillMaxSize())
+                width <= doubleColumn.width -> Row {
                     val modifier = GlanceModifier.fillMaxHeight().defaultWeight()
                     ScrollColumn(modifier)
-                    if (width >= tripleColumn.width) {
-                        ScrollColumn(modifier)
-                    }
+                    ScrollColumn(modifier)
                 }
+                else -> SampleGrid(cells = GridCells.Fixed(3))
             }
         }
     }
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/VerticalGridAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/VerticalGridAppWidget.kt
index 8ae60bc..2f8de3f 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/VerticalGridAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/VerticalGridAppWidget.kt
@@ -17,72 +17,74 @@
 package androidx.glance.appwidget.demos
 
 import android.content.Intent
-import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.glance.Button
 import androidx.glance.GlanceModifier
 import androidx.glance.LocalContext
-import androidx.glance.action.actionStartActivity
 import androidx.glance.appwidget.GlanceAppWidget
 import androidx.glance.appwidget.GlanceAppWidgetReceiver
 import androidx.glance.appwidget.action.actionStartActivity
 import androidx.glance.appwidget.appWidgetBackground
 import androidx.glance.appwidget.cornerRadius
-import androidx.glance.appwidget.lazy.LazyVerticalGrid
 import androidx.glance.appwidget.lazy.GridCells
+import androidx.glance.appwidget.lazy.LazyVerticalGrid
 import androidx.glance.appwidget.lazy.itemsIndexed
+import androidx.glance.background
 import androidx.glance.layout.Alignment
-import androidx.glance.layout.Column
 import androidx.glance.layout.Row
-import androidx.glance.layout.fillMaxHeight
 import androidx.glance.layout.fillMaxSize
 import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
-import androidx.glance.state.PreferencesGlanceStateDefinition
 import androidx.glance.text.Text
 
 class VerticalGridAppWidget : GlanceAppWidget() {
 
-  override val stateDefinition = PreferencesGlanceStateDefinition
+    @Composable
+    override fun Content() {
+        SampleGrid(
+            cells = GridCells.Adaptive,
+            modifier = GlanceModifier.padding(R.dimen.external_padding)
+                .fillMaxSize()
+                .appWidgetBackground()
+                .cornerRadius(R.dimen.corner_radius)
+                .background(R.color.default_widget_background)
+        )
+    }
+}
 
-  @Composable
-  override fun Content() {
-        Column(
-            modifier = GlanceModifier.padding(R.dimen.external_padding).fillMaxSize()
-                .appWidgetBackground().cornerRadius(R.dimen.corner_radius),
-            verticalAlignment = Alignment.Vertical.CenterVertically,
-            horizontalAlignment = Alignment.Horizontal.CenterHorizontally
-        ) {
-          val modifier = GlanceModifier.fillMaxHeight().defaultWeight()
-          LazyVerticalGrid(gridCells = GridCells.Fixed(2), modifier) {
-            item { Text("LazyVerticalGrid") }
-            items(2, { it * 2L }) { index -> Text("Item $index") }
-            itemsIndexed(
+@Composable
+fun SampleGrid(cells: GridCells, modifier: GlanceModifier = GlanceModifier.fillMaxSize()) {
+    LazyVerticalGrid(
+        modifier = modifier,
+        gridCells = cells
+    ) {
+        item {
+            Text("LazyVerticalGrid")
+        }
+        items(count = 20, itemId = { it * 2L }) { index ->
+            Text("Item $index")
+        }
+        itemsIndexed(
             listOf(
                 GlanceAppWidgetDemoActivity::class.java,
                 ListClickDestinationActivity::class.java
             )
         ) { index, activityClass ->
             Row(
-                GlanceModifier.fillMaxWidth(),
+                modifier = GlanceModifier.fillMaxWidth(),
                 horizontalAlignment = Alignment.Horizontal.CenterHorizontally
             ) {
                 Button(
                     text = "Activity ${index + 1}",
                     onClick = actionStartActivity(
-                        Intent(
-                            LocalContext.current,
-                            activityClass
-                        )
+                        Intent(LocalContext.current, activityClass)
                     )
                 )
             }
         }
-        }
     }
-  }
 }
 
 class VerticalGridAppWidgetReceiver : GlanceAppWidgetReceiver() {
-  override val glanceAppWidget: GlanceAppWidget = VerticalGridAppWidget()
+    override val glanceAppWidget: GlanceAppWidget = VerticalGridAppWidget()
 }
\ No newline at end of file
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/res/values/strings.xml b/glance/glance-appwidget/integration-tests/demos/src/main/res/values/strings.xml
index 3820d2b..ce122d4 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/res/values/strings.xml
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/res/values/strings.xml
@@ -31,4 +31,5 @@
     <string name="image_widget_name">Image Widget</string>
     <string name="grid_widget_name">Vertical Grid Widget</string>
     <string name="default_state_widget_name">Default State Widget</string>
+    <string name="progress_indicator_widget_name">ProgressBar Widget</string>
 </resources>
diff --git a/health/health-data-client/OWNERS b/health/health-data-client/OWNERS
index 851a73b..e66c7f0 100644
--- a/health/health-data-client/OWNERS
+++ b/health/health-data-client/OWNERS
@@ -1,2 +1,4 @@
 hengruicao@google.com
 jstembridge@google.com
+nickelc@google.com
+itsleo@google.com
\ No newline at end of file
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanConcurrentHashMap.kt b/lint-checks/src/main/java/androidx/build/lint/BanConcurrentHashMap.kt
index 7aa81c8..b5529a3 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanConcurrentHashMap.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanConcurrentHashMap.kt
@@ -21,6 +21,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -48,11 +49,12 @@
             if (node.selector is USimpleNameReferenceExpression) {
                 val name = node.selector as USimpleNameReferenceExpression
                 if (CONCURRENT_HASHMAP == name.identifier) {
-                    context.report(
-                        ISSUE, node, context.getLocation(node),
-                        "Detected " +
-                            "ConcurrentHashMap usage."
-                    )
+                    val incident = Incident(context)
+                        .issue(ISSUE)
+                        .location(context.getLocation(node))
+                        .message("Detected ConcurrentHashMap usage.")
+                        .scope(node)
+                    context.report(incident)
                 }
             }
         }
@@ -69,11 +71,12 @@
                 if (resolved is PsiClass &&
                     CONCURRENT_HASHMAP_QUALIFIED_NAME == resolved.qualifiedName
                 ) {
-                    context.report(
-                        ISSUE, node, context.getLocation(node),
-                        "Detected " +
-                            "ConcurrentHashMap usage."
-                    )
+                    val incident = Incident(context)
+                        .issue(ISSUE)
+                        .location(context.getLocation(node))
+                        .message("Detected ConcurrentHashMap usage.")
+                        .scope(node)
+                    context.report(incident)
                 }
             }
         }
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanKeepAnnotation.kt b/lint-checks/src/main/java/androidx/build/lint/BanKeepAnnotation.kt
index c2e6106..8bcfd3a 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanKeepAnnotation.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanKeepAnnotation.kt
@@ -23,6 +23,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -42,10 +43,12 @@
             if (node.qualifiedName == "androidx.annotation.Keep" ||
                 node.qualifiedName == "android.support.annotation.keep"
             ) {
-                context.report(
-                    ISSUE, node, context.getNameLocation(node),
-                    "Uses @Keep annotation"
-                )
+                val incident = Incident(context)
+                    .issue(ISSUE)
+                    .location(context.getNameLocation(node))
+                    .message("Uses @Keep annotation")
+                    .scope(node)
+                context.report(incident)
             }
         }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanParcelableUsage.kt b/lint-checks/src/main/java/androidx/build/lint/BanParcelableUsage.kt
index 08586eb..ff4de6a 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanParcelableUsage.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanParcelableUsage.kt
@@ -21,6 +21,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -49,10 +50,12 @@
         // lint will also examine the entire inheritance and implementation chain.
         for (superclass in declaration.uastSuperTypes) {
             if (superclass.type.canonicalText == PARCELABLE_INTERFACE_CANONICAL_NAME) {
-                context.report(
-                    ISSUE, declaration, context.getNameLocation(declaration),
-                    "Class implements android.os.Parcelable"
-                )
+                val incident = Incident(context)
+                    .issue(ISSUE)
+                    .location(context.getNameLocation(declaration))
+                    .message("Class implements android.os.Parcelable")
+                    .scope(declaration)
+                context.report(incident)
             }
         }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanSynchronizedMethods.kt b/lint-checks/src/main/java/androidx/build/lint/BanSynchronizedMethods.kt
index e1755ef1..7f50e3d 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanSynchronizedMethods.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanSynchronizedMethods.kt
@@ -22,6 +22,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -36,12 +37,13 @@
     override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
         override fun visitMethod(node: UMethod) {
             if (node.hasModifier(JvmModifier.SYNCHRONIZED)) {
-                context.report(
-                    ISSUE, node,
-                    context.getLocation(node),
-                    "Use of synchronized methods is not recommended",
-                    null
-                )
+                val incident = Incident(context)
+                    .fix(null)
+                    .issue(ISSUE)
+                    .location(context.getLocation(node))
+                    .message("Use of synchronized methods is not recommended")
+                    .scope(node)
+                context.report(incident)
             }
         }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
index 725f322c..6914489 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
@@ -25,6 +25,7 @@
 import com.android.tools.lint.detector.api.Scope
 import com.android.tools.lint.checks.VersionChecks.Companion.isWithinVersionCheckConditional
 import com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_API
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
 import com.intellij.psi.PsiMethod
@@ -53,10 +54,12 @@
         if (!isWithinVersionCheckConditional(context, node, HIGHEST_KNOWN_API, false) &&
             !isWithinVersionCheckConditional(context, node, 1, true)
         ) {
-            context.report(
-                ISSUE, node, context.getLocation(node),
-                "Calling `Method.invoke` without an SDK check"
-            )
+            val incident = Incident(context)
+                .issue(ISSUE)
+                .location(context.getLocation(node))
+                .message("Calling `Method.invoke` without an SDK check")
+                .scope(node)
+            context.report(incident)
         }
     }
 
diff --git a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
index f33aea8..6d40535 100644
--- a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
@@ -30,6 +30,7 @@
 import com.android.tools.lint.detector.api.Desugaring
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.LintFix
@@ -474,15 +475,17 @@
 
             // call.getContainingUClass()!! refers to the direct parent class of this method
             val containingClassName = call.getContainingUClass()!!.qualifiedName.toString()
-            val fix = createLintFix(method, call, api)
-
-            context.report(
-                ISSUE, reference, location,
-                "This call references a method added in API level $api; however, the " +
+            val lintFix = createLintFix(method, call, api)
+            val incident = Incident(context)
+                .fix(lintFix)
+                .issue(ISSUE)
+                .location(location)
+                .message("This call references a method added in API level $api; however, the " +
                     "containing class $containingClassName is reachable from earlier API " +
-                    "levels and will fail run-time class verification.",
-                fix,
-            )
+                    "levels and will fail run-time class verification.")
+                .scope(reference)
+
+            context.report(incident)
         }
 
         /**
diff --git a/lint-checks/src/main/java/androidx/build/lint/IdeaSuppressionDetector.kt b/lint-checks/src/main/java/androidx/build/lint/IdeaSuppressionDetector.kt
index 0eaeae6..e6acfb7 100644
--- a/lint-checks/src/main/java/androidx/build/lint/IdeaSuppressionDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/IdeaSuppressionDetector.kt
@@ -22,6 +22,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -127,10 +128,13 @@
             val warnings = source.split(" ").drop(1).filter { JAVA_WARNINGS.contains(it) }
             if (warnings.isNotEmpty()) {
                 val args = warnings.joinToString(", ") { "\"$it\"" }
-                context.report(
-                    ISSUE, element, context.getNameLocation(element),
-                    "Uses IntelliJ-specific suppression, should use `@SuppressWarnings($args)`"
-                )
+                val incident = Incident(context)
+                    .issue(ISSUE)
+                    .location(context.getNameLocation(element))
+                    .message("Uses IntelliJ-specific suppression, should use" +
+                        " `@SuppressWarnings($args)`")
+                    .scope(element)
+                context.report(incident)
             }
         }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/MetadataTagInsideApplicationTagDetector.kt b/lint-checks/src/main/java/androidx/build/lint/MetadataTagInsideApplicationTagDetector.kt
index 94fd2e1..3a13a9f 100644
--- a/lint-checks/src/main/java/androidx/build/lint/MetadataTagInsideApplicationTagDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/MetadataTagInsideApplicationTagDetector.kt
@@ -21,6 +21,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.Scope
 import com.android.tools.lint.detector.api.Severity
@@ -37,11 +38,13 @@
 
     override fun visitElement(context: XmlContext, element: Element) {
         if (element.parentNode.nodeName == NODE_APPLICATION) {
-            context.report(
-                ISSUE, element, context.getLocation(element),
-                "Detected " +
-                    "<application>-level meta-data tag."
-            )
+            val incident = Incident(context)
+                .issue(ISSUE)
+                .location(context.getLocation(element))
+                .message("Detected <application>-level meta-data tag.")
+                .scope(element)
+
+            context.report(incident)
         }
     }
 
diff --git a/lint-checks/src/main/java/androidx/build/lint/ObsoleteBuildCompatUsageDetector.kt b/lint-checks/src/main/java/androidx/build/lint/ObsoleteBuildCompatUsageDetector.kt
index 1dd909d..d3ae2de 100644
--- a/lint-checks/src/main/java/androidx/build/lint/ObsoleteBuildCompatUsageDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/ObsoleteBuildCompatUsageDetector.kt
@@ -21,6 +21,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -49,16 +50,18 @@
         val target = if (node.receiver != null) node.uastParent!! else node
 
         val apiLevel = methodsToApiLevels[node.methodName]
-        val fix = fix().name("Use SDK_INT >= $apiLevel")
+        val lintFix = fix().name("Use SDK_INT >= $apiLevel")
             .replace()
             .text(target.asRenderString())
             .with("Build.VERSION.SDK_INT >= $apiLevel")
             .build()
-
-        context.report(
-            ISSUE, node, context.getLocation(node),
-            "Using deprecated BuildCompat methods", fix
-        )
+        val incident = Incident(context)
+            .fix(lintFix)
+            .issue(ISSUE)
+            .location(context.getLocation(node))
+            .message("Using deprecated BuildCompat methods")
+            .scope(node)
+        context.report(incident)
     }
 
     companion object {
diff --git a/lint-checks/src/main/java/androidx/build/lint/PrivateConstructorForUtilityClassDetector.kt b/lint-checks/src/main/java/androidx/build/lint/PrivateConstructorForUtilityClassDetector.kt
index a862563..e34e10b 100644
--- a/lint-checks/src/main/java/androidx/build/lint/PrivateConstructorForUtilityClassDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/PrivateConstructorForUtilityClassDetector.kt
@@ -22,6 +22,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -70,11 +71,12 @@
                 return
             }
 
-            context.report(
-                ISSUE, node,
-                context.getNameLocation(node),
-                "Utility class is missing private constructor"
-            )
+            val incident = Incident(context)
+                .issue(ISSUE)
+                .location(context.getNameLocation(node))
+                .message("Utility class is missing private constructor")
+                .scope(node)
+            context.report(incident)
         }
     }
 
diff --git a/lint-checks/src/main/java/androidx/build/lint/SampledAnnotationDetector.kt b/lint-checks/src/main/java/androidx/build/lint/SampledAnnotationDetector.kt
index a7ac02c..ab223e2 100644
--- a/lint-checks/src/main/java/androidx/build/lint/SampledAnnotationDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/SampledAnnotationDetector.kt
@@ -33,6 +33,7 @@
 import com.android.tools.lint.detector.api.Context
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.LintMap
@@ -112,11 +113,11 @@
                 functionLocations == null -> {
                     locations.forEach { location ->
                         if (location.shouldReport()) {
-                            context.report(
-                                UNRESOLVED_SAMPLE_LINK,
-                                location,
-                                "Couldn't find a valid @Sampled function matching $link"
-                            )
+                            val incident = Incident(context)
+                                .issue(UNRESOLVED_SAMPLE_LINK)
+                                .location(location)
+                                .message("Couldn't find a valid @Sampled function matching $link")
+                            context.report(incident)
                         }
                     }
                 }
@@ -125,11 +126,11 @@
                 functionLocations.size > 1 -> {
                     locations.forEach { location ->
                         if (location.shouldReport()) {
-                            context.report(
-                                MULTIPLE_FUNCTIONS_FOUND,
-                                location,
-                                "Found multiple functions matching $link"
-                            )
+                            val incident = Incident(context)
+                                .issue(MULTIPLE_FUNCTIONS_FOUND)
+                                .location(location)
+                                .message("Found multiple functions matching $link")
+                            context.report(incident)
                         }
                     }
                 }
@@ -140,12 +141,12 @@
             if (sampleLinks[link] == null) {
                 locations.forEach { location ->
                     if (location.shouldReport()) {
-                        context.report(
-                            OBSOLETE_SAMPLED_ANNOTATION,
-                            location,
-                            "$link is annotated with @$SAMPLED_ANNOTATION, but is not " +
-                                "linked to from a @$SAMPLE_KDOC_ANNOTATION tag."
-                        )
+                        val incident = Incident(context)
+                            .issue(OBSOLETE_SAMPLED_ANNOTATION)
+                            .location(location)
+                            .message("$link is annotated with @$SAMPLED_ANNOTATION, but is not " +
+                                "linked to from a @$SAMPLE_KDOC_ANNOTATION tag.")
+                        context.report(incident)
                     }
                 }
             }
@@ -294,13 +295,13 @@
         val currentPath = context.psiFile!!.virtualFile.path
 
         if (SAMPLES_DIRECTORY !in currentPath) {
-            context.report(
-                INVALID_SAMPLES_LOCATION,
-                node,
-                context.getNameLocation(node),
-                "${node.name} is annotated with @$SAMPLED_ANNOTATION" +
-                    ", but is not inside a project/directory named $SAMPLES_DIRECTORY."
-            )
+            val incident = Incident(context)
+                .issue(INVALID_SAMPLES_LOCATION)
+                .location(context.getNameLocation(node))
+                .message("${node.name} is annotated with @$SAMPLED_ANNOTATION" +
+                    ", but is not inside a project/directory named $SAMPLES_DIRECTORY.")
+                .scope(node)
+            context.report(incident)
             return
         }
 
@@ -320,11 +321,11 @@
         val location = context.getNameLocation(node)
 
         if (sampledFunctionLintMap.getLocation(fullFqName) != null) {
-            context.report(
-                MULTIPLE_FUNCTIONS_FOUND,
-                location,
-                "Found multiple functions matching $fullFqName"
-            )
+            val incident = Incident(context)
+                .issue(MULTIPLE_FUNCTIONS_FOUND)
+                .location(location)
+                .message("Found multiple functions matching $fullFqName")
+            context.report(incident)
         }
 
         sampledFunctionLintMap.put(fullFqName, location)
diff --git a/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt b/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
index 4e9fd59..7027b1e 100644
--- a/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
@@ -23,6 +23,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -43,17 +44,20 @@
     private inner class AnnotationChecker(val context: JavaContext) : UElementHandler() {
         override fun visitAnnotation(node: UAnnotation) {
             if (node.qualifiedName == "android.annotation.TargetApi") {
-                context.report(
-                    ISSUE, node, context.getNameLocation(node),
-                    "Use `@RequiresApi` instead of `@TargetApi`",
-                    fix().name("Replace with `@RequiresApi`")
-                        .replace()
-                        .pattern("(?:android\\.annotation\\.)?TargetApi")
-                        .with("androidx.annotation.RequiresApi")
-                        .shortenNames()
-                        .autoFix(true, true)
-                        .build(),
-                )
+                val lintFix = fix().name("Replace with `@RequiresApi`")
+                    .replace()
+                    .pattern("(?:android\\.annotation\\.)?TargetApi")
+                    .with("androidx.annotation.RequiresApi")
+                    .shortenNames()
+                    .autoFix(true, true)
+                    .build()
+                val incident = Incident(context)
+                    .fix(lintFix)
+                    .issue(ISSUE)
+                    .location(context.getNameLocation(node))
+                    .message("Use `@RequiresApi` instead of `@TargetApi`")
+                    .scope(node)
+                context.report(incident)
             }
         }
     }
diff --git a/lint-checks/src/main/java/androidx/build/lint/TestSizeAnnotationEnforcer.kt b/lint-checks/src/main/java/androidx/build/lint/TestSizeAnnotationEnforcer.kt
index 73d1b76..a6b34e6 100644
--- a/lint-checks/src/main/java/androidx/build/lint/TestSizeAnnotationEnforcer.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/TestSizeAnnotationEnforcer.kt
@@ -22,6 +22,7 @@
 import com.android.tools.lint.detector.api.Category
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
@@ -69,12 +70,13 @@
                 ?.type?.canonicalText ?: return
 
             if (testRunnerClassName !in ALLOWED_TEST_RUNNERS) {
-                context.report(
-                    UNSUPPORTED_TEST_RUNNER,
-                    testRunner,
-                    context.getNameLocation(testRunner),
-                    "Unsupported test runner. Supported runners are: $ALLOWED_TEST_RUNNERS"
-                )
+                val incident = Incident(context)
+                    .issue(UNSUPPORTED_TEST_RUNNER)
+                    .location(context.getNameLocation(testRunner))
+                    .message("Unsupported test runner." +
+                        " Supported runners are: $ALLOWED_TEST_RUNNERS")
+                    .scope(testRunner)
+                context.report(incident)
                 return
             }
 
@@ -95,12 +97,12 @@
                 // Report an issue if neither the test method nor the surrounding class have a
                 // valid test size annotation
                 if (combinedAnnotations.none { it.qualifiedName in TEST_SIZE_ANNOTATIONS }) {
-                    context.report(
-                        MISSING_TEST_SIZE_ANNOTATION,
-                        method,
-                        context.getNameLocation(method),
-                        "Missing test size annotation"
-                    )
+                    val incident = Incident(context)
+                        .issue(MISSING_TEST_SIZE_ANNOTATION)
+                        .location(context.getNameLocation(method))
+                        .message("Missing test size annotation")
+                        .scope(method)
+                    context.report(incident)
                 }
             }
         }
@@ -113,12 +115,12 @@
             node.uAnnotations
                 .find { it.qualifiedName in TEST_SIZE_ANNOTATIONS }
                 ?.let { annotation ->
-                    context.report(
-                        UNEXPECTED_TEST_SIZE_ANNOTATION,
-                        annotation,
-                        context.getNameLocation(annotation),
-                        "Unexpected test size annotation"
-                    )
+                    val incident = Incident(context)
+                        .issue(UNEXPECTED_TEST_SIZE_ANNOTATION)
+                        .location(context.getNameLocation(annotation))
+                        .message("Unexpected test size annotation")
+                        .scope(annotation)
+                    context.report(incident)
                 }
 
             node.methods.filter {
@@ -128,12 +130,12 @@
                 method.uAnnotations
                     .find { it.qualifiedName in TEST_SIZE_ANNOTATIONS }
                     ?.let { annotation ->
-                        context.report(
-                            UNEXPECTED_TEST_SIZE_ANNOTATION,
-                            annotation,
-                            context.getNameLocation(annotation),
-                            "Unexpected test size annotation"
-                        )
+                        val incident = Incident(context)
+                            .issue(UNEXPECTED_TEST_SIZE_ANNOTATION)
+                            .location(context.getNameLocation(annotation))
+                            .message("Unexpected test size annotation")
+                            .scope(annotation)
+                        context.report(incident)
                     }
             }
         }
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
index 60b5462..7927944 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
@@ -38,6 +38,7 @@
 import androidx.room.util.TableInfo;
 import androidx.room.util.ViewInfo;
 import androidx.sqlite.db.SupportSQLiteDatabase;
+import androidx.sqlite.db.SupportSQLiteOpenHelper;
 import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -562,6 +563,37 @@
         }
     }
 
+    // Verifies that even with allowDataLossOnRecovery, bad migrations are propagated and the DB
+    // is not silently deleted.
+    @Test
+    public void badMigration_allowDataLossOnRecovery() throws IOException {
+        // Create DB at version 1
+        helper.createDatabase(TEST_DB, 1).close();
+
+        // Create DB at latest version, but no migrations and with allowDataLossOnRecovery, it
+        // should fail to open.
+        Context targetContext = ApplicationProvider.getApplicationContext();
+        MigrationDb db = Room.databaseBuilder(targetContext, MigrationDb.class, TEST_DB)
+                .openHelperFactory(configuration -> {
+                    SupportSQLiteOpenHelper.Configuration config =
+                            SupportSQLiteOpenHelper.Configuration.builder(targetContext)
+                                    .name(configuration.name)
+                                    .callback(configuration.callback)
+                                    .allowDataLossOnRecovery(true)
+                                    .build();
+                    return new FrameworkSQLiteOpenHelperFactory().create(config);
+                })
+                .build();
+        try {
+            db.getOpenHelper().getWritableDatabase();
+            Assert.fail("Expected a missing migration exception");
+        } catch (IllegalStateException ex) {
+            // Verifies exception is not wrapped
+            Truth.assertThat(ex).hasMessageThat()
+                    .containsMatch("A migration from \\d+ to \\d+ was required but not found.");
+        }
+    }
+
     private void testFailure(int startVersion, int endVersion) throws IOException {
         final SupportSQLiteDatabase db = helper.createDatabase(TEST_DB, startVersion);
         db.close();
diff --git a/sqlite/sqlite-framework/build.gradle b/sqlite/sqlite-framework/build.gradle
index 8e92837..9dfb2cf 100644
--- a/sqlite/sqlite-framework/build.gradle
+++ b/sqlite/sqlite-framework/build.gradle
@@ -19,11 +19,20 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("org.jetbrains.kotlin.android")
 }
 
 dependencies {
     api("androidx.annotation:annotation:1.2.0")
     api(project(":sqlite:sqlite"))
+    androidTestImplementation(libs.kotlinStdlib)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner) {
+        exclude module: "support-annotations"
+        exclude module: "hamcrest-core"
+    }
+    androidTestImplementation(libs.truth)
 }
 
 androidx {
diff --git a/sqlite/sqlite-framework/src/androidTest/java/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt b/sqlite/sqlite-framework/src/androidTest/java/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt
new file mode 100644
index 0000000..2ff6161
--- /dev/null
+++ b/sqlite/sqlite-framework/src/androidTest/java/androidx/sqlite/db/framework/OpenHelperRecoveryTest.kt
@@ -0,0 +1,248 @@
+/*
+ * 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.sqlite.db.framework
+
+import android.content.Context
+import android.database.sqlite.SQLiteException
+import androidx.sqlite.db.SupportSQLiteDatabase
+import androidx.sqlite.db.SupportSQLiteOpenHelper
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+
+@LargeTest
+class OpenHelperRecoveryTest {
+
+    private val dbName = "test.db"
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Before
+    fun setup() {
+        context.deleteDatabase(dbName)
+    }
+
+    @Test
+    fun writeOver() {
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, EmptyCallback(), false, false)
+        openHelper.writableDatabase.use { db ->
+            db.execSQL("CREATE TABLE Foo (id INTEGER PRIMARY KEY)")
+            db.query("SELECT * FROM sqlite_master WHERE name = 'Foo'").use {
+                assertThat(it.count).isEqualTo(1)
+            }
+        }
+
+        val dbFile = context.getDatabasePath(dbName)
+        assertThat(dbFile.exists()).isTrue()
+        assertThat(dbFile.length()).isGreaterThan(0)
+        dbFile.writeText("malas vibra")
+
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: SQLiteException) {
+            // Expected
+        }
+    }
+
+    @Test
+    fun writeOver_allowDataLossOnRecovery() {
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, EmptyCallback(), false, true)
+        openHelper.writableDatabase.use { db ->
+            db.execSQL("CREATE TABLE Foo (id INTEGER PRIMARY KEY)")
+            db.query("SELECT * FROM sqlite_master WHERE name = 'Foo'").use {
+                assertThat(it.count).isEqualTo(1)
+            }
+        }
+
+        val dbFile = context.getDatabasePath(dbName)
+        assertThat(dbFile.exists()).isTrue()
+        assertThat(dbFile.length()).isGreaterThan(0)
+        dbFile.writeText("malas vibra")
+
+        openHelper.writableDatabase.use { db ->
+            db.query("SELECT * FROM sqlite_master WHERE name = 'Foo'").use {
+                assertThat(it.count).isEqualTo(0)
+            }
+        }
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onCreateError() {
+        var createAttempts = 0
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(1) {
+            override fun onCreate(db: SupportSQLiteDatabase) {
+                if (createAttempts++ < 2) {
+                    throw RuntimeException("Not an SQLiteException")
+                }
+            }
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {}
+        }
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: RuntimeException) {
+            // Expected
+            assertThat(ex.message).contains("Not an SQLiteException")
+        }
+        assertThat(createAttempts).isEqualTo(2)
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onUpgradeError() {
+        // Create DB at version 1, open and close it
+        FrameworkSQLiteOpenHelper(context, dbName, EmptyCallback(1), false, true).let {
+            it.writableDatabase.close()
+        }
+
+        // A callback to open DB at version 2, it has a bad migration.
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(2) {
+            override fun onCreate(db: SupportSQLiteDatabase) {}
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
+                db.execSQL("SELECT * FROM bad_table")
+            }
+        }
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: SQLiteException) {
+            // Expected
+            assertThat(ex.message).contains("no such table: bad_table")
+        }
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onOpenNonSQLiteError() {
+        var openAttempts = 0
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(1) {
+            override fun onCreate(db: SupportSQLiteDatabase) {}
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {}
+            override fun onOpen(db: SupportSQLiteDatabase) {
+                if (openAttempts++ < 2) {
+                    throw RuntimeException("Not an SQLiteException")
+                }
+            }
+        }
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: RuntimeException) {
+            // Expected
+            assertThat(ex.message).contains("Not an SQLiteException")
+        }
+        assertThat(openAttempts).isEqualTo(2)
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onOpenSQLiteError_intermediate() {
+        FrameworkSQLiteOpenHelper(context, dbName, EmptyCallback(), false, false)
+            .writableDatabase.use { db ->
+                db.execSQL("CREATE TABLE Foo (id INTEGER PRIMARY KEY)")
+            }
+
+        var openAttempts = 0
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(1) {
+            override fun onCreate(db: SupportSQLiteDatabase) {}
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {}
+            override fun onOpen(db: SupportSQLiteDatabase) {
+                if (openAttempts++ < 1) {
+                    db.execSQL("SELECT * FROM bad_table")
+                }
+            }
+        }
+        // With only 1 onOpen error, the database is opened without being deleted, simulates an
+        // intermediate error.
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        openHelper.writableDatabase.use { db ->
+            db.query("SELECT * FROM sqlite_master WHERE name = 'Foo'").use {
+                assertThat(it.count).isEqualTo(1)
+            }
+        }
+        assertThat(openAttempts).isEqualTo(2)
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onOpenSQLiteError_recoverable() {
+        FrameworkSQLiteOpenHelper(context, dbName, EmptyCallback(), false, false)
+            .writableDatabase.use { db ->
+                db.execSQL("CREATE TABLE Foo (id INTEGER PRIMARY KEY)")
+            }
+
+        var openAttempts = 0
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(1) {
+            override fun onCreate(db: SupportSQLiteDatabase) {}
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {}
+            override fun onOpen(db: SupportSQLiteDatabase) {
+                if (openAttempts++ < 2) {
+                    db.execSQL("SELECT * FROM bad_table")
+                }
+            }
+        }
+        // With 2 onOpen error, the database is opened by deleting it, simulating a recoverable
+        // error.
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        openHelper.writableDatabase.use { db ->
+            db.query("SELECT * FROM sqlite_master WHERE name = 'Foo'").use {
+                assertThat(it.count).isEqualTo(0)
+            }
+        }
+        assertThat(openAttempts).isEqualTo(3)
+    }
+
+    @Test
+    fun allowDataLossOnRecovery_onOpenSQLiteError_permanent() {
+        var openAttempts = 0
+        val badCallback = object : SupportSQLiteOpenHelper.Callback(1) {
+            override fun onCreate(db: SupportSQLiteDatabase) {}
+            override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {}
+            override fun onOpen(db: SupportSQLiteDatabase) {
+                openAttempts++
+                db.execSQL("SELECT * FROM bad_table")
+            }
+        }
+        // Consistent onOpen error, might be a user bug or an actual SQLite permanent error,
+        // nothing we can do here, expect failure
+        val openHelper = FrameworkSQLiteOpenHelper(context, dbName, badCallback, false, true)
+        try {
+            openHelper.writableDatabase
+            fail("Database should have failed to open.")
+        } catch (ex: SQLiteException) {
+            // Expected
+            assertThat(ex.message).contains("no such table: bad_table")
+        }
+        assertThat(openAttempts).isEqualTo(3)
+    }
+
+    class EmptyCallback(version: Int = 1) : SupportSQLiteOpenHelper.Callback(version) {
+        override fun onCreate(db: SupportSQLiteDatabase) {
+        }
+
+        override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
+        }
+
+        override fun onOpen(db: SupportSQLiteDatabase) {
+        }
+
+        override fun onCorruption(db: SupportSQLiteDatabase) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.java b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.java
index b3f6a12..7a76b70 100644
--- a/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.java
+++ b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelper.java
@@ -19,24 +19,31 @@
 import android.content.Context;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Build;
+import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.sqlite.db.SupportSQLiteCompat;
 import androidx.sqlite.db.SupportSQLiteDatabase;
 import androidx.sqlite.db.SupportSQLiteOpenHelper;
 import androidx.sqlite.util.ProcessLock;
+import androidx.sqlite.util.SneakyThrow;
 
 import java.io.File;
 import java.util.UUID;
 
 class FrameworkSQLiteOpenHelper implements SupportSQLiteOpenHelper {
 
+    private static final String TAG = "SupportSQLite";
+
     private final Context mContext;
     private final String mName;
     private final Callback mCallback;
     private final boolean mUseNoBackupDirectory;
+    private final boolean mAllowDataLossOnRecovery;
     private final Object mLock;
 
     // Delegate is created lazily
@@ -55,10 +62,20 @@
             String name,
             Callback callback,
             boolean useNoBackupDirectory) {
+        this(context, name, callback, useNoBackupDirectory, false);
+    }
+
+    FrameworkSQLiteOpenHelper(
+            Context context,
+            String name,
+            Callback callback,
+            boolean useNoBackupDirectory,
+            boolean allowDataLossOnRecovery) {
         mContext = context;
         mName = name;
         mCallback = callback;
         mUseNoBackupDirectory = useNoBackupDirectory;
+        mAllowDataLossOnRecovery = allowDataLossOnRecovery;
         mLock = new Object();
     }
 
@@ -80,9 +97,11 @@
                             SupportSQLiteCompat.Api21Impl.getNoBackupFilesDir(mContext),
                             mName
                     );
-                    mDelegate = new OpenHelper(mContext, file.getAbsolutePath(), dbRef, mCallback);
+                    mDelegate = new OpenHelper(mContext, file.getAbsolutePath(), dbRef, mCallback,
+                            mAllowDataLossOnRecovery);
                 } else {
-                    mDelegate = new OpenHelper(mContext, mName, dbRef, mCallback);
+                    mDelegate = new OpenHelper(mContext, mName, dbRef, mCallback,
+                            mAllowDataLossOnRecovery);
                 }
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                     SupportSQLiteCompat.Api16Impl.setWriteAheadLoggingEnabled(mDelegate,
@@ -111,12 +130,12 @@
 
     @Override
     public SupportSQLiteDatabase getWritableDatabase() {
-        return getDelegate().getWritableSupportDatabase();
+        return getDelegate().getSupportDatabase(true);
     }
 
     @Override
     public SupportSQLiteDatabase getReadableDatabase() {
-        return getDelegate().getReadableSupportDatabase();
+        return getDelegate().getSupportDatabase(false);
     }
 
     @Override
@@ -131,7 +150,9 @@
          * constructor.
          */
         final FrameworkSQLiteDatabase[] mDbRef;
+        final Context mContext;
         final Callback mCallback;
+        final boolean mAllowDataLossOnRecovery;
         // see b/78359448
         private boolean mMigrated;
         // see b/193182592
@@ -139,7 +160,7 @@
         private boolean mOpened;
 
         OpenHelper(Context context, String name, final FrameworkSQLiteDatabase[] dbRef,
-                final Callback callback) {
+                final Callback callback, boolean allowDataLossOnRecovery) {
             super(context, name, null, callback.version,
                     new DatabaseErrorHandler() {
                         @Override
@@ -147,21 +168,23 @@
                             callback.onCorruption(getWrappedDb(dbRef, dbObj));
                         }
                     });
+            mContext = context;
             mCallback = callback;
             mDbRef = dbRef;
+            mAllowDataLossOnRecovery = allowDataLossOnRecovery;
             mLock = new ProcessLock(name == null ? UUID.randomUUID().toString() : name,
                     context.getCacheDir(), false);
         }
 
-        SupportSQLiteDatabase getWritableSupportDatabase() {
+        SupportSQLiteDatabase getSupportDatabase(boolean writable) {
             try {
                 mLock.lock(!mOpened && getDatabaseName() != null);
                 mMigrated = false;
-                SQLiteDatabase db = super.getWritableDatabase();
+                final SQLiteDatabase db = innerGetDatabase(writable);
                 if (mMigrated) {
                     // there might be a connection w/ stale structure, we should re-open.
                     close();
-                    return getWritableSupportDatabase();
+                    return getSupportDatabase(writable);
                 }
                 return getWrappedDb(db);
             } finally {
@@ -169,19 +192,87 @@
             }
         }
 
-        SupportSQLiteDatabase getReadableSupportDatabase() {
-            try {
-                mLock.lock(!mOpened && getDatabaseName() != null);
-                mMigrated = false;
-                SQLiteDatabase db = super.getReadableDatabase();
-                if (mMigrated) {
-                    // there might be a connection w/ stale structure, we should re-open.
-                    close();
-                    return getReadableSupportDatabase();
+        private SQLiteDatabase innerGetDatabase(boolean writable) {
+            String name = getDatabaseName();
+            if (name != null) {
+                File databaseFile = mContext.getDatabasePath(name);
+                File parentFile = databaseFile.getParentFile();
+                if (parentFile != null) {
+                    parentFile.mkdirs();
+                    if (!parentFile.isDirectory()) {
+                        Log.w(TAG, "Invalid database parent file, not a directory: " + parentFile);
+                    }
                 }
-                return getWrappedDb(db);
-            } finally {
-                mLock.unlock();
+            }
+
+            try {
+                return getWritableOrReadableDatabase(writable);
+            } catch (Throwable t) {
+                // No good, just try again...
+                super.close();
+            }
+
+            try {
+                // Wait before trying to open the DB, ideally enough to account for some slow I/O.
+                // Similar to android_database_SQLiteConnection's BUSY_TIMEOUT_MS but not as much.
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                // Ignore, and continue
+            }
+
+            final Throwable openRetryError;
+            try {
+                return getWritableOrReadableDatabase(writable);
+            } catch (Throwable t) {
+                super.close();
+                openRetryError = t;
+            }
+            if (openRetryError instanceof CallbackException) {
+                // Callback error (onCreate, onUpgrade, onOpen, etc), possibly user error.
+                final CallbackException callbackException = (CallbackException) openRetryError;
+                final Throwable cause = callbackException.getCause();
+                switch (callbackException.getCallbackName()) {
+                    case ON_CONFIGURE:
+                    case ON_CREATE:
+                    case ON_UPGRADE:
+                    case ON_DOWNGRADE:
+                        SneakyThrow.reThrow(cause);
+                        break;
+                    case ON_OPEN:
+                    default:
+                        break;
+                }
+                // If callback exception is not an SQLiteException, then more certainly it is not
+                // recoverable.
+                if (!(cause instanceof SQLiteException)) {
+                    SneakyThrow.reThrow(cause);
+                }
+            } else if (openRetryError instanceof SQLiteException) {
+                // Ideally we are looking for SQLiteCantOpenDatabaseException and similar, but
+                // corruption can manifest in others forms.
+                if (name == null || !mAllowDataLossOnRecovery) {
+                    SneakyThrow.reThrow(openRetryError);
+                }
+            } else {
+                SneakyThrow.reThrow(openRetryError);
+            }
+
+            // Delete the database and try one last time. (mAllowDataLossOnRecovery == true)
+            mContext.deleteDatabase(name);
+            try {
+                return getWritableOrReadableDatabase(writable);
+            } catch (CallbackException ex) {
+                // Unwrap our exception to avoid disruption with other try-catch in the call stack.
+                SneakyThrow.reThrow(ex.getCause());
+                return null; // Unreachable code, but compiler doesn't know it.
+            }
+        }
+
+        private SQLiteDatabase getWritableOrReadableDatabase(boolean writable) {
+            if (writable) {
+                return super.getWritableDatabase();
+            } else {
+                return super.getReadableDatabase();
             }
         }
 
@@ -191,31 +282,51 @@
 
         @Override
         public void onCreate(SQLiteDatabase sqLiteDatabase) {
-            mCallback.onCreate(getWrappedDb(sqLiteDatabase));
+            try {
+                mCallback.onCreate(getWrappedDb(sqLiteDatabase));
+            } catch (Throwable t) {
+                throw new CallbackException(CallbackName.ON_CREATE, t);
+            }
         }
 
         @Override
         public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
             mMigrated = true;
-            mCallback.onUpgrade(getWrappedDb(sqLiteDatabase), oldVersion, newVersion);
+            try {
+                mCallback.onUpgrade(getWrappedDb(sqLiteDatabase), oldVersion, newVersion);
+            } catch (Throwable t) {
+                throw new CallbackException(CallbackName.ON_UPGRADE, t);
+            }
         }
 
         @Override
         public void onConfigure(SQLiteDatabase db) {
-            mCallback.onConfigure(getWrappedDb(db));
+            try {
+                mCallback.onConfigure(getWrappedDb(db));
+            } catch (Throwable t) {
+                throw new CallbackException(CallbackName.ON_CONFIGURE, t);
+            }
         }
 
         @Override
         public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             mMigrated = true;
-            mCallback.onDowngrade(getWrappedDb(db), oldVersion, newVersion);
+            try {
+                mCallback.onDowngrade(getWrappedDb(db), oldVersion, newVersion);
+            } catch (Throwable t) {
+                throw new CallbackException(CallbackName.ON_DOWNGRADE, t);
+            }
         }
 
         @Override
         public void onOpen(SQLiteDatabase db) {
             if (!mMigrated) {
                 // if we've migrated, we'll re-open the db so we should not call the callback.
-                mCallback.onOpen(getWrappedDb(db));
+                try {
+                    mCallback.onOpen(getWrappedDb(db));
+                } catch (Throwable t) {
+                    throw new CallbackException(CallbackName.ON_OPEN, t);
+                }
             }
             mOpened = true;
         }
@@ -241,5 +352,36 @@
             }
             return refHolder[0];
         }
+
+        private static final class CallbackException extends RuntimeException {
+
+            private final CallbackName mCallbackName;
+            private final Throwable mCause;
+
+            CallbackException(CallbackName callbackName, Throwable cause) {
+                super(cause);
+                mCallbackName = callbackName;
+                mCause = cause;
+            }
+
+            public CallbackName getCallbackName() {
+                return mCallbackName;
+            }
+
+            @NonNull
+            @Override
+            @SuppressWarnings("UnsynchronizedOverridesSynchronized") // Not needed, cause is final
+            public Throwable getCause() {
+                return mCause;
+            }
+        }
+
+        enum CallbackName {
+            ON_CONFIGURE,
+            ON_CREATE,
+            ON_UPGRADE,
+            ON_DOWNGRADE,
+            ON_OPEN
+        }
     }
 }
diff --git a/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.java b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.java
index 2f55202..34a0ce0 100644
--- a/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.java
+++ b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.java
@@ -33,6 +33,7 @@
                 configuration.context,
                 configuration.name,
                 configuration.callback,
-                configuration.useNoBackupDirectory);
+                configuration.useNoBackupDirectory,
+                configuration.allowDataLossOnRecovery);
     }
 }
diff --git a/sqlite/sqlite-framework/src/main/java/androidx/sqlite/util/SneakyThrow.java b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/util/SneakyThrow.java
new file mode 100644
index 0000000..e1309b4
--- /dev/null
+++ b/sqlite/sqlite-framework/src/main/java/androidx/sqlite/util/SneakyThrow.java
@@ -0,0 +1,47 @@
+/*
+ * 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.sqlite.util;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+
+/**
+ * Java 8 Sneaky Throw technique.
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class SneakyThrow {
+
+    /**
+     * Re-throws a throwable as if it was a runtime exception without wrapping it.
+     *
+     * @param t the throwable to re-throw.
+     */
+    public static void reThrow(@NonNull Throwable t) {
+        sneakyThrow(t);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <E extends Throwable> void sneakyThrow(@NonNull Throwable t) throws E {
+        throw (E) t;
+    }
+
+    private SneakyThrow() {
+
+    }
+}
diff --git a/sqlite/sqlite/api/api_lint.ignore b/sqlite/sqlite/api/api_lint.ignore
index 4e9a7e3..3d31715 100644
--- a/sqlite/sqlite/api/api_lint.ignore
+++ b/sqlite/sqlite/api/api_lint.ignore
@@ -41,6 +41,8 @@
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.name(String)
 BuilderSetStyle: androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder#noBackupDirectory(boolean):
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.noBackupDirectory(boolean)
+BuilderSetStyle: androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder#allowDataLossOnRecovery(boolean):
+    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder.allowDataLossOnRecovery(boolean)
 BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#builder(String):
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.sqlite.db.SupportSQLiteQueryBuilder.builder(String)
 BuilderSetStyle: androidx.sqlite.db.SupportSQLiteQueryBuilder#columns(String[]):
diff --git a/sqlite/sqlite/api/current.txt b/sqlite/sqlite/api/current.txt
index dbdea61..927cb1b 100644
--- a/sqlite/sqlite/api/current.txt
+++ b/sqlite/sqlite/api/current.txt
@@ -74,6 +74,7 @@
 
   public static class SupportSQLiteOpenHelper.Configuration {
     method public static androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder builder(android.content.Context);
+    field public final boolean allowDataLossOnRecovery;
     field public final androidx.sqlite.db.SupportSQLiteOpenHelper.Callback callback;
     field public final android.content.Context context;
     field public final String? name;
@@ -81,6 +82,7 @@
   }
 
   public static class SupportSQLiteOpenHelper.Configuration.Builder {
+    method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder allowDataLossOnRecovery(boolean);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration build();
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder callback(androidx.sqlite.db.SupportSQLiteOpenHelper.Callback);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder name(String?);
diff --git a/sqlite/sqlite/api/public_plus_experimental_current.txt b/sqlite/sqlite/api/public_plus_experimental_current.txt
index dbdea61..927cb1b 100644
--- a/sqlite/sqlite/api/public_plus_experimental_current.txt
+++ b/sqlite/sqlite/api/public_plus_experimental_current.txt
@@ -74,6 +74,7 @@
 
   public static class SupportSQLiteOpenHelper.Configuration {
     method public static androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder builder(android.content.Context);
+    field public final boolean allowDataLossOnRecovery;
     field public final androidx.sqlite.db.SupportSQLiteOpenHelper.Callback callback;
     field public final android.content.Context context;
     field public final String? name;
@@ -81,6 +82,7 @@
   }
 
   public static class SupportSQLiteOpenHelper.Configuration.Builder {
+    method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder allowDataLossOnRecovery(boolean);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration build();
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder callback(androidx.sqlite.db.SupportSQLiteOpenHelper.Callback);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder name(String?);
diff --git a/sqlite/sqlite/api/restricted_current.txt b/sqlite/sqlite/api/restricted_current.txt
index dbdea61..927cb1b 100644
--- a/sqlite/sqlite/api/restricted_current.txt
+++ b/sqlite/sqlite/api/restricted_current.txt
@@ -74,6 +74,7 @@
 
   public static class SupportSQLiteOpenHelper.Configuration {
     method public static androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder builder(android.content.Context);
+    field public final boolean allowDataLossOnRecovery;
     field public final androidx.sqlite.db.SupportSQLiteOpenHelper.Callback callback;
     field public final android.content.Context context;
     field public final String? name;
@@ -81,6 +82,7 @@
   }
 
   public static class SupportSQLiteOpenHelper.Configuration.Builder {
+    method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder allowDataLossOnRecovery(boolean);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration build();
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder callback(androidx.sqlite.db.SupportSQLiteOpenHelper.Callback);
     method public androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration.Builder name(String?);
diff --git a/sqlite/sqlite/src/main/java/androidx/sqlite/db/SupportSQLiteOpenHelper.java b/sqlite/sqlite/src/main/java/androidx/sqlite/db/SupportSQLiteOpenHelper.java
index 0123606..55d37ea 100644
--- a/sqlite/sqlite/src/main/java/androidx/sqlite/db/SupportSQLiteOpenHelper.java
+++ b/sqlite/sqlite/src/main/java/androidx/sqlite/db/SupportSQLiteOpenHelper.java
@@ -322,6 +322,11 @@
          * If {@code true} the database will be stored in the no-backup directory.
          */
         public final boolean useNoBackupDirectory;
+        /**
+         * If {@code true} the database will be delete and its data loss in the case that it
+         * cannot be opened.
+         */
+        public final boolean allowDataLossOnRecovery;
 
         Configuration(
                 @NonNull Context context,
@@ -335,10 +340,20 @@
                 @Nullable String name,
                 @NonNull Callback callback,
                 boolean useNoBackupDirectory) {
+            this(context, name, callback, useNoBackupDirectory, false);
+        }
+
+        Configuration(
+                @NonNull Context context,
+                @Nullable String name,
+                @NonNull Callback callback,
+                boolean useNoBackupDirectory,
+                boolean allowDataLossOnRecovery) {
             this.context = context;
             this.name = name;
             this.callback = callback;
             this.useNoBackupDirectory = useNoBackupDirectory;
+            this.allowDataLossOnRecovery = allowDataLossOnRecovery;
         }
 
         /**
@@ -359,6 +374,7 @@
             String mName;
             SupportSQLiteOpenHelper.Callback mCallback;
             boolean mUseNoBackupDirectory;
+            boolean mAllowDataLossOnRecovery;
 
             /**
              * <p>
@@ -386,7 +402,8 @@
                             "Must set a non-null database name to a configuration that uses the "
                                     + "no backup directory.");
                 }
-                return new Configuration(mContext, mName, mCallback, mUseNoBackupDirectory);
+                return new Configuration(mContext, mName, mCallback, mUseNoBackupDirectory,
+                        mAllowDataLossOnRecovery);
             }
 
             Builder(@NonNull Context context) {
@@ -424,6 +441,19 @@
                 mUseNoBackupDirectory = useNoBackupDirectory;
                 return this;
             }
+
+            /**
+             * Sets whether to delete and recreate the database file in situations when the
+             * database file cannot be opened, thus allowing for its data to be lost.
+             * @param allowDataLossOnRecovery If {@code true} the database file might be recreated
+             *                                in the case that it cannot be opened.
+             * @return this
+             */
+            @NonNull
+            public Builder allowDataLossOnRecovery(boolean allowDataLossOnRecovery) {
+                mAllowDataLossOnRecovery = allowDataLossOnRecovery;
+                return this;
+            }
         }
     }
 
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Picker.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Picker.kt
index cdfdca0..38df852 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Picker.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Picker.kt
@@ -40,6 +40,7 @@
  * A scrollable list of items to pick from. By default, items will be repeated
  * "infinitely" in both directions, unless [PickerState#repeatItems] is specified as false.
  *
+ * Example of a simple picker to select one of five options:
  * @sample androidx.wear.compose.material.samples.SimplePicker
  *
  * @param state The state of the component
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index 11ad138..91a5fc1 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -93,6 +93,23 @@
     "Material",
     listOf(
         DemoCategory(
+            "Picker",
+            listOf(
+                ComposableDemo("Time HH:MM:SS") {
+                    TimePickerWithHoursMinutesSeconds()
+                },
+                ComposableDemo("Time 12 Hour") {
+                    TimePickerWith12HourClock()
+                },
+                ComposableDemo("Simple Picker") {
+                    SimplePicker()
+                },
+                ComposableDemo("Change Selected Option Picker") {
+                    OptionChangePicker()
+                },
+            )
+        ),
+        DemoCategory(
             "Slider",
             listOf(
                 DemoCategory(
@@ -375,19 +392,6 @@
             )
         ),
         ComposableDemo("Curved Text") { CurvedTextDemo() },
-        DemoCategory(
-            "Picker",
-            listOf(
-                ComposableDemo("Simple Picker") {
-                    SimplePicker()
-                },
-                ComposableDemo("Change Selected Option Picker") {
-                    OptionChangePicker()
-                },
-                ComposableDemo("Time Picker") {
-                    PickerTimeDemo()
-                }
-            )
-        )
+
     ),
 )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
index 56af8be..b29cd08 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
@@ -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.
@@ -16,79 +16,305 @@
 
 package androidx.wear.compose.integration.demos
 
-import androidx.compose.foundation.background
+import android.view.MotionEvent
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInteropFilter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.Button
+import androidx.wear.compose.material.ChipDefaults
+import androidx.wear.compose.material.CompactChip
+import androidx.wear.compose.material.Icon
 import androidx.wear.compose.material.MaterialTheme
 import androidx.wear.compose.material.Picker
+import androidx.wear.compose.material.PickerDefaults
+import androidx.wear.compose.material.PickerScope
+import androidx.wear.compose.material.PickerState
+import androidx.wear.compose.material.ScalingParams
 import androidx.wear.compose.material.Text
 import androidx.wear.compose.material.rememberPickerState
 
+@OptIn(ExperimentalComposeUiApi::class)
 @Composable
-fun PickerTimeDemo() {
-    // The option initially selected on the Picker can be passed to rememberPickerState()
-    val hourState = rememberPickerState(numberOfOptions = 24, initiallySelectedOption = 6)
-    val minuteState = rememberPickerState(numberOfOptions = 60)
-    LaunchedEffect(true) {
-        // This is possible, but not desirable, since the observed state.selectedOption may take a
-        // few frames to update to this value.
-        minuteState.scrollToOption(15)
-    }
+fun TimePickerWithHoursMinutesSeconds() {
+    var selectedColumn by remember { mutableStateOf(0) }
+    val textStyle = MaterialTheme.typography.display2
+    val optionColor = MaterialTheme.colors.secondary
     Box(modifier = Modifier.fillMaxSize()) {
-        Row(
-            modifier = Modifier.align(Alignment.Center),
-            verticalAlignment = Alignment.CenterVertically
+        Column(
+            verticalArrangement = Arrangement.Center,
+            horizontalAlignment = Alignment.CenterHorizontally
         ) {
-            Picker(
-                state = hourState,
-                modifier = Modifier
-                    .size(50.dp, 80.dp)
-                    .background(color = Color.Black),
-                separation = (-10).dp
-            ) {
-                Text(
-                    modifier = Modifier.wrapContentSize(),
-                    text = it.toString(),
-                    style = MaterialTheme.typography.display3
-                )
-            }
-            Spacer(modifier = Modifier.size(10.dp))
-            Picker(
-                state = minuteState,
-                modifier = Modifier
-                    .size(50.dp, 80.dp)
-                    .background(color = Color.Black),
-                separation = (-10).dp
-            ) {
-                Text(
-                    modifier = Modifier.wrapContentSize(),
-                    text = "%02d".format(it),
-                    style = MaterialTheme.typography.display3
-                )
-            }
-        }
-
-        Box(
-            modifier = Modifier
-                .align(Alignment.TopCenter)
-                .padding(top = 20.dp)
-        ) {
+            Spacer(Modifier.height(16.dp))
             Text(
-                "${hourState.selectedOption} : " +
-                    "%02d".format(minuteState.selectedOption),
-                style = MaterialTheme.typography.title3.copy(color = Color.White)
+                text = when (selectedColumn) {
+                    0 -> "Hour"
+                    1 -> "Minute"
+                    else -> "Second"
+                },
+                color = optionColor,
+                style = MaterialTheme.typography.button,
+                maxLines = 1,
+            )
+            val weightsToCenterVertically = 0.5f
+            Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
+            Row(
+                modifier = Modifier.fillMaxWidth(),
+                verticalAlignment = Alignment.CenterVertically,
+                horizontalArrangement = Arrangement.SpaceEvenly,
+            ) {
+                val selectablePickerModifier = Modifier.size(54.dp, 120.dp)
+                val separation = (-10).dp
+                Spacer(Modifier.width(8.dp))
+                SelectablePicker(
+                    selected = selectedColumn == 0,
+                    state = rememberPickerState(numberOfOptions = 24, initiallySelectedOption = 6),
+                    modifier = selectablePickerModifier,
+                    separation = separation,
+                ) { hour: Int, selected: Boolean ->
+                    TimePiece(
+                        selected = selected,
+                        onSelected = { selectedColumn = 0 },
+                        text = "%02d".format(hour),
+                        style = textStyle,
+                    )
+                }
+                Separator(4.dp)
+                SelectablePicker(
+                    selected = selectedColumn == 1,
+                    state = rememberPickerState(numberOfOptions = 60),
+                    modifier = selectablePickerModifier,
+                    separation = separation,
+                ) { minute: Int, selected: Boolean ->
+                    TimePiece(
+                        selected = selected,
+                        onSelected = { selectedColumn = 1 },
+                        text = "%02d".format(minute),
+                        style = textStyle,
+                    )
+                }
+                Separator(4.dp)
+                SelectablePicker(
+                    selected = selectedColumn == 2,
+                    state = rememberPickerState(numberOfOptions = 60),
+                    modifier = selectablePickerModifier,
+                    separation = separation,
+                ) { second: Int, selected: Boolean ->
+                    TimePiece(
+                        selected = selected,
+                        onSelected = { selectedColumn = 2 },
+                        text = "%02d".format(second),
+                        style = textStyle,
+                    )
+                }
+                Spacer(Modifier.width(8.dp))
+            }
+            Spacer(Modifier.fillMaxWidth().weight(weightsToCenterVertically))
+            Button(onClick = {}) {
+                Icon(
+                    painter = painterResource(id = R.drawable.ic_check_24px),
+                    contentDescription = "check",
+                    modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
+                )
+            }
+            Spacer(Modifier.height(12.dp))
+        }
+    }
+}
+
+@OptIn(ExperimentalComposeUiApi::class)
+@Composable
+fun TimePickerWith12HourClock() {
+    var morning by remember { mutableStateOf(true) }
+    var selectedColumn by remember { mutableStateOf(0) }
+    Column(
+        modifier = Modifier.fillMaxSize(),
+        verticalArrangement = Arrangement.Center,
+        horizontalAlignment = Alignment.CenterHorizontally
+    ) {
+        Spacer(Modifier.height(16.dp))
+        CompactChip(
+            onClick = { morning = !morning },
+            modifier = Modifier.size(width = 50.dp, height = 24.dp),
+            label = {
+                Row(
+                    modifier = Modifier.fillMaxWidth(),
+                    horizontalArrangement = Arrangement.Center) {
+                    Text(
+                        text = if (morning) "AM" else "PM",
+                        color = MaterialTheme.colors.onPrimary,
+                        style = MaterialTheme.typography.button,
+                    )
+                }
+            },
+            colors = ChipDefaults.chipColors(backgroundColor = MaterialTheme.colors.secondary),
+            contentPadding = PaddingValues(vertical = 0.dp),
+        )
+        Spacer(Modifier.fillMaxWidth().weight(0.5f))
+        Row(
+            modifier = Modifier.fillMaxWidth(),
+            verticalAlignment = Alignment.CenterVertically,
+            horizontalArrangement = Arrangement.Center,
+        ) {
+            Spacer(Modifier.width(8.dp))
+            SelectablePicker(
+                selected = selectedColumn == 0,
+                state = rememberPickerState(numberOfOptions = 12, initiallySelectedOption = 6),
+                modifier = Modifier.size(64.dp, 120.dp),
+                separation = (-10).dp,
+                label = { LabelText("Hour") }
+            ) { hour: Int, selected: Boolean ->
+                TimePiece(
+                    selected = selected,
+                    onSelected = { selectedColumn = 0 },
+                    text = "%2d".format(hour + 1),
+                )
+            }
+            Separator(8.dp)
+            SelectablePicker(
+                selected = selectedColumn == 1,
+                state = rememberPickerState(numberOfOptions = 60),
+                modifier = Modifier.size(64.dp, 120.dp),
+                separation = (-10).dp,
+                label = { LabelText("Minute") }
+            ) { minute: Int, selected: Boolean ->
+                TimePiece(
+                    selected = selected,
+                    onSelected = { selectedColumn = 1 },
+                    text = "%02d".format(minute),
+                )
+            }
+            Spacer(Modifier.width(8.dp))
+        }
+        Spacer(Modifier.fillMaxWidth().weight(0.5f))
+        Button(onClick = {}) {
+            Icon(
+                painter = painterResource(id = R.drawable.ic_check_24px),
+                contentDescription = "check",
+                modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
+            )
+        }
+        Spacer(Modifier.height(12.dp))
+    }
+}
+
+/**
+ * [SelectablePicker] builds on the functionality of [Picker], displaying a [Picker] when selected
+ * and providing a slot for content (typically [Text]) otherwise.
+ *
+ * @param selected Determines whether the [SelectablePicker] is selected
+ * (in which case it shows a Picker).
+ * @param state The state of the component.
+ * @param modifier Modifier to be applied to the Picker. Typically provides size for the underlying
+ * [Picker].
+ * @param label A slot for providing a label, displayed above the [SelectablePicker]
+ * when unselected.
+ * @param scalingParams the parameters to configure the scaling and transparency effects for the
+ * component. See [ScalingParams]
+ * @param separation the amount of separation in [Dp] between items. Can be negative, which can be
+ * useful for Text if it has plenty of whitespace.
+ * @param option a block which describes the content. Inside this block you can reference
+ * [PickerScope.selectedOption] and other properties in [PickerScope]. The Int parameter determines
+ * the option index and the Boolean parameter determines whether the Pickable is selected (typically
+ * this is used to change the appearance of the content, e.g. by setting a highlight color).
+ */
+@OptIn(ExperimentalComposeUiApi::class)
+@Composable
+private fun SelectablePicker(
+    selected: Boolean,
+    state: PickerState,
+    modifier: Modifier = Modifier,
+    label: @Composable (BoxScope.() -> Unit)? = null,
+    scalingParams: ScalingParams = PickerDefaults.scalingParams(),
+    separation: Dp = 0.dp,
+    option: @Composable BoxScope.(Int, Boolean) -> Unit
+) {
+    Box(modifier = modifier) {
+        if (selected) {
+            Picker(
+                state = state,
+                modifier = Modifier.fillMaxSize(),
+                separation = separation,
+                scalingParams = scalingParams,
+            ) {
+                option(it, true)
+            }
+        } else {
+            if (label != null) {
+                label()
+            }
+            option(
+                state.selectedOption,
+                false
             )
         }
     }
-}
\ No newline at end of file
+}
+
+@OptIn(ExperimentalComposeUiApi::class)
+@Composable
+private fun BoxScope.TimePiece(
+    selected: Boolean,
+    onSelected: () -> Unit,
+    text: String,
+    style: TextStyle = MaterialTheme.typography.display1,
+) {
+    val modifier = Modifier.align(Alignment.Center).wrapContentSize()
+    Text(
+        text = text,
+        style = style,
+        color =
+            if (selected) MaterialTheme.colors.secondary
+            else MaterialTheme.colors.onBackground,
+        modifier =
+            if (selected) modifier
+            else modifier.pointerInteropFilter {
+                if (it.action == MotionEvent.ACTION_DOWN) onSelected()
+                true
+            },
+    )
+}
+
+@Composable
+private fun BoxScope.LabelText(text: String) {
+    Text(
+        text = text,
+        style = MaterialTheme.typography.button,
+        color = MaterialTheme.colors.onBackground,
+        modifier = Modifier.align(Alignment.TopCenter).offset(y = 12.dp)
+    )
+}
+
+@Composable
+private fun Separator(width: Dp) {
+    Spacer(Modifier.width(width))
+    Text(
+        text = ":",
+        style = MaterialTheme.typography.display2,
+        color = MaterialTheme.colors.onBackground
+    )
+    Spacer(Modifier.width(width))
+}
diff --git a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
index a00755a..832a6740 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
+++ b/wear/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/wear/compose/integration/macrobenchmark/target/BaselineActivity.kt
@@ -164,7 +164,6 @@
                         }
                         composable(PROGRESS_INDICATOR_INDETERMINATE) {
                             Column(
-                                modifier = Modifier.fillMaxSize(),
                                 verticalArrangement = Arrangement.Center,
                                 horizontalAlignment = Alignment.CenterHorizontally
                             ) {