Merge changes I79864ffd,I86422b7b,I7fd61193 into androidx-main

* changes:
  Add XMethodElement#name to reflect source name
  Add name property to XMethodElement
  Rename XMethodElement.name to jvmName
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0e45536..cfc87ae 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -35,12 +35,19 @@
 
 - Download and install JDK 11, if you don’t have it already.
 
+- Download and install the NDK
+
+  ```bash
+  sdkmanager --install "ndk;23.1.7779620"
+  ```
+
   Next, you need to set up the following environment variables:
 
   ```bash
   # You could also add this to your .{bash|zsh}rc file.
   export JAVA_HOME="location of JDK 11 folder"
   export ANDROID_SDK_ROOT="location of the Android SDK folder"
+  export ANDROID_NDK_ROOT="location of the Android NDK folder containing version 23.1.7779620"
   ```
 
 ### Checkout & Importing a Project
diff --git a/OWNERS b/OWNERS
index 8089367..5d06014 100644
--- a/OWNERS
+++ b/OWNERS
@@ -13,7 +13,6 @@
 mount@google.com
 nickanthony@google.com
 owengray@google.com
-pavlis@google.com
 romainguy@android.com
 saff@google.com
 sergeyv@google.com
diff --git a/activity/activity-compose/samples/lint-baseline.xml b/activity/activity-compose/samples/lint-baseline.xml
deleted file mode 100644
index 16095fa..0000000
--- a/activity/activity-compose/samples/lint-baseline.xml
+++ /dev/null
@@ -1,9779 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.1.0-beta02" type="baseline" client="gradle" dependencies="true" name="AGP (7.1.0-beta02)" variant="all" version="7.1.0-beta02">
-
-    <issue
-        id="WrongConstant"
-        message="Must be one or more of: AccessibilityEventCompat.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION, AccessibilityEventCompat.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION, AccessibilityEventCompat.CONTENT_CHANGE_TYPE_SUBTREE, AccessibilityEventCompat.CONTENT_CHANGE_TYPE_TEXT, AccessibilityEventCompat.CONTENT_CHANGE_TYPE_UNDEFINED, but could be AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE, AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED, AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED"
-        errorLine1="            return event.getContentChangeTypes();"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="344"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Action.SEMANTIC_ACTION_NONE, Action.SEMANTIC_ACTION_REPLY, Action.SEMANTIC_ACTION_MARK_AS_READ, Action.SEMANTIC_ACTION_MARK_AS_UNREAD, Action.SEMANTIC_ACTION_DELETE, Action.SEMANTIC_ACTION_ARCHIVE, Action.SEMANTIC_ACTION_MUTE, Action.SEMANTIC_ACTION_UNMUTE, Action.SEMANTIC_ACTION_THUMBS_UP, Action.SEMANTIC_ACTION_THUMBS_DOWN, Action.SEMANTIC_ACTION_CALL"
-        errorLine1="                    builder.setSemanticAction(action.getSemanticAction());"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4801"
-            column="47"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="                            ? remoteInput.getEditChoicesBeforeSending()"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="6443"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="                                ? src.getEditChoicesBeforeSending()"
-        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="7476"
-            column="35"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Action.SEMANTIC_ACTION_NONE, Action.SEMANTIC_ACTION_REPLY, Action.SEMANTIC_ACTION_MARK_AS_READ, Action.SEMANTIC_ACTION_MARK_AS_UNREAD, Action.SEMANTIC_ACTION_DELETE, Action.SEMANTIC_ACTION_ARCHIVE, Action.SEMANTIC_ACTION_MUTE, Action.SEMANTIC_ACTION_UNMUTE, Action.SEMANTIC_ACTION_THUMBS_UP, Action.SEMANTIC_ACTION_THUMBS_DOWN, Action.SEMANTIC_ACTION_CALL"
-        errorLine1="                actionBuilder.setSemanticAction(action.getSemanticAction());"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatBuilder.java"
-            line="390"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: LineBreaker.BREAK_STRATEGY_SIMPLE, LineBreaker.BREAK_STRATEGY_HIGH_QUALITY, LineBreaker.BREAK_STRATEGY_BALANCED"
-        errorLine1="                        .setBreakStrategy(params.getBreakStrategy())"
-        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="467"
-            column="43"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Layout.HYPHENATION_FREQUENCY_NORMAL, Layout.HYPHENATION_FREQUENCY_FULL, Layout.HYPHENATION_FREQUENCY_NONE"
-        errorLine1="                        .setHyphenationFrequency(params.getHyphenationFrequency())"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="468"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.SOURCE_FREE_FORM_INPUT, RemoteInput.SOURCE_CHOICE"
-        errorLine1="            return android.app.RemoteInput.getResultsSource(intent);"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="531"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="576"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="            builder.setEditChoicesBeforeSending(src.getEditChoicesBeforeSending());"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/RemoteInput.java"
-            line="598"
-            column="49"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: LineBreaker.BREAK_STRATEGY_SIMPLE, LineBreaker.BREAK_STRATEGY_HIGH_QUALITY, LineBreaker.BREAK_STRATEGY_BALANCED"
-        errorLine1="            textView.setBreakStrategy(params.getBreakStrategy());"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/TextViewCompat.java"
-            line="886"
-            column="39"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Layout.HYPHENATION_FREQUENCY_NORMAL, Layout.HYPHENATION_FREQUENCY_FULL, Layout.HYPHENATION_FREQUENCY_NONE"
-        errorLine1="            textView.setHyphenationFrequency(params.getHyphenationFrequency());"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/TextViewCompat.java"
-            line="887"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Callback.DISPATCH_MODE_STOP, Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE"
-        errorLine1="                super(compat.getDispatchMode());"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/WindowInsetsAnimationCompat.java"
-            line="968"
-            column="23"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one or more of: Type.STATUS_BARS, Type.NAVIGATION_BARS, Type.CAPTION_BAR, Type.IME, Type.WINDOW_DECOR, Type.SYSTEM_GESTURES, Type.MANDATORY_SYSTEM_GESTURES, Type.TAPPABLE_ELEMENT, Type.DISPLAY_CUTOUT"
-        errorLine1="            return mController.getTypes();"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/WindowInsetsAnimationControllerCompat.java"
-            line="332"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH, WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE, WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE"
-        errorLine1="        return mImpl.getSystemBarsBehavior();"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/WindowInsetsControllerCompat.java"
-            line="275"
-            column="16"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH, WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE, WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE, but could be WindowInsetsController.BEHAVIOR_DEFAULT"
-        errorLine1="            return mInsetsController.getSystemBarsBehavior();"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/WindowInsetsControllerCompat.java"
-            line="730"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                    requestRelaunchActivityMethod.invoke(activityThread,"
-        errorLine2="                    ^">
-        <location
-            file="src/main/java/androidx/core/app/ActivityRecreator.java"
-            line="152"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                            performStopActivity3ParamsMethod.invoke(activityThread,"
-        errorLine2="                            ^">
-        <location
-            file="src/main/java/androidx/core/app/ActivityRecreator.java"
-            line="274"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                            performStopActivity2ParamsMethod.invoke(activityThread,"
-        errorLine2="                            ^">
-        <location
-            file="src/main/java/androidx/core/app/ActivityRecreator.java"
-            line="277"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                    return (IBinder) sGetIBinderMethod.invoke(bundle, key);"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/BundleCompat.java"
-            line="60"
-            column="38"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                    sPutIBinderMethod.invoke(bundle, key, binder);"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/BundleCompat.java"
-            line="84"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (String) getMethod.invoke(systemProperties, name);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DisplayCompat.java"
-            line="135"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                return (String) sGetScriptMethod.invoke(null, args);"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/ICUCompat.java"
-            line="116"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                return (String) sAddLikelySubtagsMethod.invoke(null, args);"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/ICUCompat.java"
-            line="133"
-            column="33"/>
-    </issue>
-
-    <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="                return (Boolean) sActionBarOnMenuKeyMethod.invoke(actionBar, event);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/KeyEventDispatcher.java"
-            line="106"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                    Boolean result = (Boolean) sMethodUserHandleIsAppMethod.invoke(null, uid);"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ProcessCompat.java"
-            line="104"
-            column="48"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                    Boolean result = (Boolean) sMethodUserIdIsAppMethod.invoke(null, uid);"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ProcessCompat.java"
-            line="142"
-            column="48"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                            sRebaseMethod.invoke(theme);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/ResourcesCompat.java"
-            line="704"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                        removeItemAtMethod.invoke(menu, i);"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/TextViewCompat.java"
-            line="625"
-            column="25"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Typeface) sCreateFromFamiliesWithDefault.invoke("
-        errorLine2="                              ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi21Impl.java"
-            line="127"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            final Boolean result = (Boolean) sAddFontWeightStyle.invoke("
-        errorLine2="                                             ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi21Impl.java"
-            line="138"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            final Boolean result = (Boolean) sAddFontWeightStyle.invoke("
-        errorLine2="                                             ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi24Impl.java"
-            line="112"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Typeface) sCreateFromFamiliesWithDefault.invoke("
-        errorLine2="                              ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi24Impl.java"
-            line="124"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Boolean) mAddFontFromAssetManager.invoke(family,"
-        errorLine2="                             ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="140"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Boolean) mAddFontFromBuffer.invoke(family,"
-        errorLine2="                             ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="155"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Typeface) mCreateFromFamiliesWithDefault.invoke(null /* static method */,"
-        errorLine2="                              ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="171"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Boolean) mFreeze.invoke(family);"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="183"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            mAbortCreation.invoke(family);"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="194"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="            return (Typeface) mCreateFromFamiliesWithDefault.invoke(null /* static method */,"
-        errorLine2="                              ^">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi28Impl.java"
-            line="51"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="BanUncheckedReflection"
-        message="Calling `Method.invoke` without an SDK check"
-        errorLine1="                return (Boolean) sIsProjectedDrawableMethod.invoke(mDrawable);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/WrappedDrawableApi21.java"
-            line="131"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="PrivateConstructorForUtilityClass"
-        message="Utility class is missing private constructor"
-        errorLine1="public class NotificationCompat {"
-        errorLine2="             ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="82"
-            column="14"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `parent` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getParent() {"
-        errorLine2="                                       ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2164"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2179"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`CollectionInfoCompat`) and setter parameter type (`Object`) getter and setter methods for property `collectionInfo` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public CollectionInfoCompat getCollectionInfo() {"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2988"
-            column="33"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2998"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`CollectionItemInfoCompat`) and setter parameter type (`Object`) getter and setter methods for property `collectionItemInfo` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public CollectionItemInfoCompat getCollectionItemInfo() {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3021"
-            column="37"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3007"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `labelFor` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getLabelFor() {"
-        errorLine2="                                       ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3262"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3225"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `labeledBy` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getLabeledBy() {"
-        errorLine2="                                       ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3318"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3276"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="This method should be called `getCanOpenPopup` such that `canOpenPopup` can be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public boolean canOpenPopup() {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3331"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `traversalBefore` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getTraversalBefore() {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3533"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3555"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `traversalAfter` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getTraversalAfter() {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3598"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3620"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="The getter return type (`AccessibilityNodeInfoCompat`) and setter parameter type (`View`) getter and setter methods for property `source` should have exactly the same type to allow be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public AccessibilityNodeInfoCompat getSource() {"
-        errorLine2="                                       ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="159"
-            column="40"/>
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="97"
-            column="17"
-            message="Setter here"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="This method should be called `setLongpressEnabled` such that (along with the `isLongpressEnabled` getter) Kotlin code can access it as a property (`longpressEnabled`); see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public void setIsLongpressEnabled(boolean enabled) {"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="555"
-            column="17"/>
-    </issue>
-
-    <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="                   ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java"
-            line="181"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="KotlinPropertyAccess"
-        message="This method should be called `getAntiAlias` such that `antiAlias` can be accessed as a property from Kotlin; see https://android.github.io/kotlin-guides/interop.html#property-prefixes"
-        errorLine1="    public boolean hasAntiAlias() {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java"
-            line="205"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="LambdaLast"
-        message="Functional interface parameters (such as parameter 2, &quot;r&quot;, in androidx.core.os.HandlerCompat.postDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions"
-        errorLine1="            @Nullable Object token, long delayMillis) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/HandlerCompat.java"
-            line="181"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="LambdaLast"
-        message="Functional interface parameters (such as parameter 1, &quot;component&quot;, in androidx.core.view.KeyEventDispatcher.dispatchKeyEvent) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions"
-        errorLine1="            @Nullable View root, @Nullable Window.Callback callback, @NonNull KeyEvent event) {"
-        errorLine2="                                                                     ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/KeyEventDispatcher.java"
-            line="79"
-            column="70"/>
-    </issue>
-
-    <issue
-        id="LambdaLast"
-        message="Functional interface parameters (such as parameter 1, &quot;callable&quot;, in androidx.core.provider.SelfDestructiveThread.postAndWait) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions"
-        errorLine1="    public &lt;T> T postAndWait(final Callable&lt;T> callable, int timeoutMillis)"
-        errorLine2="                                                         ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/SelfDestructiveThread.java"
-            line="169"
-            column="58"/>
-    </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="            AccessibilityNodeInfoCompat nodeInfoCompat, int clickableSpanActionId) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityClickableSpanCompat.java"
-            line="55"
-            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 AccessibilityDelegateCompat(AccessibilityDelegate originalDelegate) {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="147"
-            column="40"/>
-    </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 void sendAccessibilityEvent(View host, int eventType) {"
-        errorLine2="                                       ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="173"
-            column="40"/>
-    </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 void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {"
-        errorLine2="                                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="195"
-            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 void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {"
-        errorLine2="                                                           ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="195"
-            column="60"/>
-    </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 boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                                      ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="216"
-            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 boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="216"
-            column="66"/>
-    </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 void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="236"
-            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 void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="236"
-            column="57"/>
-    </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 void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="256"
-            column="48"/>
-    </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 void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="256"
-            column="59"/>
-    </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 void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {"
-        errorLine2="                                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="275"
-            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 void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {"
-        errorLine2="                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="275"
-            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 boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,"
-        errorLine2="                                                   ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="299"
-            column="52"/>
-    </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 boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,"
-        errorLine2="                                                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="299"
-            column="68"/>
-    </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="            AccessibilityEvent event) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="300"
-            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 AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="318"
-            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 AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {"
-        errorLine2="                                                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="318"
-            column="73"/>
-    </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 boolean performAccessibilityAction(View host, int action, Bundle args) {"
-        errorLine2="                                              ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="344"
-            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 boolean performAccessibilityAction(View host, int action, Bundle args) {"
-        errorLine2="                                                                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/AccessibilityDelegateCompat.java"
-            line="344"
-            column="70"/>
-    </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 int getRecordCount(AccessibilityEvent event) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="257"
-            column="38"/>
-    </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 appendRecord(AccessibilityEvent event, AccessibilityRecordCompat record) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="273"
-            column="37"/>
-    </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 appendRecord(AccessibilityEvent event, AccessibilityRecordCompat record) {"
-        errorLine2="                                                              ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="273"
-            column="63"/>
-    </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 AccessibilityRecordCompat getRecord(AccessibilityEvent event, int index) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="287"
-            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 AccessibilityRecordCompat getRecord(AccessibilityEvent event, int index) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="287"
-            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 AccessibilityRecordCompat asRecord(AccessibilityEvent event) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="308"
-            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 AccessibilityRecordCompat asRecord(AccessibilityEvent event) {"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="308"
-            column="54"/>
-    </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 setContentChangeTypes(AccessibilityEvent event,"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="320"
-            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 int getContentChangeTypes(AccessibilityEvent event) {"
-        errorLine2="                                            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="342"
-            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 void setMovementGranularity(AccessibilityEvent event, int granularity) {"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="357"
-            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 int getMovementGranularity(AccessibilityEvent event) {"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="368"
-            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 setAction(AccessibilityEvent event, int action) {"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="393"
-            column="34"/>
-    </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 int getAction(AccessibilityEvent event) {"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java"
-            line="404"
-            column="33"/>
-    </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 boolean addAccessibilityStateChangeListener(AccessibilityManager manager,"
-        errorLine2="                                                              ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="45"
-            column="63"/>
-    </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="            AccessibilityStateChangeListener listener) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="46"
-            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 boolean removeAccessibilityStateChangeListener(AccessibilityManager manager,"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="66"
-            column="66"/>
-    </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="            AccessibilityStateChangeListener listener) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="67"
-            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 List&lt;AccessibilityServiceInfo> getInstalledAccessibilityServiceList("
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="118"
-            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="            AccessibilityManager manager) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="119"
-            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 List&lt;AccessibilityServiceInfo> getEnabledAccessibilityServiceList("
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="141"
-            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="            AccessibilityManager manager, int feedbackTypeFlags) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="142"
-            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 boolean isTouchExplorationEnabled(AccessibilityManager manager) {"
-        errorLine2="                                                    ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="155"
-            column="53"/>
-    </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 boolean addTouchExplorationStateChangeListener(AccessibilityManager manager,"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="166"
-            column="66"/>
-    </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="            TouchExplorationStateChangeListener listener) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="167"
-            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 boolean removeTouchExplorationStateChangeListener(AccessibilityManager manager,"
-        errorLine2="                                                                    ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="185"
-            column="69"/>
-    </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="            TouchExplorationStateChangeListener listener) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java"
-            line="186"
-            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 AccessibilityActionCompat(int actionId, CharSequence label) {"
-        errorLine2="                                                       ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="608"
-            column="56"/>
-    </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 AccessibilityActionCompat(int actionId, CharSequence label,"
-        errorLine2="                                                       ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="621"
-            column="56"/>
-    </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="                AccessibilityViewCommand command) {"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="622"
-            column="17"/>
-    </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/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="667"
-            column="16"/>
-    </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 boolean perform(View view, Bundle arguments) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="683"
-            column="32"/>
-    </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 boolean perform(View view, Bundle arguments) {"
-        errorLine2="                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="683"
-            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 AccessibilityActionCompat createReplacementAction(CharSequence label,"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="707"
-            column="16"/>
-    </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 AccessibilityActionCompat createReplacementAction(CharSequence label,"
-        errorLine2="                                                                 ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="707"
-            column="66"/>
-    </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="                AccessibilityViewCommand command) {"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="708"
-            column="17"/>
-    </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 CollectionInfoCompat obtain(int rowCount, int columnCount,"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="777"
-            column="23"/>
-    </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 CollectionInfoCompat obtain(int rowCount, int columnCount,"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="799"
-            column="23"/>
-    </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 CollectionItemInfoCompat obtain(int rowIndex, int rowSpan,"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="898"
-            column="23"/>
-    </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 CollectionItemInfoCompat obtain(int rowIndex, int rowSpan,"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="923"
-            column="23"/>
-    </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 RangeInfoCompat obtain(int type, float min, float max, float current) {"
-        errorLine2="                      ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1040"
-            column="23"/>
-    </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 AccessibilityNodeInfoCompat(Object info) {"
-        errorLine2="                                       ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1696"
-            column="40"/>
-    </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 AccessibilityNodeInfoCompat wrap(@NonNull AccessibilityNodeInfo info) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1710"
-            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 AccessibilityNodeInfo unwrap() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1717"
-            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 Object getInfo() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1727"
-            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 AccessibilityNodeInfoCompat obtain(View source) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1738"
-            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 AccessibilityNodeInfoCompat obtain(View source) {"
-        errorLine2="                                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1738"
-            column="54"/>
-    </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 AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1752"
-            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 AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) {"
-        errorLine2="                                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1752"
-            column="54"/>
-    </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 AccessibilityNodeInfoCompat obtain() {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1766"
-            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 AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1777"
-            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 AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1777"
-            column="54"/>
-    </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 void setSource(View source) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1786"
-            column="27"/>
-    </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 void setSource(View root, int virtualDescendantId) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1812"
-            column="27"/>
-    </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 AccessibilityNodeInfoCompat findFocus(int focus) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1832"
-            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 AccessibilityNodeInfoCompat focusSearch(int direction) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1854"
-            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 AccessibilityNodeInfoCompat getChild(int index) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1893"
-            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 void addChild(View child) {"
-        errorLine2="                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1908"
-            column="26"/>
-    </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 void addChild(View root, int virtualDescendantId) {"
-        errorLine2="                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1926"
-            column="26"/>
-    </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 boolean removeChild(View child) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1946"
-            column="32"/>
-    </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 boolean removeChild(View root, int virtualDescendantId) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="1964"
-            column="32"/>
-    </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 void addAction(AccessibilityActionCompat action) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2029"
-            column="27"/>
-    </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 boolean removeAction(AccessibilityActionCompat action) {"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2054"
-            column="33"/>
-    </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 boolean performAction(int action, Bundle arguments) {"
-        errorLine2="                                             ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2091"
-            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 List&lt;AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2143"
-            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 List&lt;AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {"
-        errorLine2="                                                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2143"
-            column="79"/>
-    </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 AccessibilityNodeInfoCompat getParent() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2164"
-            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 void setParent(View parent) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2179"
-            column="27"/>
-    </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 void setParent(View root, int virtualDescendantId) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2205"
-            column="27"/>
-    </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 void getBoundsInParent(Rect outBounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2226"
-            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 void setBoundsInParent(Rect bounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2249"
-            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 void getBoundsInScreen(Rect outBounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2258"
-            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 void setBoundsInScreen(Rect bounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2273"
-            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 CharSequence getPackageName() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2617"
-            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 void setPackageName(CharSequence packageName) {"
-        errorLine2="                               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2632"
-            column="32"/>
-    </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 getClassName() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2641"
-            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 void setClassName(CharSequence className) {"
-        errorLine2="                             ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2656"
-            column="30"/>
-    </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 getText() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2665"
-            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 void setText(CharSequence text) {"
-        errorLine2="                        ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2695"
-            column="25"/>
-    </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 void addSpansToExtras(CharSequence text, View view) {"
-        errorLine2="                                 ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2703"
-            column="34"/>
-    </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 void addSpansToExtras(CharSequence text, View view) {"
-        errorLine2="                                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2703"
-            column="53"/>
-    </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 ClickableSpan[] getClickableSpans(CharSequence text) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2740"
-            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 ClickableSpan[] getClickableSpans(CharSequence text) {"
-        errorLine2="                                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2740"
-            column="53"/>
-    </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 getContentDescription() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2801"
-            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 void setContentDescription(CharSequence contentDescription) {"
-        errorLine2="                                      ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2831"
-            column="39"/>
-    </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 void setViewIdResourceName(String viewId) {"
-        errorLine2="                                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2876"
-            column="39"/>
-    </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 getViewIdResourceName() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2894"
-            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 CollectionInfoCompat getCollectionInfo() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2988"
-            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 void setCollectionInfo(Object collectionInfo) {"
-        errorLine2="                                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="2998"
-            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 void setCollectionItemInfo(Object collectionItemInfo) {"
-        errorLine2="                                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3007"
-            column="39"/>
-    </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 CollectionItemInfoCompat getCollectionItemInfo() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3021"
-            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 RangeInfoCompat getRangeInfo() {"
-        errorLine2="           ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3036"
-            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 void setRangeInfo(RangeInfoCompat rangeInfo) {"
-        errorLine2="                             ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3056"
-            column="30"/>
-    </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 List&lt;AccessibilityActionCompat> getActionList() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3073"
-            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 void setError(CharSequence error) {"
-        errorLine2="                         ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3200"
-            column="26"/>
-    </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 getError() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3211"
-            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 void setLabelFor(View labeled) {"
-        errorLine2="                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3225"
-            column="29"/>
-    </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 void setLabelFor(View root, int virtualDescendantId) {"
-        errorLine2="                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3245"
-            column="29"/>
-    </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 AccessibilityNodeInfoCompat getLabelFor() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3262"
-            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 void setLabeledBy(View label) {"
-        errorLine2="                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3276"
-            column="30"/>
-    </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 void setLabeledBy(View root, int virtualDescendantId) {"
-        errorLine2="                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3301"
-            column="30"/>
-    </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 AccessibilityNodeInfoCompat getLabeledBy() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3318"
-            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 List&lt;AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByViewId(String viewId) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3378"
-            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 List&lt;AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByViewId(String viewId) {"
-        errorLine2="                                                                                ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3378"
-            column="81"/>
-    </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/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3404"
-            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 AccessibilityNodeInfoCompat getTraversalBefore() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3533"
-            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 void setTraversalBefore(View view) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3555"
-            column="36"/>
-    </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 void setTraversalBefore(View root, int virtualDescendantId) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3582"
-            column="36"/>
-    </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 AccessibilityNodeInfoCompat getTraversalAfter() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3598"
-            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 void setTraversalAfter(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3620"
-            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 void setTraversalAfter(View root, int virtualDescendantId) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3646"
-            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 AccessibilityWindowInfoCompat getWindow() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java"
-            line="3659"
-            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 AccessibilityNodeProviderCompat(Object provider) {"
-        errorLine2="                                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeProviderCompat.java"
-            line="137"
-            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="    public Object getProvider() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeProviderCompat.java"
-            line="144"
-            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 boolean performAction(int virtualViewId, int action, Bundle arguments) {"
-        errorLine2="                                                                ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeProviderCompat.java"
-            line="188"
-            column="65"/>
-    </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 List&lt;AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text,"
-        errorLine2="                                                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityNodeProviderCompat.java"
-            line="207"
-            column="79"/>
-    </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 AccessibilityRecordCompat(Object record) {"
-        errorLine2="                                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="43"
-            column="38"/>
-    </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 Object getImpl() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="54"
-            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 AccessibilityRecordCompat obtain(AccessibilityRecordCompat record) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="69"
-            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 AccessibilityRecordCompat obtain(AccessibilityRecordCompat record) {"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="69"
-            column="52"/>
-    </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 AccessibilityRecordCompat obtain() {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="83"
-            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 void setSource(View source) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="97"
-            column="27"/>
-    </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 void setSource(View root, int virtualDescendantId) {"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="118"
-            column="27"/>
-    </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 setSource(@NonNull AccessibilityRecord record, View root,"
-        errorLine2="                                                                      ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="137"
-            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="    public AccessibilityNodeInfoCompat getSource() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="159"
-            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 int getMaxScrollX(AccessibilityRecord record) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="481"
-            column="37"/>
-    </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 setMaxScrollX(AccessibilityRecord record, int maxScrollX) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="507"
-            column="38"/>
-    </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 int getMaxScrollY(AccessibilityRecord record) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="531"
-            column="37"/>
-    </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 setMaxScrollY(AccessibilityRecord record, int maxScrollY) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="557"
-            column="38"/>
-    </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 getClassName() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="623"
-            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 void setClassName(CharSequence className) {"
-        errorLine2="                             ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="637"
-            column="30"/>
-    </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 List&lt;CharSequence> getText() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="650"
-            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 getBeforeText() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="662"
-            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 void setBeforeText(CharSequence beforeText) {"
-        errorLine2="                              ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="676"
-            column="31"/>
-    </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 getContentDescription() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="688"
-            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 void setContentDescription(CharSequence contentDescription) {"
-        errorLine2="                                      ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="702"
-            column="39"/>
-    </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 getParcelableData() {"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="714"
-            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 void setParcelableData(Parcelable parcelableData) {"
-        errorLine2="                                  ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityRecordCompat.java"
-            line="728"
-            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 void setBundle(Bundle bundle) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityViewCommand.java"
-            line="53"
-            column="31"/>
-    </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 getHTMLElement() {"
-        errorLine2="               ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityViewCommand.java"
-            line="103"
-            column="16"/>
-    </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 getText() {"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityViewCommand.java"
-            line="138"
-            column="16"/>
-    </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 AccessibilityNodeInfoCompat getRoot() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="127"
-            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 AccessibilityWindowInfoCompat getParent() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="141"
-            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 void getBoundsInScreen(Rect outBounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="167"
-            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 AccessibilityWindowInfoCompat getChild(int index) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="233"
-            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 getTitle() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="247"
-            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 AccessibilityNodeInfoCompat getAnchor() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="260"
-            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 AccessibilityWindowInfoCompat obtain() {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="275"
-            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 AccessibilityWindowInfoCompat obtain(AccessibilityWindowInfoCompat info) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="291"
-            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 AccessibilityWindowInfoCompat obtain(AccessibilityWindowInfoCompat info) {"
-        errorLine2="                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java"
-            line="291"
-            column="56"/>
-    </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 ActionProvider(Context context) {"
-        errorLine2="                          ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="133"
-            column="27"/>
-    </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 Context getContext() {"
-        errorLine2="           ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="140"
-            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 abstract View onCreateActionView();"
-        errorLine2="                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="149"
-            column="21"/>
-    </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 View onCreateActionView(MenuItem forItem) {"
-        errorLine2="           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="163"
-            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 View onCreateActionView(MenuItem forItem) {"
-        errorLine2="                                   ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="163"
-            column="36"/>
-    </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 void onPrepareSubMenu(SubMenu subMenu) {"
-        errorLine2="                                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="262"
-            column="34"/>
-    </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 void setSubUiVisibilityListener(SubUiVisibilityListener listener) {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="282"
-            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="    public void setVisibilityListener(VisibilityListener listener) {"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ActionProvider.java"
-            line="292"
-            column="39"/>
-    </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 PermissionCompatDelegate getPermissionCompatDelegate() {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ActivityCompat.java"
-            line="173"
-            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 boolean invalidateOptionsMenu(Activity activity) {"
-        errorLine2="                                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ActivityCompat.java"
-            line="211"
-            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 DragAndDropPermissionsCompat requestDragAndDropPermissions(Activity activity,"
-        errorLine2="                                                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ActivityCompat.java"
-            line="605"
-            column="78"/>
-    </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="            DragEvent dragEvent) {"
-        errorLine2="            ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ActivityCompat.java"
-            line="606"
-            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="            Pair&lt;View, String>... sharedElements) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ActivityOptionsCompat.java"
-            line="206"
-            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 AutoScrollHelper setEnabled(boolean enabled) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/AutoScrollHelper.java"
-            line="235"
-            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 AutoScrollHelper setExclusive(boolean exclusive) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/AutoScrollHelper.java"
-            line="263"
-            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 boolean onTouch(View v, MotionEvent event) {"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/AutoScrollHelper.java"
-            line="465"
-            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 boolean onTouch(View v, MotionEvent event) {"
-        errorLine2="                                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/AutoScrollHelper.java"
-            line="465"
-            column="36"/>
-    </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="    int[] getAutoSizeTextAvailableSizes();"
-        errorLine2="    ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/AutoSizeableTextView.java"
-            line="151"
-            column="5"/>
-    </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 Builder(Locale locale) {"
-        errorLine2="                       ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="157"
-            column="24"/>
-    </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 Builder stereoReset(boolean stereoReset) {"
-        errorLine2="               ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="176"
-            column="16"/>
-    </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 Builder setTextDirectionHeuristic(TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="               ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="192"
-            column="16"/>
-    </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 Builder setTextDirectionHeuristic(TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="192"
-            column="50"/>
-    </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 BidiFormatter build() {"
-        errorLine2="               ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="204"
-            column="16"/>
-    </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 BidiFormatter getInstance() {"
-        errorLine2="                  ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="235"
-            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 BidiFormatter getInstance(boolean rtlContext) {"
-        errorLine2="                  ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="244"
-            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 BidiFormatter getInstance(Locale locale) {"
-        errorLine2="                  ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="253"
-            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 BidiFormatter getInstance(Locale locale) {"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="253"
-            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 boolean isRtl(String str) {"
-        errorLine2="                         ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="346"
-            column="26"/>
-    </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 boolean isRtl(CharSequence str) {"
-        errorLine2="                         ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="357"
-            column="26"/>
-    </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 unicodeWrap(String str, TextDirectionHeuristicCompat heuristic, boolean isolate) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="390"
-            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 unicodeWrap(String str, TextDirectionHeuristicCompat heuristic, boolean isolate) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="390"
-            column="31"/>
-    </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 unicodeWrap(String str, TextDirectionHeuristicCompat heuristic, boolean isolate) {"
-        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="390"
-            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 CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic,"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="409"
-            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 unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic,"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="409"
-            column="37"/>
-    </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 unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic,"
-        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="409"
-            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 String unicodeWrap(String str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="440"
-            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 unicodeWrap(String str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="440"
-            column="31"/>
-    </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 unicodeWrap(String str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="440"
-            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 CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="455"
-            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 unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="455"
-            column="37"/>
-    </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 unicodeWrap(CharSequence str, TextDirectionHeuristicCompat heuristic) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="455"
-            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 String unicodeWrap(String str, boolean isolate) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="468"
-            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 unicodeWrap(String str, boolean isolate) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="468"
-            column="31"/>
-    </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 unicodeWrap(CharSequence str, boolean isolate) {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="482"
-            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 unicodeWrap(CharSequence str, boolean isolate) {"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="482"
-            column="37"/>
-    </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 unicodeWrap(String str) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="493"
-            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 unicodeWrap(String str) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="493"
-            column="31"/>
-    </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 unicodeWrap(CharSequence str) {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="505"
-            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 unicodeWrap(CharSequence str) {"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/BidiFormatter.java"
-            line="505"
-            column="37"/>
-    </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 boolean onStateChanged(int[] stateSet) {"
-        errorLine2="                                  ~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/ComplexColorCompat.java"
-            line="107"
-            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 void putExtraData(ExtraData extraData) {"
-        errorLine2="                             ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ComponentActivity.java"
-            line="78"
-            column="30"/>
-    </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 &lt;T extends ExtraData> T getExtraData(Class&lt;T> extraDataClass) {"
-        errorLine2="                                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ComponentActivity.java"
-            line="106"
-            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 boolean superDispatchKeyEvent(KeyEvent event) {"
-        errorLine2="                                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ComponentActivity.java"
-            line="121"
-            column="42"/>
-    </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 boolean dispatchKeyShortcutEvent(KeyEvent event) {"
-        errorLine2="                                            ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ComponentActivity.java"
-            line="126"
-            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 boolean dispatchKeyEvent(KeyEvent event) {"
-        errorLine2="                                    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/ComponentActivity.java"
-            line="135"
-            column="37"/>
-    </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 Cursor query(ContentResolver resolver,"
-        errorLine2="                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="71"
-            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 Cursor query(ContentResolver resolver,"
-        errorLine2="                               ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="71"
-            column="32"/>
-    </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="            Uri uri, String[] projection, String selection, String[] selectionArgs,"
-        errorLine2="            ~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="72"
-            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="            Uri uri, String[] projection, String selection, String[] selectionArgs,"
-        errorLine2="                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="72"
-            column="22"/>
-    </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="            Uri uri, String[] projection, String selection, String[] selectionArgs,"
-        errorLine2="                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="72"
-            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="            Uri uri, String[] projection, String selection, String[] selectionArgs,"
-        errorLine2="                                                            ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="72"
-            column="61"/>
-    </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="            String sortOrder, CancellationSignal cancellationSignal) {"
-        errorLine2="            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="73"
-            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="            String sortOrder, CancellationSignal cancellationSignal) {"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/ContentResolverCompat.java"
-            line="73"
-            column="31"/>
-    </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="        Object getWrapper();"
-        errorLine2="        ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/CoreComponentFactory.java"
-            line="118"
-            column="9"/>
-    </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 String concatenateWhere(String a, String b) {"
-        errorLine2="                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="40"
-            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 String concatenateWhere(String a, String b) {"
-        errorLine2="                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="40"
-            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 String concatenateWhere(String a, String b) {"
-        errorLine2="                                                    ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="40"
-            column="53"/>
-    </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 String[] appendSelectionArgs(String[] originalValues, String[] newValues) {"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="59"
-            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 String[] appendSelectionArgs(String[] originalValues, String[] newValues) {"
-        errorLine2="                                               ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="59"
-            column="48"/>
-    </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 String[] appendSelectionArgs(String[] originalValues, String[] newValues) {"
-        errorLine2="                                                                        ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/database/DatabaseUtilsCompat.java"
-            line="59"
-            column="73"/>
-    </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 buildShortClassTag(Object cls, StringBuilder out) {"
-        errorLine2="                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/DebugUtils.java"
-            line="31"
-            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 buildShortClassTag(Object cls, StringBuilder out) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/DebugUtils.java"
-            line="31"
-            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 DisplayCutoutCompat(Rect safeInsets, List&lt;Rect> boundingRects) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DisplayCutoutCompat.java"
-            line="55"
-            column="32"/>
-    </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 DisplayCutoutCompat(Rect safeInsets, List&lt;Rect> boundingRects) {"
-        errorLine2="                                                ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DisplayCutoutCompat.java"
-            line="55"
-            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 DragAndDropPermissionsCompat request(Activity activity, DragEvent dragEvent) {"
-        errorLine2="                                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java"
-            line="49"
-            column="56"/>
-    </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 DragAndDropPermissionsCompat request(Activity activity, DragEvent dragEvent) {"
-        errorLine2="                                                                          ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java"
-            line="49"
-            column="75"/>
-    </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 onDragStart(View v, DragStartHelper helper);"
-        errorLine2="                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="87"
-            column="29"/>
-    </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 onDragStart(View v, DragStartHelper helper);"
-        errorLine2="                                    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="87"
-            column="37"/>
-    </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 DragStartHelper(View view, OnDragStartListener listener) {"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="96"
-            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 DragStartHelper(View view, OnDragStartListener listener) {"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="96"
-            column="39"/>
-    </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 boolean onTouch(View v, MotionEvent event) {"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="128"
-            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 boolean onTouch(View v, MotionEvent event) {"
-        errorLine2="                                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="128"
-            column="36"/>
-    </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 boolean onLongClick(View v) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="169"
-            column="32"/>
-    </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 void getTouchPosition(Point point) {"
-        errorLine2="                                 ~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/DragStartHelper.java"
-            line="177"
-            column="34"/>
-    </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 ColorFilter getColorFilter(@NonNull Drawable drawable) {"
-        errorLine2="                  ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/DrawableCompat.java"
-            line="209"
-            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 Drawable wrap(@NonNull Drawable drawable) {"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/DrawableCompat.java"
-            line="306"
-            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 EdgeEffectCompat(Context context) {"
-        errorLine2="                            ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/EdgeEffectCompat.java"
-            line="53"
-            column="29"/>
-    </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 boolean draw(Canvas canvas) {"
-        errorLine2="                        ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/EdgeEffectCompat.java"
-            line="294"
-            column="25"/>
-    </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 Uri getUriForFile(@NonNull Context context, @NonNull String authority,"
-        errorLine2="                  ~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="439"
-            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 Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="504"
-            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 getType(@NonNull Uri uri) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="546"
-            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 Uri insert(@NonNull Uri uri, ContentValues values) {"
-        errorLine2="           ~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="567"
-            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 Uri insert(@NonNull Uri uri, ContentValues values) {"
-        errorLine2="                                        ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="567"
-            column="41"/>
-    </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 int update(@NonNull Uri uri, ContentValues values, @Nullable String selection,"
-        errorLine2="                                        ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/FileProvider.java"
-            line="576"
-            column="41"/>
-    </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 AuthenticationResult(CryptoObject crypto) {"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java"
-            line="251"
-            column="37"/>
-    </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 CryptoObject getCryptoObject() { return mCryptoObject; }"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java"
-            line="260"
-            column="16"/>
-    </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 void onAuthenticationError(int errMsgId, CharSequence errString) { }"
-        errorLine2="                                                        ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java"
-            line="277"
-            column="57"/>
-    </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 void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { }"
-        errorLine2="                                                        ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java"
-            line="286"
-            column="57"/>
-    </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 void onAuthenticationSucceeded(AuthenticationResult result) { }"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/hardware/fingerprint/FingerprintManagerCompat.java"
-            line="292"
-            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 String getIdentifier() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontRequest.java"
-            line="156"
-            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 @Nullable FamilyResourceEntry parse(XmlPullParser parser, Resources resources)"
-        errorLine2="                                                      ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/FontResourcesParserCompat.java"
-            line="181"
-            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 @Nullable FamilyResourceEntry parse(XmlPullParser parser, Resources resources)"
-        errorLine2="                                                                            ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/FontResourcesParserCompat.java"
-            line="181"
-            column="77"/>
-    </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 List&lt;List&lt;byte[]&gt;> readCerts(Resources resources, @ArrayRes int certsId) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/FontResourcesParserCompat.java"
-            line="269"
-            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 List&lt;List&lt;byte[]&gt;> readCerts(Resources resources, @ArrayRes int certsId) {"
-        errorLine2="                                               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/FontResourcesParserCompat.java"
-            line="269"
-            column="48"/>
-    </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 FontInfo[] getFonts() {"
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="399"
-            column="16"/>
-    </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 void onTypefaceRetrieved(Typeface typeface) {}"
-        errorLine2="                                        ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="486"
-            column="41"/>
-    </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 Typeface getFontSync("
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="543"
-            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="            final Context context,"
-        errorLine2="                  ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="544"
-            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="            final FontRequest request,"
-        errorLine2="                  ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="545"
-            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 Map&lt;Uri, ByteBuffer> prepareFontData("
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="588"
-            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="            Context context,"
-        errorLine2="            ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="589"
-            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="            FontInfo[] fonts,"
-        errorLine2="            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="590"
-            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="            CancellationSignal cancellationSignal"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/FontsContractCompat.java"
-            line="591"
-            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 GestureDetectorCompat(Context context, OnGestureListener listener) {"
-        errorLine2="                                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="505"
-            column="34"/>
-    </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 GestureDetectorCompat(Context context, OnGestureListener listener) {"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="505"
-            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 GestureDetectorCompat(Context context, OnGestureListener listener, Handler handler) {"
-        errorLine2="                                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="519"
-            column="34"/>
-    </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 GestureDetectorCompat(Context context, OnGestureListener listener, Handler handler) {"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="519"
-            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 GestureDetectorCompat(Context context, OnGestureListener listener, Handler handler) {"
-        errorLine2="                                                                              ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="519"
-            column="79"/>
-    </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 boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="542"
-            column="33"/>
-    </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 void setOnDoubleTapListener(OnDoubleTapListener listener) {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GestureDetectorCompat.java"
-            line="566"
-            column="40"/>
-    </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 apply(int gravity, int w, int h, Rect container,"
-        errorLine2="                                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="62"
-            column="57"/>
-    </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="            Rect outRect, int layoutDirection) {"
-        errorLine2="            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="63"
-            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 apply(int gravity, int w, int h, Rect container,"
-        errorLine2="                                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="96"
-            column="57"/>
-    </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="            int xAdj, int yAdj, Rect outRect, int layoutDirection) {"
-        errorLine2="                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="97"
-            column="33"/>
-    </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 applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {"
-        errorLine2="                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="125"
-            column="50"/>
-    </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 applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {"
-        errorLine2="                                                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/GravityCompat.java"
-            line="125"
-            column="64"/>
-    </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 String maximizeAndGetScript(Locale locale) {"
-        errorLine2="                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/ICUCompat.java"
-            line="88"
-            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 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 IBinder onBind(@NonNull Intent intent) {"
-        errorLine2="           ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/JobIntentService.java"
-            line="468"
-            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="        boolean superDispatchKeyEvent(KeyEvent event);"
-        errorLine2="                                      ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/KeyEventDispatcher.java"
-            line="191"
-            column="39"/>
-    </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 LayoutInflaterFactory getFactory(LayoutInflater inflater) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterCompat.java"
-            line="169"
-            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 LayoutInflaterFactory getFactory(LayoutInflater inflater) {"
-        errorLine2="                                                   ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterCompat.java"
-            line="169"
-            column="52"/>
-    </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="    View onCreateView(View parent, String name, Context context, AttributeSet attrs);"
-        errorLine2="    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterFactory.java"
-            line="46"
-            column="5"/>
-    </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="    View onCreateView(View parent, String name, Context context, AttributeSet attrs);"
-        errorLine2="                      ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterFactory.java"
-            line="46"
-            column="23"/>
-    </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="    View onCreateView(View parent, String name, Context context, AttributeSet attrs);"
-        errorLine2="                                   ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterFactory.java"
-            line="46"
-            column="36"/>
-    </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="    View onCreateView(View parent, String name, Context context, AttributeSet attrs);"
-        errorLine2="                                                ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterFactory.java"
-            line="46"
-            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="    View onCreateView(View parent, String name, Context context, AttributeSet attrs);"
-        errorLine2="                                                                 ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/LayoutInflaterFactory.java"
-            line="46"
-            column="66"/>
-    </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 OnTouchListener createDragToOpenListener(Object listPopupWindow, View src) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ListPopupWindowCompat.java"
-            line="64"
-            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 OnTouchListener createDragToOpenListener(Object listPopupWindow, View src) {"
-        errorLine2="                                                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ListPopupWindowCompat.java"
-            line="64"
-            column="60"/>
-    </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 OnTouchListener createDragToOpenListener(Object listPopupWindow, View src) {"
-        errorLine2="                                                                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ListPopupWindowCompat.java"
-            line="64"
-            column="84"/>
-    </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 LocaleListCompat wrap(Object localeList) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/LocaleListCompat.java"
-            line="45"
-            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 LocaleListCompat wrap(Object localeList) {"
-        errorLine2="                                        ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/LocaleListCompat.java"
-            line="45"
-            column="41"/>
-    </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
-            file="src/main/java/androidx/core/os/LocaleListCompat.java"
-            line="85"
-            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 int indexOf(Locale locale) {"
-        errorLine2="                       ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/LocaleListCompat.java"
-            line="116"
-            column="24"/>
-    </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 LogWriter(String tag) {"
-        errorLine2="                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/LogWriter.java"
-            line="43"
-            column="22"/>
-    </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="    @Override public void write(char[] buf, int offset, int count) {"
-        errorLine2="                                ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/LogWriter.java"
-            line="55"
-            column="33"/>
-    </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 int getMarginStart(ViewGroup.MarginLayoutParams lp) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="41"
-            column="38"/>
-    </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 int getMarginEnd(ViewGroup.MarginLayoutParams lp) {"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="60"
-            column="36"/>
-    </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 setMarginStart(ViewGroup.MarginLayoutParams lp, int marginStart) {"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="79"
-            column="39"/>
-    </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 setMarginEnd(ViewGroup.MarginLayoutParams lp, int marginEnd) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="98"
-            column="37"/>
-    </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 boolean isMarginRelative(ViewGroup.MarginLayoutParams lp) {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="111"
-            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="    public static int getLayoutDirection(ViewGroup.MarginLayoutParams lp) {"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="125"
-            column="42"/>
-    </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 setLayoutDirection(ViewGroup.MarginLayoutParams lp, int layoutDirection) {"
-        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="149"
-            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 resolveLayoutDirection(ViewGroup.MarginLayoutParams lp,"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MarginLayoutParamsCompat.java"
-            line="159"
-            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 setShowAsAction(MenuItem item, int actionEnum) {"
-        errorLine2="                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuCompat.java"
-            line="35"
-            column="40"/>
-    </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 setGroupDividerEnabled(Menu menu, boolean enabled) {"
-        errorLine2="                                              ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuCompat.java"
-            line="45"
-            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="        boolean onMenuItemActionExpand(MenuItem item);"
-        errorLine2="                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="109"
-            column="40"/>
-    </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 onMenuItemActionCollapse(MenuItem item);"
-        errorLine2="                                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="118"
-            column="42"/>
-    </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 setShowAsAction(MenuItem item, int actionEnum) {"
-        errorLine2="                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="134"
-            column="40"/>
-    </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 MenuItem setActionView(MenuItem item, View view) {"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="152"
-            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 MenuItem setActionView(MenuItem item, View view) {"
-        errorLine2="                                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="152"
-            column="42"/>
-    </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 MenuItem setActionView(MenuItem item, View view) {"
-        errorLine2="                                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="152"
-            column="57"/>
-    </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 MenuItem setActionView(MenuItem item, int resId) {"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="174"
-            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 MenuItem setActionView(MenuItem item, int resId) {"
-        errorLine2="                                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="174"
-            column="42"/>
-    </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 View getActionView(MenuItem item) {"
-        errorLine2="                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="187"
-            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 View getActionView(MenuItem item) {"
-        errorLine2="                                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="187"
-            column="38"/>
-    </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 MenuItem setActionProvider(MenuItem item, ActionProvider provider) {"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="206"
-            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 MenuItem setActionProvider(MenuItem item, ActionProvider provider) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="206"
-            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 MenuItem setActionProvider(MenuItem item, ActionProvider provider) {"
-        errorLine2="                                                            ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="206"
-            column="61"/>
-    </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 ActionProvider getActionProvider(MenuItem item) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="223"
-            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 ActionProvider getActionProvider(MenuItem item) {"
-        errorLine2="                                                   ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="223"
-            column="52"/>
-    </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 boolean expandActionView(MenuItem item) {"
-        errorLine2="                                           ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="248"
-            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="    public static boolean collapseActionView(MenuItem item) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="267"
-            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 boolean isActionViewExpanded(MenuItem item) {"
-        errorLine2="                                               ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="283"
-            column="48"/>
-    </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 MenuItem setOnActionExpandListener(MenuItem item,"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="300"
-            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 MenuItem setOnActionExpandListener(MenuItem item,"
-        errorLine2="                                                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="300"
-            column="54"/>
-    </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="            final OnActionExpandListener listener) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="301"
-            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 void setContentDescription(MenuItem item, CharSequence contentDescription) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="321"
-            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 setContentDescription(MenuItem item, CharSequence contentDescription) {"
-        errorLine2="                                                            ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="321"
-            column="61"/>
-    </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 CharSequence getContentDescription(MenuItem item) {"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="334"
-            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 CharSequence getContentDescription(MenuItem item) {"
-        errorLine2="                                                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="334"
-            column="54"/>
-    </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 setTooltipText(MenuItem item, CharSequence tooltipText) {"
-        errorLine2="                                      ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="350"
-            column="39"/>
-    </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 setTooltipText(MenuItem item, CharSequence tooltipText) {"
-        errorLine2="                                                     ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="350"
-            column="54"/>
-    </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 CharSequence getTooltipText(MenuItem item) {"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="363"
-            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 CharSequence getTooltipText(MenuItem item) {"
-        errorLine2="                                              ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="363"
-            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 setShortcut(MenuItem item, char numericChar, char alphaChar,"
-        errorLine2="                                   ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="395"
-            column="36"/>
-    </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 setNumericShortcut(MenuItem item, char numericChar, int numericModifiers) {"
-        errorLine2="                                          ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="417"
-            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 int getNumericModifiers(MenuItem item) {"
-        errorLine2="                                          ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="435"
-            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 setAlphabeticShortcut(MenuItem item, char alphaChar, int alphaModifiers) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="462"
-            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 int getAlphabeticModifiers(MenuItem item) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="480"
-            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 setIconTintList(MenuItem item, ColorStateList tint) {"
-        errorLine2="                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="502"
-            column="40"/>
-    </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 setIconTintList(MenuItem item, ColorStateList tint) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="502"
-            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 ColorStateList getIconTintList(MenuItem item) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="514"
-            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 ColorStateList getIconTintList(MenuItem item) {"
-        errorLine2="                                                 ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="514"
-            column="50"/>
-    </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 setIconTintMode(MenuItem item, PorterDuff.Mode tintMode) {"
-        errorLine2="                                       ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="533"
-            column="40"/>
-    </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 setIconTintMode(MenuItem item, PorterDuff.Mode tintMode) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="533"
-            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 PorterDuff.Mode getIconTintMode(MenuItem item) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="547"
-            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 PorterDuff.Mode getIconTintMode(MenuItem item) {"
-        errorLine2="                                                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MenuItemCompat.java"
-            line="547"
-            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 int getActionMasked(MotionEvent event) {"
-        errorLine2="                                      ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="464"
-            column="39"/>
-    </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 int getActionIndex(MotionEvent event) {"
-        errorLine2="                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="476"
-            column="38"/>
-    </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 int findPointerIndex(MotionEvent event, int pointerId) {"
-        errorLine2="                                       ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="487"
-            column="40"/>
-    </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 int getPointerId(MotionEvent event, int pointerIndex) {"
-        errorLine2="                                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="498"
-            column="36"/>
-    </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 float getX(MotionEvent event, int pointerIndex) {"
-        errorLine2="                             ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="509"
-            column="30"/>
-    </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 float getY(MotionEvent event, int pointerIndex) {"
-        errorLine2="                             ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="520"
-            column="30"/>
-    </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 int getPointerCount(MotionEvent event) {"
-        errorLine2="                                      ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="531"
-            column="39"/>
-    </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 int getSource(MotionEvent event) {"
-        errorLine2="                                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="543"
-            column="33"/>
-    </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 boolean isFromSource(MotionEvent event, int source) {"
-        errorLine2="                                       ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="552"
-            column="40"/>
-    </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 float getAxisValue(MotionEvent event, int axis) {"
-        errorLine2="                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="569"
-            column="38"/>
-    </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 float getAxisValue(MotionEvent event, int axis, int pointerIndex) {"
-        errorLine2="                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="589"
-            column="38"/>
-    </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 int getButtonState(MotionEvent event) {"
-        errorLine2="                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/MotionEventCompat.java"
-            line="598"
-            column="38"/>
-    </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="        void onScrollChange(NestedScrollView v, int scrollX, int scrollY,"
-        errorLine2="                            ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="99"
-            column="29"/>
-    </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="            int dyUnconsumed, int[] offsetInWindow, int type) {"
-        errorLine2="                              ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="262"
-            column="31"/>
-    </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 boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow,"
-        errorLine2="                                                           ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="268"
-            column="60"/>
-    </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 boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow,"
-        errorLine2="                                                                           ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="268"
-            column="76"/>
-    </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="            int dyUnconsumed, int[] offsetInWindow) {"
-        errorLine2="                              ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="302"
-            column="31"/>
-    </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 boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {"
-        errorLine2="                                                           ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="308"
-            column="60"/>
-    </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 boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {"
-        errorLine2="                                                                           ~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="308"
-            column="76"/>
-    </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 void addView(View child) {"
-        errorLine2="                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="487"
-            column="25"/>
-    </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 void addView(View child, int index) {"
-        errorLine2="                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="496"
-            column="25"/>
-    </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 void addView(View child, ViewGroup.LayoutParams params) {"
-        errorLine2="                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="505"
-            column="25"/>
-    </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 void addView(View child, ViewGroup.LayoutParams params) {"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="505"
-            column="37"/>
-    </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 void addView(View child, int index, ViewGroup.LayoutParams params) {"
-        errorLine2="                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="514"
-            column="25"/>
-    </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 void addView(View child, int index, ViewGroup.LayoutParams params) {"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="514"
-            column="48"/>
-    </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 boolean dispatchKeyEvent(KeyEvent event) {"
-        errorLine2="                                    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="635"
-            column="37"/>
-    </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 boolean onInterceptTouchEvent(MotionEvent ev) {"
-        errorLine2="                                         ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="732"
-            column="42"/>
-    </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 boolean onTouchEvent(MotionEvent ev) {"
-        errorLine2="                                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="844"
-            column="33"/>
-    </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 boolean onGenericMotionEvent(MotionEvent event) {"
-        errorLine2="                                        ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1067"
-            column="41"/>
-    </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="    protected void measureChild(View child, int parentWidthMeasureSpec,"
-        errorLine2="                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1630"
-            column="33"/>
-    </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="    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,"
-        errorLine2="                                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1646"
-            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="    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {"
-        errorLine2="                                                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1814"
-            column="60"/>
-    </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 void requestChildFocus(View child, View focused) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1880"
-            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 void requestChildFocus(View child, View focused) {"
-        errorLine2="                                              ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1880"
-            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="            Rect previouslyFocusedRect) {"
-        errorLine2="            ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1900"
-            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 boolean requestChildRectangleOnScreen(View child, Rect rectangle,"
-        errorLine2="                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1927"
-            column="50"/>
-    </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 boolean requestChildRectangleOnScreen(View child, Rect rectangle,"
-        errorLine2="                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="1927"
-            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 void draw(Canvas canvas) {"
-        errorLine2="                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="2072"
-            column="22"/>
-    </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="    protected void onRestoreInstanceState(Parcelable state) {"
-        errorLine2="                                          ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="2151"
-            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="    protected Parcelable onSaveInstanceState() {"
-        errorLine2="              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/NestedScrollView.java"
-            line="2164"
-            column="15"/>
-    </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="    Notification.Builder getBuilder();"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationBuilderWithBuilderAccessor.java"
-            line="34"
-            column="5"/>
-    </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 Context mContext;"
-        errorLine2="               ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="901"
-            column="16"/>
-    </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 ArrayList&lt;Action> mActions = new ArrayList&lt;>();"
-        errorLine2="               ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="905"
-            column="16"/>
-    </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 ArrayList&lt;String> mPeople;"
-        errorLine2="               ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="967"
-            column="16"/>
-    </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 RemoteViews getContentView() {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2454"
-            column="16"/>
-    </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 RemoteViews getBigContentView() {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2462"
-            column="16"/>
-    </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 RemoteViews getHeadsUpContentView() {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2470"
-            column="16"/>
-    </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="        protected Builder mBuilder;"
-        errorLine2="                  ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2538"
-            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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2584"
-            column="27"/>
-    </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 RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2600"
-            column="16"/>
-    </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 RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2600"
-            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="        public RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2608"
-            column="16"/>
-    </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 RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2608"
-            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 RemoteViews makeHeadsUpContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2616"
-            column="16"/>
-    </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 RemoteViews makeHeadsUpContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2616"
-            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 Bitmap createColoredBitmap(int iconId, int color) {"
-        errorLine2="               ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2927"
-            column="16"/>
-    </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 void buildIntoRemoteViews(RemoteViews outerView,"
-        errorLine2="                                         ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2977"
-            column="42"/>
-    </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="                RemoteViews innerView) {"
-        errorLine2="                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="2978"
-            column="17"/>
-    </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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="3127"
-            column="27"/>
-    </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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="3357"
-            column="27"/>
-    </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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="3701"
-            column="27"/>
-    </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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4261"
-            column="27"/>
-    </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 void apply(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4362"
-            column="27"/>
-    </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 RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4373"
-            column="16"/>
-    </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 RemoteViews makeContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4373"
-            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="        public RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4390"
-            column="16"/>
-    </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 RemoteViews makeBigContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4390"
-            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 RemoteViews makeHeadsUpContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4411"
-            column="16"/>
-    </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 RemoteViews makeHeadsUpContentView(NotificationBuilderWithBuilderAccessor builder) {"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4411"
-            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 CharSequence title;"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4595"
-            column="16"/>
-    </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 actionIntent;"
-        errorLine2="               ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"
-            line="4600"
-            column="16"/>
-    </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 IBinder onBind(Intent intent) {"
-        errorLine2="           ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.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 IBinder onBind(Intent intent) {"
-        errorLine2="                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="47"
-            column="27"/>
-    </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 abstract void notify(String packageName, int id, String tag, Notification notification);"
-        errorLine2="                                ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="62"
-            column="33"/>
-    </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 abstract void notify(String packageName, int id, String tag, Notification notification);"
-        errorLine2="                                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="62"
-            column="61"/>
-    </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 abstract void notify(String packageName, int id, String tag, Notification notification);"
-        errorLine2="                                                                        ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="62"
-            column="73"/>
-    </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 abstract void cancel(String packageName, int id, String tag);"
-        errorLine2="                                ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="67"
-            column="33"/>
-    </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 abstract void cancel(String packageName, int id, String tag);"
-        errorLine2="                                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="67"
-            column="61"/>
-    </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 abstract void cancelAll(String packageName);"
-        errorLine2="                                   ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompatSideChannelService.java"
-            line="72"
-            column="36"/>
-    </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="    WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets);"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/OnApplyWindowInsetsListener.java"
-            line="42"
-            column="5"/>
-    </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="    WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets);"
-        errorLine2="                                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/OnApplyWindowInsetsListener.java"
-            line="42"
-            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="    WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets);"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/OnApplyWindowInsetsListener.java"
-            line="42"
-            column="52"/>
-    </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 void onViewAttachedToWindow(View v) {"
-        errorLine2="                                       ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/OneShotPreDrawListener.java"
-            line="89"
-            column="40"/>
-    </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 void onViewDetachedFromWindow(View v) {"
-        errorLine2="                                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/OneShotPreDrawListener.java"
-            line="94"
-            column="42"/>
-    </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 &lt;T> Parcelable.Creator&lt;T> newCreator("
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ParcelableCompat.java"
-            line="39"
-            column="23"/>
-    </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="            ParcelableCompatCreatorCallbacks&lt;T> callbacks) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ParcelableCompat.java"
-            line="40"
-            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="    T createFromParcel(Parcel in, ClassLoader loader);"
-        errorLine2="                       ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ParcelableCompatCreatorCallbacks.java"
-            line="40"
-            column="24"/>
-    </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="    T createFromParcel(Parcel in, ClassLoader loader);"
-        errorLine2="                                  ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/os/ParcelableCompatCreatorCallbacks.java"
-            line="40"
-            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="    T[] newArray(int size);"
-        errorLine2="    ~~~">
-        <location
-            file="src/main/java/androidx/core/os/ParcelableCompatCreatorCallbacks.java"
-            line="49"
-            column="5"/>
-    </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 Interpolator create(Path path) {"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java"
-            line="47"
-            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 Interpolator create(Path path) {"
-        errorLine2="                                      ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java"
-            line="47"
-            column="39"/>
-    </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 Interpolator create(float controlX, float controlY) {"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java"
-            line="62"
-            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 Interpolator create(float controlX1, float controlY1,"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java"
-            line="79"
-            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 Path createPathFromPathData(String pathData) {"
-        errorLine2="                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="72"
-            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 Path createPathFromPathData(String pathData) {"
-        errorLine2="                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="72"
-            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 PathDataNode[] createNodesFromPathData(String pathData) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="90"
-            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 PathDataNode[] createNodesFromPathData(String pathData) {"
-        errorLine2="                                                         ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="90"
-            column="58"/>
-    </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 PathDataNode[] deepCopyNodes(PathDataNode[] source) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="119"
-            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 PathDataNode[] deepCopyNodes(PathDataNode[] source) {"
-        errorLine2="                                               ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="119"
-            column="48"/>
-    </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 updateNodes(PathDataNode[] target, PathDataNode[] source) {"
-        errorLine2="                                   ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="162"
-            column="36"/>
-    </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 updateNodes(PathDataNode[] target, PathDataNode[] source) {"
-        errorLine2="                                                          ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="162"
-            column="59"/>
-    </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 boolean interpolatePathDataNodes(PathDataNode[] target, PathDataNode[] from,"
-        errorLine2="                                                   ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="313"
-            column="52"/>
-    </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 boolean interpolatePathDataNodes(PathDataNode[] target, PathDataNode[] from,"
-        errorLine2="                                                                          ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="313"
-            column="75"/>
-    </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="            PathDataNode[] to, float fraction) {"
-        errorLine2="            ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="314"
-            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 float[] mParams;"
-        errorLine2="               ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="350"
-            column="16"/>
-    </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 nodesToPath(PathDataNode[] node, Path path) {"
-        errorLine2="                                       ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="368"
-            column="40"/>
-    </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 nodesToPath(PathDataNode[] node, Path path) {"
-        errorLine2="                                                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="368"
-            column="61"/>
-    </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 void interpolatePathDataNode(PathDataNode nodeFrom, PathDataNode nodeTo,"
-        errorLine2="                                            ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="386"
-            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 void interpolatePathDataNode(PathDataNode nodeFrom, PathDataNode nodeTo,"
-        errorLine2="                                                                   ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/PathParser.java"
-            line="386"
-            column="68"/>
-    </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 Object getPointerIcon() {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.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 static PointerIconCompat getSystemIcon(Context context, int style) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="129"
-            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 PointerIconCompat getSystemIcon(Context context, int style) {"
-        errorLine2="                                                  ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="129"
-            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 PointerIconCompat create(Bitmap bitmap, float hotSpotX, float hotSpotY) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="150"
-            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 PointerIconCompat create(Bitmap bitmap, float hotSpotX, float hotSpotY) {"
-        errorLine2="                                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="150"
-            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="    public static PointerIconCompat load(Resources resources, int resourceId) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="179"
-            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 PointerIconCompat load(Resources resources, int resourceId) {"
-        errorLine2="                                         ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/PointerIconCompat.java"
-            line="179"
-            column="42"/>
-    </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 Builder setBreakStrategy(int strategy) {"
-        errorLine2="                   ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="143"
-            column="20"/>
-    </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 Builder setHyphenationFrequency(int frequency) {"
-        errorLine2="                   ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="161"
-            column="20"/>
-    </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 Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {"
-        errorLine2="                   ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="179"
-            column="20"/>
-    </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 PrecomputedTextCompat create(@NonNull CharSequence text, @NonNull Params params) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="428"
-            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 Future&lt;PrecomputedTextCompat> getTextFuture("
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="644"
-            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 void setSpan(Object what, int start, int end, int flags) {"
-        errorLine2="                        ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="670"
-            column="25"/>
-    </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 void removeSpan(Object what) {"
-        errorLine2="                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="686"
-            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 &lt;T> T[] getSpans(int start, int end, Class&lt;T> type) {"
-        errorLine2="               ~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="704"
-            column="16"/>
-    </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 &lt;T> T[] getSpans(int start, int end, Class&lt;T> type) {"
-        errorLine2="                                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="704"
-            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 int getSpanStart(Object tag) {"
-        errorLine2="                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="714"
-            column="29"/>
-    </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 int getSpanEnd(Object tag) {"
-        errorLine2="                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="719"
-            column="27"/>
-    </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 int getSpanFlags(Object tag) {"
-        errorLine2="                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="724"
-            column="29"/>
-    </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 int nextSpanTransition(int start, int limit, Class type) {"
-        errorLine2="                                                        ~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="729"
-            column="57"/>
-    </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 subSequence(int start, int end) {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/PrecomputedTextCompat.java"
-            line="749"
-            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 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 final void callbackSuccessAsync(final Typeface typeface, @Nullable Handler handler) {"
-        errorLine2="                                                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/ResourcesCompat.java"
-            line="437"
-            column="54"/>
-    </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 Typeface getFont(@NonNull Context context, @FontRes int id, TypedValue value,"
-        errorLine2="                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/ResourcesCompat.java"
-            line="506"
-            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 Typeface getFont(@NonNull Context context, @FontRes int id, TypedValue value,"
-        errorLine2="                                                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/ResourcesCompat.java"
-            line="506"
-            column="79"/>
-    </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
-            file="src/main/java/android/support/v4/os/ResultReceiver.java"
-            line="83"
-            column="27"/>
-    </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 void send(int resultCode, Bundle resultData) {"
-        errorLine2="                                     ~~~~~~">
-        <location
-            file="src/main/java/android/support/v4/os/ResultReceiver.java"
-            line="95"
-            column="38"/>
-    </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="    protected void onReceiveResult(int resultCode, Bundle resultData) {"
-        errorLine2="                                                   ~~~~~~">
-        <location
-            file="src/main/java/android/support/v4/os/ResultReceiver.java"
-            line="120"
-            column="52"/>
-    </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 void writeToParcel(Parcel out, int flags) {"
-        errorLine2="                              ~~~~~~">
-        <location
-            file="src/main/java/android/support/v4/os/ResultReceiver.java"
-            line="129"
-            column="31"/>
-    </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 void setColorFilter(ColorFilter cf) {"
-        errorLine2="                               ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java"
-            line="288"
-            column="32"/>
-    </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 ColorFilter getColorFilter() {"
-        errorLine2="           ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java"
-            line="294"
-            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="    protected void onBoundsChange(Rect bounds) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/RoundedBitmapDrawable.java"
-            line="344"
-            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 static void setQuickScaleEnabled(Object scaleGestureDetector, boolean enabled) {"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java"
-            line="39"
-            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="            ScaleGestureDetector scaleGestureDetector, boolean enabled) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java"
-            line="52"
-            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 boolean isQuickScaleEnabled(Object scaleGestureDetector) {"
-        errorLine2="                                              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java"
-            line="67"
-            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 boolean isQuickScaleEnabled(ScaleGestureDetector scaleGestureDetector) {"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java"
-            line="77"
-            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 ScrollerCompat create(Context context) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ScrollerCompat.java"
-            line="40"
-            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 ScrollerCompat create(Context context) {"
-        errorLine2="                                        ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ScrollerCompat.java"
-            line="40"
-            column="41"/>
-    </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 ScrollerCompat create(Context context, Interpolator interpolator) {"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ScrollerCompat.java"
-            line="48"
-            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 ScrollerCompat create(Context context, Interpolator interpolator) {"
-        errorLine2="                                        ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ScrollerCompat.java"
-            line="48"
-            column="41"/>
-    </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 ScrollerCompat create(Context context, Interpolator interpolator) {"
-        errorLine2="                                                         ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/ScrollerCompat.java"
-            line="48"
-            column="58"/>
-    </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="            String threadName, int priority, int destructAfterMillisec) {"
-        errorLine2="            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/SelfDestructiveThread.java"
-            line="83"
-            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 &lt;T> void postAndReply(final Callable&lt;T> callable, final ReplyCallback&lt;T> reply) {"
-        errorLine2="                                       ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/SelfDestructiveThread.java"
-            line="140"
-            column="40"/>
-    </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 &lt;T> void postAndReply(final Callable&lt;T> callable, final ReplyCallback&lt;T> reply) {"
-        errorLine2="                                                                   ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/SelfDestructiveThread.java"
-            line="140"
-            column="68"/>
-    </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 &lt;T> T postAndWait(final Callable&lt;T> callable, int timeoutMillis)"
-        errorLine2="                                   ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/provider/SelfDestructiveThread.java"
-            line="169"
-            column="36"/>
-    </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 void onSharedElementStart(List&lt;String> sharedElementNames,"
-        errorLine2="                                     ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="77"
-            column="38"/>
-    </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="            List&lt;View> sharedElements, List&lt;View> sharedElementSnapshots) {}"
-        errorLine2="            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="78"
-            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="            List&lt;View> sharedElements, List&lt;View> sharedElementSnapshots) {}"
-        errorLine2="                                       ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="78"
-            column="40"/>
-    </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 void onSharedElementEnd(List&lt;String> sharedElementNames,"
-        errorLine2="                                   ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="108"
-            column="36"/>
-    </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="            List&lt;View> sharedElements, List&lt;View> sharedElementSnapshots) {}"
-        errorLine2="            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="109"
-            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="            List&lt;View> sharedElements, List&lt;View> sharedElementSnapshots) {}"
-        errorLine2="                                       ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="109"
-            column="40"/>
-    </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 void onRejectSharedElements(List&lt;View> rejectedSharedElements) {}"
-        errorLine2="                                       ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="133"
-            column="40"/>
-    </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 void onMapSharedElements(List&lt;String> names, Map&lt;String, View> sharedElements) {}"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="144"
-            column="37"/>
-    </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 void onMapSharedElements(List&lt;String> names, Map&lt;String, View> sharedElements) {}"
-        errorLine2="                                                        ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="144"
-            column="57"/>
-    </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 onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="166"
-            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 onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,"
-        errorLine2="                                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="166"
-            column="54"/>
-    </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 onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,"
-        errorLine2="                                                                         ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="166"
-            column="74"/>
-    </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="            RectF screenBounds) {"
-        errorLine2="            ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="167"
-            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 View onCreateSnapshotView(Context context, Parcelable snapshot) {"
-        errorLine2="           ~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="256"
-            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 View onCreateSnapshotView(Context context, Parcelable snapshot) {"
-        errorLine2="                                     ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="256"
-            column="38"/>
-    </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 View onCreateSnapshotView(Context context, Parcelable snapshot) {"
-        errorLine2="                                                      ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="256"
-            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 void onSharedElementsArrived(List&lt;String> sharedElementNames,"
-        errorLine2="                                        ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="299"
-            column="41"/>
-    </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="            List&lt;View> sharedElements, OnSharedElementsReadyListener listener) {"
-        errorLine2="            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="300"
-            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="            List&lt;View> sharedElements, OnSharedElementsReadyListener listener) {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/SharedElementCallback.java"
-            line="300"
-            column="40"/>
-    </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 EditorCompat getInstance() {"
-        errorLine2="                      ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/SharedPreferencesCompat.java"
-            line="65"
-            column="23"/>
-    </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 ShortcutInfo toShortcutInfo() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java"
-            line="107"
-            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 getIcon() {"
-        errorLine2="           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java"
-            line="325"
-            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 Builder setIcon(IconCompat icon) {"
-        errorLine2="                               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java"
-            line="662"
-            column="32"/>
-    </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 abstract T addShortcuts(List&lt;ShortcutInfoCompat> shortcuts);"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="38"
-            column="36"/>
-    </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 abstract T removeShortcuts(List&lt;String> shortcutIds);"
-        errorLine2="                                      ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="41"
-            column="39"/>
-    </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 List&lt;ShortcutInfoCompat> getShortcuts() throws Exception {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.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 Void addShortcuts(List&lt;ShortcutInfoCompat> shortcuts) {"
-        errorLine2="               ~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="59"
-            column="16"/>
-    </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 Void addShortcuts(List&lt;ShortcutInfoCompat> shortcuts) {"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="59"
-            column="34"/>
-    </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 Void removeShortcuts(List&lt;String> shortcutIds) {"
-        errorLine2="               ~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="64"
-            column="16"/>
-    </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 Void removeShortcuts(List&lt;String> shortcutIds) {"
-        errorLine2="                                    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="64"
-            column="37"/>
-    </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 Void removeAllShortcuts() {"
-        errorLine2="               ~~~~">
-        <location
-            file="src/main/java/androidx/core/content/pm/ShortcutInfoCompatSaver.java"
-            line="69"
-            column="16"/>
-    </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="    MenuItem setShowAsActionFlags(int actionEnum);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="107"
-            column="5"/>
-    </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="    MenuItem setActionView(View view);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="122"
-            column="5"/>
-    </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="    MenuItem setActionView(View view);"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="122"
-            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="    MenuItem setActionView(int resId);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="137"
-            column="5"/>
-    </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="    View getActionView();"
-        errorLine2="    ~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="147"
-            column="5"/>
-    </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="    SupportMenuItem setSupportActionProvider(ActionProvider actionProvider);"
-        errorLine2="    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="162"
-            column="5"/>
-    </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="    SupportMenuItem setSupportActionProvider(ActionProvider actionProvider);"
-        errorLine2="                                             ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="162"
-            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="    ActionProvider getSupportActionProvider();"
-        errorLine2="    ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="171"
-            column="5"/>
-    </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="    SupportMenuItem setContentDescription(CharSequence contentDescription);"
-        errorLine2="    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="220"
-            column="5"/>
-    </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="    SupportMenuItem setContentDescription(CharSequence contentDescription);"
-        errorLine2="                                          ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="220"
-            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="    CharSequence getContentDescription();"
-        errorLine2="    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="228"
-            column="5"/>
-    </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="    SupportMenuItem setTooltipText(CharSequence tooltipText);"
-        errorLine2="    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="237"
-            column="5"/>
-    </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="    SupportMenuItem setTooltipText(CharSequence tooltipText);"
-        errorLine2="                                   ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="237"
-            column="36"/>
-    </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="    CharSequence getTooltipText();"
-        errorLine2="    ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="245"
-            column="5"/>
-    </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="    MenuItem setShortcut(char numericChar, char alphaChar, int numericModifiers,"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="271"
-            column="5"/>
-    </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="    MenuItem setNumericShortcut(char numericChar, int numericModifiers);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="288"
-            column="5"/>
-    </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="    MenuItem setAlphabeticShortcut(char alphaChar, int alphaModifiers);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="322"
-            column="5"/>
-    </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="    MenuItem setIconTintList(ColorStateList tint);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="350"
-            column="5"/>
-    </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="    MenuItem setIconTintList(ColorStateList tint);"
-        errorLine2="                             ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="350"
-            column="30"/>
-    </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="    ColorStateList getIconTintList();"
-        errorLine2="    ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="357"
-            column="5"/>
-    </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="    MenuItem setIconTintMode(PorterDuff.Mode tintMode);"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="369"
-            column="5"/>
-    </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="    MenuItem setIconTintMode(PorterDuff.Mode tintMode);"
-        errorLine2="                             ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="369"
-            column="30"/>
-    </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="    PorterDuff.Mode getIconTintMode();"
-        errorLine2="    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/internal/view/SupportMenuItem.java"
-            line="378"
-            column="5"/>
-    </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 TaskStackBuilder from(Context context) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="108"
-            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 TaskStackBuilder from(Context context) {"
-        errorLine2="                                        ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="108"
-            column="41"/>
-    </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="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="    public Intent getIntent(int index) {"
-        errorLine2="           ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="233"
-            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 Iterator&lt;Intent> iterator() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/TaskStackBuilder.java"
-            line="255"
-            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="    boolean isRtl(char[] array, int start, int count);"
-        errorLine2="                  ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/TextDirectionHeuristicCompat.java"
-            line="33"
-            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="    boolean isRtl(CharSequence cs, int start, int count);"
-        errorLine2="                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/text/TextDirectionHeuristicCompat.java"
-            line="45"
-            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 void formatDuration(long duration, StringBuilder builder) {"
-        errorLine2="                                                     ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/TimeUtils.java"
-            line="153"
-            column="54"/>
-    </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 formatDuration(long duration, PrintWriter pw, int fieldLen) {"
-        errorLine2="                                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/TimeUtils.java"
-            line="162"
-            column="54"/>
-    </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 formatDuration(long duration, PrintWriter pw) {"
-        errorLine2="                                                     ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/TimeUtils.java"
-            line="171"
-            column="54"/>
-    </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 formatDuration(long time, long now, PrintWriter pw) {"
-        errorLine2="                                                           ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/util/TimeUtils.java"
-            line="177"
-            column="60"/>
-    </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="    void setTintList(ColorStateList tint);"
-        errorLine2="                     ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/TintAwareDrawable.java"
-            line="36"
-            column="22"/>
-    </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="    void setTintMode(PorterDuff.Mode tintMode);"
-        errorLine2="                     ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/TintAwareDrawable.java"
-            line="37"
-            column="22"/>
-    </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 tagSocket(Socket socket) throws SocketException {"
-        errorLine2="                                 ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/net/TrafficStatsCompat.java"
-            line="113"
-            column="34"/>
-    </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 untagSocket(Socket socket) throws SocketException {"
-        errorLine2="                                   ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/net/TrafficStatsCompat.java"
-            line="123"
-            column="36"/>
-    </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 ComplexColorCompat getNamedComplexColor(@NonNull TypedArray a,"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/content/res/TypedArrayUtils.java"
-            line="137"
-            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="            @NonNull Context context, @NonNull Resources resources, int id, String path,"
-        errorLine2="                                                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompat.java"
-            line="172"
-            column="77"/>
-    </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="    protected Typeface createFromFamiliesWithDefault(Object family) {"
-        errorLine2="                                                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="167"
-            column="54"/>
-    </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 Typeface createFromFontFamilyFilesResourceEntry(Context context,"
-        errorLine2="                                                           ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="200"
-            column="60"/>
-    </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="            FontResourcesParserCompat.FontFamilyFilesResourceEntry entry, Resources resources,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="201"
-            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="            FontResourcesParserCompat.FontFamilyFilesResourceEntry entry, Resources resources,"
-        errorLine2="                                                                          ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="201"
-            column="75"/>
-    </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 Typeface createFromFontInfo(Context context,"
-        errorLine2="                                       ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="226"
-            column="40"/>
-    </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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="            ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="290"
-            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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="                             ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="290"
-            column="30"/>
-    </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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="                                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="290"
-            column="59"/>
-    </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="    protected Class&lt;?> obtainFontFamily() throws ClassNotFoundException {"
-        errorLine2="              ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="315"
-            column="15"/>
-    </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="    protected Constructor&lt;?> obtainFontFamilyCtor(Class&lt;?> fontFamily)"
-        errorLine2="              ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="319"
-            column="15"/>
-    </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="    protected Constructor&lt;?> obtainFontFamilyCtor(Class&lt;?> fontFamily)"
-        errorLine2="                                                  ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="319"
-            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="    protected Method obtainAddFontFromAssetManagerMethod(Class&lt;?> fontFamily)"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="324"
-            column="15"/>
-    </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="    protected Method obtainAddFontFromAssetManagerMethod(Class&lt;?> fontFamily)"
-        errorLine2="                                                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="324"
-            column="58"/>
-    </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="    protected Method obtainAddFontFromBufferMethod(Class&lt;?> fontFamily)"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="331"
-            column="15"/>
-    </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="    protected Method obtainAddFontFromBufferMethod(Class&lt;?> fontFamily)"
-        errorLine2="                                                   ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="331"
-            column="52"/>
-    </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="    protected Method obtainFreezeMethod(Class&lt;?> fontFamily) throws NoSuchMethodException {"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="338"
-            column="15"/>
-    </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="    protected Method obtainFreezeMethod(Class&lt;?> fontFamily) throws NoSuchMethodException {"
-        errorLine2="                                        ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="338"
-            column="41"/>
-    </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="    protected Method obtainAbortCreationMethod(Class&lt;?> fontFamily) throws NoSuchMethodException {"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="342"
-            column="15"/>
-    </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="    protected Method obtainAbortCreationMethod(Class&lt;?> fontFamily) throws NoSuchMethodException {"
-        errorLine2="                                               ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="342"
-            column="48"/>
-    </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="    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class&lt;?> fontFamily)"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="346"
-            column="15"/>
-    </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="    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class&lt;?> fontFamily)"
-        errorLine2="                                                               ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi26Impl.java"
-            line="346"
-            column="64"/>
-    </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="    protected Typeface createFromFamiliesWithDefault(Object family) {"
-        errorLine2="              ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi28Impl.java"
-            line="47"
-            column="15"/>
-    </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="    protected Typeface createFromFamiliesWithDefault(Object family) {"
-        errorLine2="                                                     ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi28Impl.java"
-            line="47"
-            column="54"/>
-    </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="    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class&lt;?> fontFamily)"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi28Impl.java"
-            line="59"
-            column="15"/>
-    </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="    protected Method obtainCreateFromFamiliesWithDefaultMethod(Class&lt;?> fontFamily)"
-        errorLine2="                                                               ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi28Impl.java"
-            line="59"
-            column="64"/>
-    </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="    protected FontsContractCompat.FontInfo findBestInfo(FontsContractCompat.FontInfo[] fonts,"
-        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="46"
-            column="15"/>
-    </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="    protected FontsContractCompat.FontInfo findBestInfo(FontsContractCompat.FontInfo[] fonts,"
-        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="46"
-            column="57"/>
-    </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="    protected Typeface createFromInputStream(Context context, InputStream is) {"
-        errorLine2="              ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="53"
-            column="15"/>
-    </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="    protected Typeface createFromInputStream(Context context, InputStream is) {"
-        errorLine2="                                             ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="53"
-            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="    protected Typeface createFromInputStream(Context context, InputStream is) {"
-        errorLine2="                                                              ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="53"
-            column="63"/>
-    </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 Typeface createFromFontInfo(Context context,"
-        errorLine2="                                       ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="59"
-            column="40"/>
-    </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 Typeface createFromFontFamilyFilesResourceEntry(Context context,"
-        errorLine2="                                                           ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="105"
-            column="60"/>
-    </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="            FontResourcesParserCompat.FontFamilyFilesResourceEntry familyEntry, Resources resources,"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="106"
-            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="            FontResourcesParserCompat.FontFamilyFilesResourceEntry familyEntry, Resources resources,"
-        errorLine2="                                                                                ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="106"
-            column="81"/>
-    </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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="            ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="151"
-            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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="                             ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="151"
-            column="30"/>
-    </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="            Context context, Resources resources, int id, String path, int style) {"
-        errorLine2="                                                          ~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatApi29Impl.java"
-            line="151"
-            column="59"/>
-    </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 File getTempFile(Context context) {"
-        errorLine2="                                   ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="68"
-            column="36"/>
-    </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 ByteBuffer mmap(Context context, CancellationSignal cancellationSignal, Uri uri) {"
-        errorLine2="                                  ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="108"
-            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 static ByteBuffer mmap(Context context, CancellationSignal cancellationSignal, Uri uri) {"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="108"
-            column="52"/>
-    </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 ByteBuffer mmap(Context context, CancellationSignal cancellationSignal, Uri uri) {"
-        errorLine2="                                                                                          ~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="108"
-            column="91"/>
-    </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 ByteBuffer copyToDirectBuffer(Context context, Resources res, int id) {"
-        errorLine2="                                                ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="129"
-            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 ByteBuffer copyToDirectBuffer(Context context, Resources res, int id) {"
-        errorLine2="                                                                 ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="129"
-            column="66"/>
-    </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 boolean copyToFile(File file, InputStream is) {"
-        errorLine2="                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="147"
-            column="38"/>
-    </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 boolean copyToFile(File file, InputStream is) {"
-        errorLine2="                                                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="147"
-            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 boolean copyToFile(File file, Resources res, int id) {"
-        errorLine2="                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="170"
-            column="38"/>
-    </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 boolean copyToFile(File file, Resources res, int id) {"
-        errorLine2="                                                ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="170"
-            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 void closeQuietly(Closeable c) {"
-        errorLine2="                                    ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/TypefaceCompatUtil.java"
-            line="180"
-            column="37"/>
-    </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 float getXVelocity(VelocityTracker tracker, int pointerId) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/VelocityTrackerCompat.java"
-            line="36"
-            column="38"/>
-    </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 float getYVelocity(VelocityTracker tracker, int pointerId) {"
-        errorLine2="                                     ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/VelocityTrackerCompat.java"
-            line="48"
-            column="38"/>
-    </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 boolean canScrollHorizontally(View view, int direction) {"
-        errorLine2="                                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="543"
-            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 boolean canScrollVertically(View view, int direction) {"
-        errorLine2="                                              ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="556"
-            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 int getOverScrollMode(View v) {"
-        errorLine2="                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="573"
-            column="41"/>
-    </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 setOverScrollMode(View v, @OverScroll int overScrollMode) {"
-        errorLine2="                                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="593"
-            column="42"/>
-    </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 onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {"
-        errorLine2="                                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="633"
-            column="53"/>
-    </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 onPopulateAccessibilityEvent(View v, AccessibilityEvent event) {"
-        errorLine2="                                                            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="633"
-            column="61"/>
-    </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 onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {"
-        errorLine2="                                                      ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="665"
-            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 void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) {"
-        errorLine2="                                                              ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="665"
-            column="63"/>
-    </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 float getAlpha(View view) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1469"
-            column="34"/>
-    </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 setLayerType(View view, @LayerType int layerType, Paint paint) {"
-        errorLine2="                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1508"
-            column="37"/>
-    </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 setLayerType(View view, @LayerType int layerType, Paint paint) {"
-        errorLine2="                                                                         ~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1508"
-            column="74"/>
-    </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 int getLayerType(View view) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1532"
-            column="36"/>
-    </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 boolean isOpaque(View view) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1700"
-            column="36"/>
-    </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 int getMeasuredWidthAndState(View view) {"
-        errorLine2="                                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1737"
-            column="48"/>
-    </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 int getMeasuredHeightAndState(View view) {"
-        errorLine2="                                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1754"
-            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 int getMeasuredState(View view) {"
-        errorLine2="                                       ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1768"
-            column="40"/>
-    </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 float getTranslationX(View view) {"
-        errorLine2="                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1960"
-            column="41"/>
-    </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 float getTranslationY(View view) {"
-        errorLine2="                                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1974"
-            column="41"/>
-    </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 Matrix getMatrix(View view) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="1996"
-            column="36"/>
-    </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 setTranslationX(View view, float value) {"
-        errorLine2="                                       ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2102"
-            column="40"/>
-    </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 setTranslationY(View view, float value) {"
-        errorLine2="                                       ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2119"
-            column="40"/>
-    </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 setAlpha(View view, @FloatRange(from = 0.0, to = 1.0) float value) {"
-        errorLine2="                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2136"
-            column="33"/>
-    </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 setX(View view, float value) {"
-        errorLine2="                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2151"
-            column="29"/>
-    </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 setY(View view, float value) {"
-        errorLine2="                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2166"
-            column="29"/>
-    </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 setRotation(View view, float value) {"
-        errorLine2="                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2179"
-            column="36"/>
-    </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 setRotationX(View view, float value) {"
-        errorLine2="                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2193"
-            column="37"/>
-    </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 setRotationY(View view, float value) {"
-        errorLine2="                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2207"
-            column="37"/>
-    </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 setScaleX(View view, float value) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2220"
-            column="34"/>
-    </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 setScaleY(View view, float value) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2233"
-            column="34"/>
-    </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 float getPivotX(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2244"
-            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 static void setPivotX(View view, float value) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2260"
-            column="34"/>
-    </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 float getPivotY(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2273"
-            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 static void setPivotY(View view, float value) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2289"
-            column="34"/>
-    </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 float getRotation(View view) {"
-        errorLine2="                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2297"
-            column="37"/>
-    </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 float getRotationX(View view) {"
-        errorLine2="                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2305"
-            column="38"/>
-    </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 float getRotationY(View view) {"
-        errorLine2="                                     ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2313"
-            column="38"/>
-    </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 float getScaleX(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2321"
-            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 static float getScaleY(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2329"
-            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 static float getX(View view) {"
-        errorLine2="                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2337"
-            column="30"/>
-    </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 float getY(View view) {"
-        errorLine2="                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2345"
-            column="30"/>
-    </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 setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled) {"
-        errorLine2="                                                      ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2469"
-            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 void setFitsSystemWindows(View view, boolean fitSystemWindows) {"
-        errorLine2="                                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2510"
-            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 void jumpDrawablesToCurrentState(View v) {"
-        errorLine2="                                                   ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2524"
-            column="52"/>
-    </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 setSaveFromParentEnabled(View v, boolean enabled) {"
-        errorLine2="                                                ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2930"
-            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 void setActivated(View view, boolean activated) {"
-        errorLine2="                                    ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewCompat.java"
-            line="2946"
-            column="37"/>
-    </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 int getScaledPagingTouchSlop(ViewConfiguration config) {"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewConfigurationCompat.java"
-            line="56"
-            column="48"/>
-    </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 boolean hasPermanentMenuKey(ViewConfiguration config) {"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewConfigurationCompat.java"
-            line="67"
-            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 int getScaledHoverSlop(ViewConfiguration config) {"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewConfigurationCompat.java"
-            line="127"
-            column="42"/>
-    </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 boolean shouldShowMenuShortcutsWhenKeyboardPresent(ViewConfiguration config,"
-        errorLine2="                                                                     ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewConfigurationCompat.java"
-            line="139"
-            column="70"/>
-    </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 boolean onRequestSendAccessibilityEvent(ViewGroup group, View child,"
-        errorLine2="                                                          ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewGroupCompat.java"
-            line="73"
-            column="59"/>
-    </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 boolean onRequestSendAccessibilityEvent(ViewGroup group, View child,"
-        errorLine2="                                                                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewGroupCompat.java"
-            line="73"
-            column="76"/>
-    </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="            AccessibilityEvent event) {"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewGroupCompat.java"
-            line="74"
-            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 setMotionEventSplittingEnabled(ViewGroup group, boolean split) {"
-        errorLine2="                                                      ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewGroupCompat.java"
-            line="97"
-            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="            ViewParent parent, View child, AccessibilityEvent event) {"
-        errorLine2="            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="65"
-            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="            ViewParent parent, View child, AccessibilityEvent event) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="65"
-            column="32"/>
-    </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="            ViewParent parent, View child, AccessibilityEvent event) {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="65"
-            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="    public static boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="83"
-            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 boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="83"
-            column="66"/>
-    </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 boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="83"
-            column="78"/>
-    </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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="100"
-            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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="100"
-            column="66"/>
-    </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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="100"
-            column="78"/>
-    </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 onStopNestedScroll(ViewParent parent, View target) {"
-        errorLine2="                                          ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="113"
-            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 onStopNestedScroll(ViewParent parent, View target) {"
-        errorLine2="                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="113"
-            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 void onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                      ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="130"
-            column="39"/>
-    </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 onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="130"
-            column="58"/>
-    </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 onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                      ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="158"
-            column="39"/>
-    </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 onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="158"
-            column="58"/>
-    </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 onNestedPreScroll(ViewParent parent, View target, int dx, int dy,"
-        errorLine2="                                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="176"
-            column="42"/>
-    </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 onNestedPreScroll(ViewParent parent, View target, int dx, int dy,"
-        errorLine2="                                                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="176"
-            column="61"/>
-    </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="            int[] consumed) {"
-        errorLine2="            ~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="177"
-            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 boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="205"
-            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 boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="205"
-            column="66"/>
-    </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 boolean onStartNestedScroll(ViewParent parent, View child, View target,"
-        errorLine2="                                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="205"
-            column="78"/>
-    </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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="246"
-            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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="246"
-            column="66"/>
-    </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 onNestedScrollAccepted(ViewParent parent, View child, View target,"
-        errorLine2="                                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="246"
-            column="78"/>
-    </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 onStopNestedScroll(ViewParent parent, View target, int type) {"
-        errorLine2="                                          ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="281"
-            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 onStopNestedScroll(ViewParent parent, View target, int type) {"
-        errorLine2="                                                             ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="281"
-            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 void onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                      ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="325"
-            column="39"/>
-    </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 onNestedScroll(ViewParent parent, View target, int dxConsumed,"
-        errorLine2="                                                         ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="325"
-            column="58"/>
-    </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 onNestedPreScroll(ViewParent parent, View target, int dx, int dy,"
-        errorLine2="                                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="382"
-            column="42"/>
-    </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 onNestedPreScroll(ViewParent parent, View target, int dx, int dy,"
-        errorLine2="                                                            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="382"
-            column="61"/>
-    </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="            int[] consumed, int type) {"
-        errorLine2="            ~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="383"
-            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 boolean onNestedFling(ViewParent parent, View target, float velocityX,"
-        errorLine2="                                        ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="422"
-            column="41"/>
-    </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 boolean onNestedFling(ViewParent parent, View target, float velocityX,"
-        errorLine2="                                                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="422"
-            column="60"/>
-    </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 boolean onNestedPreFling(ViewParent parent, View target, float velocityX,"
-        errorLine2="                                           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="459"
-            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="    public static boolean onNestedPreFling(ViewParent parent, View target, float velocityX,"
-        errorLine2="                                                              ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="459"
-            column="63"/>
-    </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 notifySubtreeAccessibilityStateChanged(ViewParent parent, View child,"
-        errorLine2="                                                              ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="490"
-            column="63"/>
-    </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 notifySubtreeAccessibilityStateChanged(ViewParent parent, View child,"
-        errorLine2="                                                                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="490"
-            column="82"/>
-    </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="            View source, int changeType) {"
-        errorLine2="            ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewParentCompat.java"
-            line="491"
-            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 ViewPropertyAnimatorCompat setDuration(long value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="121"
-            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 ViewPropertyAnimatorCompat alpha(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="136"
-            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 ViewPropertyAnimatorCompat alphaBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="151"
-            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 ViewPropertyAnimatorCompat translationX(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="166"
-            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 ViewPropertyAnimatorCompat translationY(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="181"
-            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 ViewPropertyAnimatorCompat withEndAction(Runnable runnable) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="214"
-            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 ViewPropertyAnimatorCompat withEndAction(Runnable runnable) {"
-        errorLine2="                                                    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="214"
-            column="53"/>
-    </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 ViewPropertyAnimatorCompat setInterpolator(Interpolator value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="252"
-            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 ViewPropertyAnimatorCompat setInterpolator(Interpolator value) {"
-        errorLine2="                                                      ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="252"
-            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 Interpolator getInterpolator() {"
-        errorLine2="           ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="265"
-            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 ViewPropertyAnimatorCompat setStartDelay(long value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="284"
-            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 ViewPropertyAnimatorCompat rotation(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="316"
-            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 ViewPropertyAnimatorCompat rotationBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="331"
-            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 ViewPropertyAnimatorCompat rotationX(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="346"
-            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 ViewPropertyAnimatorCompat rotationXBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="361"
-            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 ViewPropertyAnimatorCompat rotationY(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="376"
-            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 ViewPropertyAnimatorCompat rotationYBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="391"
-            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 ViewPropertyAnimatorCompat scaleX(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="406"
-            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 ViewPropertyAnimatorCompat scaleXBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="421"
-            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 ViewPropertyAnimatorCompat scaleY(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="436"
-            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 ViewPropertyAnimatorCompat scaleYBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="451"
-            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 ViewPropertyAnimatorCompat x(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="476"
-            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 ViewPropertyAnimatorCompat xBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="491"
-            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 ViewPropertyAnimatorCompat y(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.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 ViewPropertyAnimatorCompat yBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="521"
-            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 ViewPropertyAnimatorCompat translationXBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="536"
-            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 ViewPropertyAnimatorCompat translationYBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="551"
-            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 ViewPropertyAnimatorCompat translationZBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="568"
-            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 ViewPropertyAnimatorCompat translationZ(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="587"
-            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 ViewPropertyAnimatorCompat z(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="606"
-            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 ViewPropertyAnimatorCompat zBy(float value) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="625"
-            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 ViewPropertyAnimatorCompat withLayer() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="678"
-            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 ViewPropertyAnimatorCompat withStartAction(Runnable runnable) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="706"
-            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 ViewPropertyAnimatorCompat withStartAction(Runnable runnable) {"
-        errorLine2="                                                      ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="706"
-            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 ViewPropertyAnimatorCompat setListener(final ViewPropertyAnimatorListener listener) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="727"
-            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 ViewPropertyAnimatorCompat setListener(final ViewPropertyAnimatorListener listener) {"
-        errorLine2="                                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="727"
-            column="57"/>
-    </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 ViewPropertyAnimatorCompat setUpdateListener("
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="773"
-            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="            final ViewPropertyAnimatorUpdateListener listener) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorCompat.java"
-            line="774"
-            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="    void onAnimationStart(View view);"
-        errorLine2="                          ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListener.java"
-            line="32"
-            column="27"/>
-    </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="    void onAnimationEnd(View view);"
-        errorLine2="                        ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListener.java"
-            line="40"
-            column="25"/>
-    </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="    void onAnimationCancel(View view);"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListener.java"
-            line="48"
-            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 void onAnimationStart(View view) {"
-        errorLine2="                                 ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListenerAdapter.java"
-            line="33"
-            column="34"/>
-    </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 void onAnimationEnd(View view) {"
-        errorLine2="                               ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListenerAdapter.java"
-            line="40"
-            column="32"/>
-    </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 void onAnimationCancel(View view) {"
-        errorLine2="                                  ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorListenerAdapter.java"
-            line="47"
-            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="    void onAnimationUpdate(View view);"
-        errorLine2="                           ~~~~">
-        <location
-            file="src/main/java/androidx/core/view/ViewPropertyAnimatorUpdateListener.java"
-            line="34"
-            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="    Drawable getWrappedDrawable();"
-        errorLine2="    ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/WrappedDrawable.java"
-            line="33"
-            column="5"/>
-    </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="    void setWrappedDrawable(Drawable drawable);"
-        errorLine2="                            ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/graphics/drawable/WrappedDrawable.java"
-            line="34"
-            column="29"/>
-    </issue>
-
-</issues>
diff --git a/appsearch/appsearch-builtin-types/OWNERS b/appsearch/appsearch-builtin-types/OWNERS
new file mode 100644
index 0000000..e863f7d
--- /dev/null
+++ b/appsearch/appsearch-builtin-types/OWNERS
@@ -0,0 +1,4 @@
+ddong@google.com
+saurabhkb@google.com
+quazi@google.com
+pinyaoting@google.com
diff --git a/benchmark/benchmark-common/build.gradle b/benchmark/benchmark-common/build.gradle
index 47f2c19..cceacc9 100644
--- a/benchmark/benchmark-common/build.gradle
+++ b/benchmark/benchmark-common/build.gradle
@@ -78,3 +78,15 @@
         freeCompilerArgs += ["-Xopt-in=kotlin.Experimental"]
     }
 }
+
+// https://github.com/square/wire/issues/1947
+// Remove when we upgrade to fixed wire library
+afterEvaluate {
+    tasks.named("compileReleaseKotlin").configure {
+        it.dependsOn("generateDebugProtos")
+    }
+    tasks.named("compileDebugKotlin").configure {
+        it.dependsOn("generateReleaseProtos")
+    }
+}
+
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
index 6a11376..19cc93a 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/CompilationMode.kt
@@ -185,12 +185,9 @@
                 )
             }
         }
-        // Kill Process
+        // Kill process before compiling
         Log.d(TAG, "Killing process $packageName")
         Shell.executeCommand("am force-stop $packageName")
-        // Compile
-        compilePackage(packageName)
-        Log.d(TAG, "$packageName is compiled.")
     } else if (this is SpeedProfile) {
         repeat(this.warmupIterations) {
             block()
@@ -204,8 +201,8 @@
             Log.d(TAG, "Received dump profile response $response")
             throw RuntimeException("Failed to dump profile for $packageName ($response)")
         }
-        compilePackage(packageName)
     }
+    compilePackage(packageName)
 }
 
 /**
diff --git a/benchmark/integration-tests/macrobenchmark-target/build.gradle b/benchmark/integration-tests/macrobenchmark-target/build.gradle
index 2ef7963..20dd547 100644
--- a/benchmark/integration-tests/macrobenchmark-target/build.gradle
+++ b/benchmark/integration-tests/macrobenchmark-target/build.gradle
@@ -35,6 +35,7 @@
     implementation(libs.constraintLayout)
     implementation(project(":appcompat:appcompat"))
     implementation(project(":activity:activity"))
+    implementation(project(":profileinstaller:profileinstaller"))
     implementation(project(":recyclerview:recyclerview"))
     implementation(project(":tracing:tracing-ktx"))
     implementation(libs.material)
diff --git a/biometric/biometric/build.gradle b/biometric/biometric/build.gradle
index 3ac9baf..b655629 100644
--- a/biometric/biometric/build.gradle
+++ b/biometric/biometric/build.gradle
@@ -62,11 +62,6 @@
     testOptions.unitTests.includeAndroidResources = true
 }
 
-// Robolectric requires more memory than Gradle default
-tasks.withType(Test) { t ->
-    t.maxHeapSize = "1024m"
-}
-
 androidx {
     name = "Biometric"
     publish = Publish.SNAPSHOT_AND_RELEASE
diff --git a/buildSrc-tests/project-subsets/src/test/kotlin/androidx/build/ProjectSubsetsTest.kt b/buildSrc-tests/project-subsets/src/test/kotlin/androidx/build/ProjectSubsetsTest.kt
index 0f02efd..6530957 100644
--- a/buildSrc-tests/project-subsets/src/test/kotlin/androidx/build/ProjectSubsetsTest.kt
+++ b/buildSrc-tests/project-subsets/src/test/kotlin/androidx/build/ProjectSubsetsTest.kt
@@ -63,7 +63,9 @@
         }
         GradleRunner.create()
             .withProjectDir(projectDir)
-            .withArguments("-Pandroidx.projects=$name", "tasks")
+            // TODO(b/207407626) remove --no-configuration-cache once changing the subset works
+            // correctly
+            .withArguments("-Pandroidx.projects=$name", "tasks", "--no-configuration-cache")
             .withTestKitDir(File(outDir, ".gradle-testkit"))
             .build(); // fails the test if the build fails
     }
diff --git a/buildSrc/lint.xml b/buildSrc/lint.xml
index 12cad2a..5ec6632 100644
--- a/buildSrc/lint.xml
+++ b/buildSrc/lint.xml
@@ -1,5 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Please copy any lint rules added here to all other modules local lint.xml files -->
+<!--
+  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.
+  -->
+
+<!--
+  Please copy any lint rules added here to all other modules local lint.xml
+  files and lint_samples.xml (if applicable).
+   -->
 <lint>
     <issue id="LintBaseline" severity="ignore">
         <ignore regexp=".* filtered out because .* listed in the baseline file.*"/>
diff --git a/buildSrc/lint_samples.xml b/buildSrc/lint_samples.xml
new file mode 100644
index 0000000..8ec48c4
--- /dev/null
+++ b/buildSrc/lint_samples.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<!--
+  This configuration is applied to LibraryType.SAMPLES projects which must run
+  specific lint checks on dependencies, but don't want the full suite running.
+  -->
+<lint>
+    <issue id="LintBaseline" severity="ignore">
+        <ignore regexp=".* filtered out because .* listed in the baseline file.*"/>
+    </issue>
+    <!-- Disable all lint checks in non-sample projects. -->
+    <issue id="all">
+        <ignore regexp="^((?!samples).)*$" />
+    </issue>
+    <!-- Re-enable sampled lint checks for all projects. -->
+    <issue id="InvalidSamplesLocation" severity="fatal" />
+    <issue id="MultipleSampledFunctions" severity="fatal" />
+    <issue id="UnresolvedSampleLink" severity="fatal" />
+    <issue id="ObsoleteSampledAnnotation" severity="fatal" />
+</lint>
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
index a06cdbd..b003840 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
@@ -146,6 +146,7 @@
                     error.add("ModifierFactoryReturnType")
                     error.add("ModifierFactoryExtensionFunction")
                     error.add("ModifierParameter")
+                    error.add("MutableCollectionMutableState")
                     error.add("UnnecessaryComposedModifier")
 
                     // Paths we want to enable ListIterator checks for - for higher level
@@ -178,16 +179,13 @@
                 }
             }
 
-            // TODO(148540713): remove this exclusion when Lint can support using multiple lint jars
-            configurations.getByName("lintChecks").exclude(
-                mapOf("module" to "lint-checks")
-            )
             // TODO: figure out how to apply this to multiplatform modules
             dependencies.add(
                 "lintChecks",
                 project.dependencies.project(
                     mapOf(
                         "path" to ":compose:lint:internal-lint-checks",
+                        // TODO(b/206617878) remove this shadow configuration
                         "configuration" to "shadow"
                     )
                 )
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index e377245..f359495 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -113,6 +113,7 @@
 
         project.configureTaskTimeouts()
         project.configureMavenArtifactUpload(extension)
+        project.configureExportLibraryGroupsToXml()
         project.configureExternalDependencyLicenseCheck()
         project.configureProjectStructureValidation(extension)
         project.configureProjectVersionValidation(extension)
@@ -136,6 +137,9 @@
     private fun configureTestTask(project: Project, task: Test) {
         AffectedModuleDetector.configureTaskGuard(task)
 
+        // Robolectric 1.7 increased heap size requirements, see b/207169653.
+        task.maxHeapSize = "2g"
+
         val xmlReportDestDir = project.getHostTestResultDirectory()
         val archiveName = "${project.path.asFilenamePrefix()}_${task.name}.zip"
         if (project.isDisplayTestOutput()) {
@@ -394,6 +398,17 @@
         project.addToProjectMap(extension)
     }
 
+    private fun Project.configureExportLibraryGroupsToXml() {
+        project.tasks.register(
+            "exportLibraryGroupsToXml",
+            ExportLibraryGroupsToXmlTask::class.java
+        ) { task ->
+            task.libraryGroupFile = project.file("${project.getSupportRootFolder()}" +
+                "/buildSrc/public/src/main/kotlin/androidx/build/LibraryGroups.kt")
+            task.xmlOutputFile = project.file("${project.buildDir}/lint/library-groups.xml")
+        }
+    }
+
     private fun Project.configureProjectStructureValidation(
         extension: AndroidXExtension
     ) {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/ExportLibraryGroupsToXmlTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/ExportLibraryGroupsToXmlTask.kt
new file mode 100644
index 0000000..bb8df4a
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/ExportLibraryGroupsToXmlTask.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.build
+
+import com.google.common.io.Files
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import java.io.BufferedWriter
+import java.io.File
+import java.io.Writer
+import kotlin.reflect.full.memberProperties
+import kotlin.text.Charsets.UTF_8
+
+/**
+ * Task that parses the contents of a given library group file (usually [LibraryGroups]) and writes
+ * them to an XML file. The XML file is then used by Lint.
+ */
+@CacheableTask
+abstract class ExportLibraryGroupsToXmlTask : DefaultTask() {
+
+    @get:[InputFile PathSensitive(PathSensitivity.NONE)]
+    lateinit var libraryGroupFile: File
+
+    @get:OutputFile
+    lateinit var xmlOutputFile: File
+
+    @TaskAction
+    fun exec() {
+        val writer: Writer = BufferedWriter(Files.newWriter(xmlOutputFile, UTF_8))
+
+        // Write XML header and outermost opening tag
+        writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+        writer.write("<libraryGroups>\n")
+
+        LibraryGroups::class.memberProperties.forEach { member ->
+            try {
+                val libraryGroup = member.get(LibraryGroups) as LibraryGroup
+                val groupName = libraryGroup.group
+                val isAtomic = (libraryGroup.forcedVersion != null)
+
+                // Write data for this LibraryGroup
+                writer.run {
+                    write("    <libraryGroup>\n")
+                    write("        <group>$groupName</group>\n")
+                    write("        <isAtomic>$isAtomic</isAtomic>\n")
+                    write("    </libraryGroup>\n")
+                }
+            } catch (ignore: ClassCastException) {
+                // Object isn't a LibraryGroup, skip it
+            }
+        }
+
+        // Write outermost closing tag and close writer
+        writer.write("<libraryGroups>\n")
+        writer.close()
+    }
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
index 97cc2cb..05effe5 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -88,7 +88,6 @@
         it.enabled = false
     }
     tasks.register("lintAnalyzeDebug") {
-        it.dependsOn(lintTask)
         it.enabled = false
     }
     tasks.register("lintRelease") {
@@ -108,7 +107,6 @@
         setUpLintDebugIfNeeded()
     }
     tasks.register("lintAnalyze") {
-        it.dependsOn("lintDebug")
         it.enabled = false
     }
     configureLint(lint, extension)
@@ -303,13 +301,6 @@
             //  This is needed because SampledAnnotationDetector uses partial analysis, and
             //  hence requires dependencies to be analyzed.
             checkDependencies = true
-            // TODO: baselines from dependencies aren't used when we run lint with
-            //  isCheckDependencies = true. NewApi was recently enabled for tests, and so
-            //  there are a large amount of baselined issues that would be reported here
-            //  again, and we don't want to add them to the baseline for the sample modules.
-            //  Instead just temporarily disable this lint check until the underlying issues
-            //  are fixed.
-            disable.add("NewApi")
         }
 
         // Only run certain checks where API tracking is important.
@@ -319,9 +310,14 @@
 
         // If the project has not overridden the lint config, set the default one.
         if (lintConfig == null) {
+            val lintXmlPath = if (extension.type == LibraryType.SAMPLES) {
+                "buildSrc/lint_samples.xml"
+            } else {
+                "buildSrc/lint.xml"
+            }
             // suppress warnings more specifically than issue-wide severity (regexes)
             // Currently suppresses warnings from baseline files working as intended
-            lintConfig = File(project.getSupportRootFolder(), "buildSrc/lint.xml")
+            lintConfig = File(project.getSupportRootFolder(), lintXmlPath)
         }
 
         // Ideally, teams aren't able to add new violations to a baseline file; they should only
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
index cb6f0f2..47ac289 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
@@ -169,10 +169,13 @@
             Sync::class.java
         ) { task ->
             val sources = docsConfiguration.incoming.artifactView { }.files
+            // Store archiveOperations into a local variable to prevent access to the plugin
+            // during the task execution, as that breaks configuration caching.
+            val localVar = archiveOperations
             task.from(
                 sources.elements.map { jars ->
                     jars.map {
-                        archiveOperations.zipTree(it).matching {
+                        localVar.zipTree(it).matching {
                             // Filter out files that documentation tools cannot process.
                             it.exclude("**/*.MF")
                             it.exclude("**/*.aidl")
@@ -206,13 +209,15 @@
         docsConfiguration: Configuration
     ): TaskProvider<Sync> {
         return project.tasks.register("unzipSourcesForDackka", Sync::class.java) { task ->
-
             val sources = docsConfiguration.incoming.artifactView { }.files
 
+            // Store archiveOperations into a local variable to prevent access to the plugin
+            // during the task execution, as that breaks configuration caching.
+            val localVar = archiveOperations
             task.from(
                 sources.elements.map { jars ->
                     jars.map {
-                        archiveOperations.zipTree(it)
+                        localVar.zipTree(it)
                     }
                 }
             )
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt b/buildSrc/private/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
index 523e202..83676f6 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/uptodatedness/TaskUpToDateValidator.kt
@@ -181,19 +181,6 @@
     "validateProperties",
     "tasks",
 
-    ":benchmark:benchmark-common:generateReleaseProtos",
-    ":benchmark:benchmark-common:generateDebugProtos",
-    ":benchmark:benchmark-common:compileReleaseKotlin",
-    ":benchmark:benchmark-common:compileDebugKotlin",
-    ":benchmark:benchmark-common:compileReleaseJavaWithJavac",
-    ":benchmark:benchmark-common:compileDebugJavaWithJavac",
-    ":benchmark:benchmark-common:extractReleaseAnnotations",
-    ":benchmark:benchmark-common:extractDebugAnnotations",
-    ":benchmark:benchmark-common:generateApi",
-    ":benchmark:benchmark-common:runErrorProne",
-    ":benchmark:benchmark-common:lintAnalyzeDebug",
-    ":benchmark:benchmark-common:lintDebug",
-
     // More information about the fact that these dokka tasks rerun can be found at b/167569304
     "dokkaKotlinDocs",
     "zipDokkaDocs",
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt
index 9522e20..557195d 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -23,7 +23,7 @@
     val ACTIVITY = Version("1.5.0-alpha01")
     val ADS_IDENTIFIER = Version("1.0.0-alpha05")
     val ANNOTATION = Version("1.4.0-alpha01")
-    val ANNOTATION_EXPERIMENTAL = Version("1.2.0-beta02")
+    val ANNOTATION_EXPERIMENTAL = Version("1.2.0-rc01")
     val APPCOMPAT = Version("1.5.0-alpha01")
     val APPSEARCH = Version("1.0.0-alpha05")
     val ARCH_CORE = Version("2.2.0-alpha01")
@@ -44,12 +44,13 @@
     val CONTENTPAGER = Version("1.1.0-alpha01")
     val COMPOSE_MATERIAL3 = Version(System.getenv("COMPOSE_CUSTOM_VERSION") ?: "1.0.0-alpha02")
     val COMPOSE = Version(System.getenv("COMPOSE_CUSTOM_VERSION") ?: "1.1.0-beta04")
-    val COORDINATORLAYOUT = Version("1.2.0-beta02")
+    val COORDINATORLAYOUT = Version("1.2.0-rc01")
     val CORE = Version("1.8.0-alpha01")
     val CORE_ANIMATION = Version("1.0.0-alpha03")
     val CORE_ANIMATION_TESTING = Version("1.0.0-alpha03")
     val CORE_APPDIGEST = Version("1.0.0-alpha01")
     val CORE_GOOGLE_SHORTCUTS = Version("1.1.0-alpha02")
+    val CORE_PERFORMANCE = Version("1.0.0-alpha01")
     val CORE_REMOTEVIEWS = Version("1.0.0-alpha01")
     val CORE_ROLE = Version("1.1.0-alpha02")
     val CORE_SPLASHSCREEN = Version("1.0.0-alpha03")
@@ -104,7 +105,7 @@
     val RECYCLERVIEW_SELECTION = Version("1.2.0-alpha02")
     val REMOTECALLBACK = Version("1.0.0-alpha02")
     val RESOURCEINSPECTION = Version("1.1.0-alpha01")
-    val ROOM = Version("2.4.0-beta03")
+    val ROOM = Version("2.5.0-alpha01")
     val SAVEDSTATE = Version("1.2.0-alpha01")
     val SECURITY = Version("1.1.0-alpha04")
     val SECURITY_APP_AUTHENTICATOR = Version("1.0.0-alpha03")
@@ -118,7 +119,7 @@
     val SLICE_REMOTECALLBACK = Version("1.0.0-alpha01")
     val SLIDINGPANELAYOUT = Version("1.2.0-rc01")
     val STARTUP = Version("1.2.0-alpha01")
-    val SQLITE = Version("2.2.0-beta03")
+    val SQLITE = Version("2.3.0-alpha01")
     val SQLITE_INSPECTOR = Version("2.1.0-alpha01")
     val SWIPEREFRESHLAYOUT = Version("1.2.0-alpha01")
     val TESTSCREENSHOT = Version("1.0.0-alpha01")
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt b/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
index 8161bc3..8ba49ed 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
@@ -91,7 +91,31 @@
  * @return the root project's platform-specific NDK path as a file.
  */
 fun Project.getNdkPath(): File {
-    return File(getSdkPath(), "ndk")
+    val sdkPath = getSdkPath()
+    return getPathFromEnvironmentVariableOrNull("ANDROID_NDK_ROOT")
+        // One of the default paths when ndk is installed for the first time via sdkmanager.
+        ?: fileIfExistsOrNull(sdkPath, "ndk-bundle")
+        ?: File(sdkPath, "ndk")
+}
+
+/**
+ * @return [File] representing the path stored in [envValue] if it exists, `null` otherwise.
+ */
+private fun getPathFromEnvironmentVariableOrNull(envVar: String): File? {
+    val envValue = System.getenv(envVar)
+    if (envValue != null) {
+        val dir = File(envValue)
+        if (dir.isDirectory) {
+            return dir
+        }
+    }
+
+    return null
+}
+
+private fun fileIfExistsOrNull(parent: File, child: String): File? {
+    val file = File(parent, child)
+    return if (file.exists()) file else null
 }
 
 private fun getSdkPathFromEnvironmentVariable(): File {
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/SupportConfig.kt b/buildSrc/public/src/main/kotlin/androidx/build/SupportConfig.kt
index 931fa0a..48197b5 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/SupportConfig.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/SupportConfig.kt
@@ -27,13 +27,7 @@
     const val DEFAULT_MIN_SDK_VERSION = 14
     const val INSTRUMENTATION_RUNNER = "androidx.test.runner.AndroidJUnitRunner"
     const val BUILD_TOOLS_VERSION = "30.0.3"
-    val NDK_VERSION by lazy {
-        // TODO(aurimas) b/173737578 remove when we no longer have divergent versions
-        when (getOperatingSystem()) {
-            OperatingSystem.LINUX -> "23.0.7243079"
-            else -> "23.0.7599858"
-        }
-    }
+    const val NDK_VERSION = "23.1.7779620"
 
     /**
      * The Android SDK version to use for compilation.
diff --git a/busytown/androidx-studio-integration-lint.sh b/busytown/androidx-studio-integration-lint.sh
index a1d24aa..1ebe930 100755
--- a/busytown/androidx-studio-integration-lint.sh
+++ b/busytown/androidx-studio-integration-lint.sh
@@ -6,8 +6,7 @@
   -Pandroidx.summarizeStderr \
   -Pandroidx.verifyUpToDate \
   -x verifyDependencyVersions \
-  lint \
-  lintDebug \
-  lintReport \
+  lintAnalyze \
+  lintAnalyzeDebug \
   --no-daemon \
   --stacktrace
diff --git a/busytown/androidx.sh b/busytown/androidx.sh
index dcdefc3..5c5f28b 100755
--- a/busytown/androidx.sh
+++ b/busytown/androidx.sh
@@ -5,19 +5,24 @@
 
 cd "$(dirname $0)"
 
-# Run Gradle
 EXIT_VALUE=0
-if impl/build.sh buildOnServer checkExternalLicenses listTaskOutputs validateAllProperties \
-    -Pandroidx.enableComposeCompilerMetrics=true \
-    -Pandroidx.enableComposeCompilerReports=true \
-    --profile "$@"; then
-  EXIT_VALUE=0
-else
-  EXIT_VALUE=1
-fi
 
-# Parse performance profile reports (generated with the --profile option above) and re-export the metrics in an easily machine-readable format for tracking
-impl/parse_profile_htmls.sh
+# Validate translation exports, if present
+if ! impl/check_translations.sh; then
+  EXIT_VALUE=1
+else
+  # Run Gradle
+  if ! impl/build.sh buildOnServer checkExternalLicenses listTaskOutputs validateAllProperties \
+      -Pandroidx.enableComposeCompilerMetrics=true \
+      -Pandroidx.enableComposeCompilerReports=true \
+      --profile "$@"; then
+    EXIT_VALUE=1
+  fi
+
+  # Parse performance profile reports (generated with the --profile option above) and re-export
+  # the metrics in an easily machine-readable format for tracking
+  impl/parse_profile_htmls.sh
+fi
 
 echo "Completing $0 at $(date) with exit value $EXIT_VALUE"
 
diff --git a/busytown/impl/build.sh b/busytown/impl/build.sh
index 2efd41f..5982749 100755
--- a/busytown/impl/build.sh
+++ b/busytown/impl/build.sh
@@ -19,6 +19,10 @@
 mkdir -p "$DIST_DIR"
 export DIST_DIR="$DIST_DIR"
 
+if [ "$CHANGE_INFO" != "" ]; then
+  cp "$CHANGE_INFO" "$DIST_DIR/"
+fi
+
 # parse arguments
 if [ "$1" == "--diagnose" ]; then
   DIAGNOSE=true
@@ -60,10 +64,12 @@
 # export some variables
 ANDROID_HOME=../../prebuilts/fullsdk-linux
 
+EXIT_VALUE=0
 # run the build
 if run ./gradlew --ci saveSystemStats "$@"; then
   echo build passed
 else
+  EXIT_VALUE=1
   if [ "$DIAGNOSE" == "true" ]; then
     # see if diagnose-build-failure.sh can identify the root cauase
     echo "running diagnose-build-failure.sh, see build.log" >&2
@@ -73,7 +79,13 @@
     # more easily investigate further
     ./development/diagnose-build-failure/diagnose-build-failure.sh --timeout 600 "--ci saveSystemStats $*"
   fi
-  exit 1
+fi
+
+#export build scan information
+zip -q -r $DIST_DIR/build_scans.zip $OUT_DIR/.gradle/build-scan-data || true
+
+if [ "$EXIT_VALUE" != "0" ]; then
+  exit "$EXIT_VALUE"
 fi
 
 # check that no unexpected modifications were made to the source repository, such as new cache directories
diff --git a/busytown/impl/check_translations.sh b/busytown/impl/check_translations.sh
new file mode 100755
index 0000000..f18ec2b
--- /dev/null
+++ b/busytown/impl/check_translations.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+set -e
+
+# This script verifies the set of translatable string.xml fields against
+# those listed in the localization exports file.
+
+cd "$(dirname "$0")/../.."
+
+exports='../../vendor/google/tools/localization/exports'
+if [ ! -e "$exports" ]; then
+  echo 'Missing localization exports file, skipping verification...'
+  exit 0
+fi
+
+tempdir=$(mktemp -d "${OUT_DIR:-/tmp/}$(basename "$0").XXXXXXXXXXXX")
+trap 'rm -rf "$tempdir"' EXIT
+
+# Find string.xml files that need translation
+expect="$tempdir/expect.txt"
+find . \
+    \( \
+      -iname '*samples*' \
+      -o -iname '*debug*' \
+      -o -iname '*test*' \
+    \) \
+    -prune -o \
+    -path '*/res/values/strings.xml' \
+    -print \
+  | sed -n 's/.\///p' \
+  | sort \
+  > "$expect"
+
+# Scrape string.xml files for platform branch
+actual="$tempdir/actual.txt"
+grep 'androidx-platform-dev' "$exports" \
+  | grep -Eo '[^ ]+/strings\.xml' \
+  | sort \
+  > "$actual"
+
+# Compare and report
+diff=$(diff "${expect}" "${actual}" | { grep '<' || true; })
+if [ -n "$diff" ]; then
+  echo "Missing files in $exports:" &> 2
+  diff "$expect" "$actual" | grep strings.xml | sed -n 's/< //p' &> 2
+  echo &> 2
+  echo 'See go/androidx/playbook#translations for more information' &> 2
+  exit 1
+fi
diff --git a/camera/build.gradle b/camera/build.gradle
deleted file mode 100644
index 7797bec..0000000
--- a/camera/build.gradle
+++ /dev/null
@@ -1,6 +0,0 @@
-// b/155305020 , b/157663450 : temporarily increase test memory to see if it affects crash rate
-allprojects { pr ->
-  pr.tasks.withType(Test) { t ->
-    t.maxHeapSize = "2048m"
-  }
-}
diff --git a/camera/camera-camera2-pipe/build.gradle b/camera/camera-camera2-pipe/build.gradle
index af4e291..3cdad88 100644
--- a/camera/camera-camera2-pipe/build.gradle
+++ b/camera/camera-camera2-pipe/build.gradle
@@ -43,7 +43,7 @@
     testImplementation(libs.testRunner)
     testImplementation(libs.junit)
     testImplementation(libs.truth)
-    testImplementation(libs.robolectric)
+    testImplementation("org.robolectric:robolectric:4.6.1") // TODO(b/205731854): fix tests to work with SDK 31 and robolectric 4.7
     testImplementation(libs.kotlinCoroutinesTest)
     testImplementation(project(":camera:camera-camera2-pipe-testing"))
     testImplementation(project(":internal-testutils-truth"))
diff --git a/camera/camera-camera2/build.gradle b/camera/camera-camera2/build.gradle
index 11c1c32..386a9c0 100644
--- a/camera/camera-camera2/build.gradle
+++ b/camera/camera-camera2/build.gradle
@@ -38,7 +38,7 @@
     testImplementation(libs.testRunner)
     testImplementation(libs.junit)
     testImplementation(libs.truth)
-    testImplementation(libs.robolectric)
+    testImplementation("org.robolectric:robolectric:4.6.1") // TODO(b/205731854): fix tests to work with SDK 31 and robolectric 4.7
     testImplementation(libs.mockitoCore)
     testImplementation(libs.kotlinCoroutinesTest)
     testImplementation("androidx.annotation:annotation-experimental:1.1.0")
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
index a48140c..59cd140 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/compat/workaround/ExtraSupportedSurfaceCombinationsContainerDeviceTest.kt
@@ -20,10 +20,12 @@
 import android.graphics.ImageFormat
 import android.graphics.SurfaceTexture
 import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.CameraManager
+import android.os.Handler
+import android.os.Looper
 import android.util.Size
 import android.view.Surface
 import androidx.camera.camera2.Camera2Config
+import androidx.camera.camera2.internal.Camera2CameraFactory
 import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks
 import androidx.camera.camera2.internal.compat.quirk.ExtraSupportedSurfaceCombinationsQuirk
 import androidx.camera.camera2.interop.Camera2CameraInfo
@@ -35,6 +37,7 @@
 import androidx.camera.core.ImageProxy
 import androidx.camera.core.Preview
 import androidx.camera.core.impl.CameraInfoInternal
+import androidx.camera.core.impl.CameraThreadConfig
 import androidx.camera.core.impl.CaptureProcessor
 import androidx.camera.core.impl.ImageProxyBundle
 import androidx.camera.core.impl.SurfaceCombination
@@ -79,13 +82,17 @@
     companion object {
         @JvmStatic
         @Parameterized.Parameters(name = "cameraId = {0}")
-        fun initParameters(): List<String> = getCameraIds()
+        fun initParameters(): MutableSet<String> = getCameraIds()
 
-        private fun getCameraIds(): List<String> {
-            val cameraManager = ApplicationProvider.getApplicationContext<Context>()
-                .getSystemService(Context.CAMERA_SERVICE) as CameraManager
-
-            return cameraManager.cameraIdList.asList()
+        private fun getCameraIds(): MutableSet<String> {
+            val camera2CameraFactory = Camera2CameraFactory(
+                ApplicationProvider.getApplicationContext(),
+                CameraThreadConfig.create(
+                    CameraXExecutors.mainThreadExecutor(),
+                    Handler(Looper.getMainLooper())
+                ),
+                null)
+            return camera2CameraFactory.availableCameraIds
         }
     }
 
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
index 7d2ac60..9105f6f 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
@@ -16,7 +16,11 @@
 
 package androidx.camera.camera2.internal;
 
+import static android.hardware.camera2.CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
+
 import android.content.Context;
+import android.hardware.camera2.CameraCharacteristics;
+import android.os.Build;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -26,11 +30,13 @@
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CameraUnavailableException;
 import androidx.camera.core.InitializationException;
+import androidx.camera.core.Logger;
 import androidx.camera.core.impl.CameraFactory;
 import androidx.camera.core.impl.CameraInternal;
 import androidx.camera.core.impl.CameraStateRegistry;
 import androidx.camera.core.impl.CameraThreadConfig;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -42,6 +48,7 @@
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class Camera2CameraFactory implements CameraFactory {
+    private static final String TAG = "Camera2CameraFactory";
     private static final int DEFAULT_ALLOWED_CONCURRENT_OPEN_CAMERAS = 1;
     private final CameraThreadConfig mThreadConfig;
     private final CameraStateRegistry mCameraStateRegistry;
@@ -57,8 +64,9 @@
         mCameraStateRegistry = new CameraStateRegistry(DEFAULT_ALLOWED_CONCURRENT_OPEN_CAMERAS);
         mCameraManager = CameraManagerCompat.from(context, mThreadConfig.getSchedulerHandler());
 
-        mAvailableCameraIds = CameraSelectionOptimizer
-                .getSelectedAvailableCameraIds(this, availableCamerasSelector);
+        List<String> optimizedCameraIds = CameraSelectionOptimizer.getSelectedAvailableCameraIds(
+                this, availableCamerasSelector);
+        mAvailableCameraIds = getBackwardCompatibleCameraIds(optimizedCameraIds);
     }
 
     @Override
@@ -102,4 +110,53 @@
     public CameraManagerCompat getCameraManager() {
         return mCameraManager;
     }
+
+    private List<String> getBackwardCompatibleCameraIds(
+            @NonNull List<String> availableCameraIds) throws InitializationException {
+        List<String> backwardCompatibleCameraIds = new ArrayList<>();
+
+        for (String cameraId : availableCameraIds) {
+            // Skips camera id 0 and 1 because mostly they should be the ids of the back and
+            // front camera by default.
+            if (cameraId.equals("0") || cameraId.equals("1")) {
+                backwardCompatibleCameraIds.add(cameraId);
+                continue;
+            } else if (isBackwardCompatible(cameraId)) {
+                backwardCompatibleCameraIds.add(cameraId);
+            } else {
+                Logger.d(TAG, "Camera " + cameraId + " is filtered out because its capabilities "
+                        + "do not contain REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE.");
+            }
+        }
+
+        return backwardCompatibleCameraIds;
+    }
+
+    private boolean isBackwardCompatible(@NonNull String cameraId) throws InitializationException {
+        // Always returns true to not break robolectric tests because the cameras setup in
+        // robolectric don't have REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE capability
+        // by default.
+        if ("robolectric".equals(Build.FINGERPRINT)) {
+            return true;
+        }
+
+        int[] availableCapabilities;
+
+        try {
+            availableCapabilities = mCameraManager.getCameraCharacteristicsCompat(cameraId).get(
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+        } catch (CameraAccessExceptionCompat e) {
+            throw new InitializationException(CameraUnavailableExceptionHelper.createFrom(e));
+        }
+
+        if (availableCapabilities != null) {
+            for (int capability : availableCapabilities) {
+                if (capability == REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
index 405073f..490a9a6 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
@@ -32,7 +32,6 @@
 import androidx.camera.core.impl.UseCaseConfig;
 import androidx.core.util.Preconditions;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -186,17 +185,6 @@
             @NonNull List<UseCaseConfig<?>> newUseCaseConfigs) {
         Preconditions.checkArgument(!newUseCaseConfigs.isEmpty(), "No new use cases to be bound.");
 
-        // Use the small size (640x480) for new use cases to check whether there is any possible
-        // supported combination first
-        List<SurfaceConfig> surfaceConfigs = new ArrayList<>(existingSurfaces);
-
-        for (UseCaseConfig<?> useCaseConfig : newUseCaseConfigs) {
-            surfaceConfigs.add(
-                    transformSurfaceConfig(cameraId,
-                            useCaseConfig.getInputFormat(),
-                            new Size(640, 480)));
-        }
-
         SupportedSurfaceCombination supportedSurfaceCombination =
                 mCameraSupportedSurfaceCombinationMap.get(cameraId);
 
@@ -205,14 +193,6 @@
                     + cameraId);
         }
 
-        if (!supportedSurfaceCombination.checkSupported(surfaceConfigs)) {
-            throw new IllegalArgumentException(
-                    "No supported surface combination is found for camera device - Id : "
-                            + cameraId + ".  May be attempting to bind too many use cases. "
-                            + "Existing surfaces: " + existingSurfaces + " New configs: "
-                            + newUseCaseConfigs);
-        }
-
         return supportedSurfaceCombination.getSuggestedResolutions(existingSurfaces,
                 newUseCaseConfigs);
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
index 3ea7ebc..67803f3 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2UseCaseConfigFactory.java
@@ -25,7 +25,6 @@
 
 import android.content.Context;
 import android.hardware.camera2.CameraDevice;
-import android.hardware.display.DisplayManager;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
@@ -43,10 +42,10 @@
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class Camera2UseCaseConfigFactory implements UseCaseConfigFactory {
-    final DisplayManager mDisplayManager;
+    final DisplayInfoManager mDisplayInfoManager;
 
     public Camera2UseCaseConfigFactory(@NonNull Context context) {
-        mDisplayManager = DisplayUtil.getDisplayManager(context);
+        mDisplayInfoManager = DisplayInfoManager.getInstance(context);
     }
 
     /**
@@ -104,10 +103,10 @@
 
         if (captureType == CaptureType.PREVIEW) {
             mutableConfig.insertOption(OPTION_MAX_RESOLUTION,
-                    SupportedSurfaceCombination.getPreviewSize(mDisplayManager));
+                    mDisplayInfoManager.getPreviewSize());
         }
 
-        int targetRotation = DisplayUtil.getMaxSizeDisplay(mDisplayManager).getRotation();
+        int targetRotation = mDisplayInfoManager.getMaxSizeDisplay().getRotation();
         mutableConfig.insertOption(OPTION_TARGET_ROTATION, targetRotation);
 
         return OptionsBundle.from(mutableConfig);
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java
new file mode 100644
index 0000000..75a6bb8
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayInfoManager.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.util.Size;
+import android.view.Display;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * A singleton class to retrieve display related information.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+class DisplayInfoManager {
+    private static final Size MAX_PREVIEW_SIZE = new Size(1920, 1080);
+    private static final Object INSTANCE_LOCK = new Object();
+    private static volatile DisplayInfoManager sInstance;
+    @NonNull
+    private final DisplayManager mDisplayManager;
+    private volatile Size mPreviewSize = null;
+    private DisplayInfoManager(@NonNull Context context) {
+        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+    }
+
+    static DisplayInfoManager getInstance(Context context) {
+        if (sInstance == null) {
+            synchronized (INSTANCE_LOCK) {
+                if (sInstance == null) {
+                    sInstance = new DisplayInfoManager(context);
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    /**
+     * Test purpose only. To release the instance so that the test can create a new instance.
+     */
+    @VisibleForTesting
+    static void releaseInstance() {
+        sInstance = null;
+    }
+
+    /**
+     * Update the preview size according to current display size.
+     */
+    void refresh() {
+        mPreviewSize = calculatePreviewSize();
+    }
+
+    /**
+     * Retrieves the display which has the max size among all displays.
+     */
+    @SuppressWarnings("deprecation") /* getRealSize */
+    @NonNull
+    Display getMaxSizeDisplay() {
+        Display[] displays = mDisplayManager.getDisplays();
+        if (displays.length == 1) {
+            return displays[0];
+        }
+
+        Display maxDisplay = null;
+        int maxDisplaySize = -1;
+        for (Display display : displays) {
+            Point displaySize = new Point();
+            display.getRealSize(displaySize);
+            if (displaySize.x * displaySize.y > maxDisplaySize) {
+                maxDisplaySize = displaySize.x * displaySize.y;
+                maxDisplay = display;
+            }
+        }
+
+        if (maxDisplay == null) {
+            throw new IllegalArgumentException("No display can be found from the input display "
+                    + "manager!");
+        }
+        return maxDisplay;
+    }
+
+    /**
+     * PREVIEW refers to the best size match to the device's screen resolution, or to 1080p
+     * (1920x1080), whichever is smaller.
+     */
+    @NonNull
+    Size getPreviewSize() {
+        // Use cached value to speed up since this would be called multiple times.
+        if (mPreviewSize != null) {
+            return mPreviewSize;
+        }
+
+        mPreviewSize = calculatePreviewSize();
+        return mPreviewSize;
+    }
+
+    @SuppressWarnings("deprecation") /* getRealSize */
+    private Size calculatePreviewSize() {
+        Point displaySize = new Point();
+        Display display = getMaxSizeDisplay();
+        display.getRealSize(displaySize);
+        Size displayViewSize;
+        if (displaySize.x > displaySize.y) {
+            displayViewSize = new Size(displaySize.x, displaySize.y);
+        } else {
+            displayViewSize = new Size(displaySize.y, displaySize.x);
+        }
+
+        if (displayViewSize.getWidth() * displayViewSize.getHeight()
+                > MAX_PREVIEW_SIZE.getWidth() * MAX_PREVIEW_SIZE.getHeight()) {
+            return MAX_PREVIEW_SIZE;
+        } else {
+            return displayViewSize;
+        }
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayUtil.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayUtil.java
deleted file mode 100644
index 11f7b14..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/DisplayUtil.java
+++ /dev/null
@@ -1,67 +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.camera.camera2.internal;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-/**
- * Utility class for {@link Display} related information.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public final class DisplayUtil {
-    /**
-     * Retrieves the display which has the max size among all displays.
-     */
-    @SuppressWarnings("deprecation") /* getRealSize */
-    @NonNull
-    public static Display getMaxSizeDisplay(@NonNull DisplayManager displayManager) {
-        Display maxDisplay = null;
-        int maxDisplaySize = -1;
-
-        for (Display display : displayManager.getDisplays()) {
-            Point displaySize = new Point();
-            display.getRealSize(displaySize);
-            if (displaySize.x * displaySize.y > maxDisplaySize) {
-                maxDisplaySize = displaySize.x * displaySize.y;
-                maxDisplay = display;
-            }
-        }
-
-        if (maxDisplay == null) {
-            throw new IllegalArgumentException("No display can be found from the input display "
-                    + "manager!");
-        }
-
-        return maxDisplay;
-    }
-
-    /**
-     * Retrieves the {@link DisplayManager} instance.
-     */
-    @NonNull
-    public static DisplayManager getDisplayManager(@NonNull Context context) {
-        return (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
-    }
-
-    private DisplayUtil() {}
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
index be5dfad..e387700 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
@@ -18,11 +18,9 @@
 
 import android.content.Context;
 import android.graphics.ImageFormat;
-import android.graphics.Point;
 import android.graphics.SurfaceTexture;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.display.DisplayManager;
 import android.media.CamcorderProfile;
 import android.media.MediaRecorder;
 import android.os.Build;
@@ -53,6 +51,7 @@
 import androidx.camera.core.impl.SurfaceSizeDefinition;
 import androidx.camera.core.impl.UseCaseConfig;
 import androidx.camera.core.impl.utils.CameraOrientationUtil;
+import androidx.camera.core.impl.utils.CompareSizesByArea;
 import androidx.core.util.Preconditions;
 
 import java.util.ArrayList;
@@ -75,7 +74,6 @@
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 final class SupportedSurfaceCombination {
     private static final String TAG = "SupportedSurfaceCombination";
-    private static final Size MAX_PREVIEW_SIZE = new Size(1920, 1080);
     private static final Size DEFAULT_SIZE = new Size(640, 480);
     private static final Size ZERO_SIZE = new Size(0, 0);
     private static final Size QUALITY_1080P_SIZE = new Size(1920, 1080);
@@ -100,6 +98,8 @@
     private boolean mIsBurstCaptureSupported = false;
     private SurfaceSizeDefinition mSurfaceSizeDefinition;
     private Map<Integer, Size[]> mOutputSizesCache = new HashMap<>();
+    @NonNull
+    private final DisplayInfoManager mDisplayInfoManager;
 
     SupportedSurfaceCombination(@NonNull Context context, @NonNull String cameraId,
             @NonNull CameraManagerCompat cameraManagerCompat,
@@ -110,6 +110,7 @@
         mExcludedSupportedSizesContainer = new ExcludedSupportedSizesContainer(cameraId);
         mExtraSupportedSurfaceCombinationsContainer =
                 new ExtraSupportedSurfaceCombinationsContainer();
+        mDisplayInfoManager = DisplayInfoManager.getInstance(context);
 
         try {
             mCharacteristics = cameraManagerCompat.getCameraCharacteristicsCompat(mCameraId);
@@ -122,7 +123,7 @@
             throw CameraUnavailableExceptionHelper.createFrom(e);
         }
         generateSupportedCombinationList();
-        generateSurfaceSizeDefinition(DisplayUtil.getDisplayManager(context));
+        generateSurfaceSizeDefinition();
         checkCustomization();
     }
 
@@ -222,6 +223,25 @@
     Map<UseCaseConfig<?>, Size> getSuggestedResolutions(
             @NonNull List<SurfaceConfig> existingSurfaces,
             @NonNull List<UseCaseConfig<?>> newUseCaseConfigs) {
+       // Refresh Preview Size based on current display configurations.
+        refreshPreviewSize();
+
+        // Use the small size (640x480) for new use cases to check whether there is any possible
+        // supported combination first
+        List<SurfaceConfig> surfaceConfigs = new ArrayList<>(existingSurfaces);
+        for (UseCaseConfig<?> useCaseConfig : newUseCaseConfigs) {
+            surfaceConfigs.add(
+                    transformSurfaceConfig(useCaseConfig.getInputFormat(),
+                            new Size(640, 480)));
+        }
+
+        if (!checkSupported(surfaceConfigs)) {
+            throw new IllegalArgumentException(
+                    "No supported surface combination is found for camera device - Id : "
+                            + mCameraId + ".  May be attempting to bind too many use cases. "
+                            + "Existing surfaces: " + existingSurfaces + " New configs: "
+                            + newUseCaseConfigs);
+        }
 
         // Get the index order list by the use case priority for finding stream configuration
         List<Integer> useCasesPriorityOrder = getUseCasesPriorityOrder(newUseCaseConfigs);
@@ -322,6 +342,7 @@
         return outputRatio;
     }
 
+    @VisibleForTesting
     SurfaceSizeDefinition getSurfaceSizeDefinition() {
         return mSurfaceSizeDefinition;
     }
@@ -1189,40 +1210,25 @@
     // Utility classes and methods:
     // *********************************************************************************************
 
-    private void generateSurfaceSizeDefinition(@NonNull DisplayManager displayManager) {
+    private void generateSurfaceSizeDefinition() {
         Size analysisSize = new Size(640, 480);
-        Size previewSize = getPreviewSize(displayManager);
+        Size previewSize = mDisplayInfoManager.getPreviewSize();
         Size recordSize = getRecordSize();
         mSurfaceSizeDefinition =
                 SurfaceSizeDefinition.create(analysisSize, previewSize, recordSize);
     }
 
-    /**
-     * PREVIEW refers to the best size match to the device's screen resolution, or to 1080p
-     * (1920x1080), whichever is smaller.
-     */
-    @SuppressWarnings("deprecation") /* getRealSize */
-    @NonNull
-    static Size getPreviewSize(@NonNull DisplayManager displayManager) {
-        Point displaySize = new Point();
-        DisplayUtil.getMaxSizeDisplay(displayManager).getRealSize(displaySize);
-
-        Size displayViewSize;
-        if (displaySize.x > displaySize.y) {
-            displayViewSize = new Size(displaySize.x, displaySize.y);
+    private void refreshPreviewSize() {
+        mDisplayInfoManager.refresh();
+        if (mSurfaceSizeDefinition == null) {
+            generateSurfaceSizeDefinition();
         } else {
-            displayViewSize = new Size(displaySize.y, displaySize.x);
+            Size previewSize = mDisplayInfoManager.getPreviewSize();
+            mSurfaceSizeDefinition = SurfaceSizeDefinition.create(
+                    mSurfaceSizeDefinition.getAnalysisSize(),
+                    previewSize,
+                    mSurfaceSizeDefinition.getRecordSize());
         }
-
-        // Limit the max preview size to under min(display size, 1080P) by comparing the area size
-        Size previewSize =
-                Collections.min(
-                        Arrays.asList(
-                                new Size(displayViewSize.getWidth(), displayViewSize.getHeight()),
-                                MAX_PREVIEW_SIZE),
-                        new CompareSizesByArea());
-
-        return previewSize;
     }
 
     /**
@@ -1334,34 +1340,6 @@
         return excludedSizes;
     }
 
-    /** Comparator based on area of the given {@link Size} objects. */
-    @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-    static final class CompareSizesByArea implements Comparator<Size> {
-        private boolean mReverse = false;
-
-        CompareSizesByArea() {
-        }
-
-        CompareSizesByArea(boolean reverse) {
-            mReverse = reverse;
-        }
-
-        @Override
-        public int compare(Size lhs, Size rhs) {
-            // We cast here to ensure the multiplications won't overflow
-            int result =
-                    Long.signum(
-                            (long) lhs.getWidth() * lhs.getHeight()
-                                    - (long) rhs.getWidth() * rhs.getHeight());
-
-            if (mReverse) {
-                result *= -1;
-            }
-
-            return result;
-        }
-    }
-
     /** Comparator based on how close they are to the target aspect ratio. */
     @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     static final class CompareAspectRatiosByDistanceToTargetRatio implements Comparator<Rational> {
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2CameraFactoryTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2CameraFactoryTest.kt
new file mode 100644
index 0000000..2c6b7f2
--- /dev/null
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2CameraFactoryTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal
+
+import android.content.Context
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CameraMetadata
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.impl.CameraThreadConfig
+import androidx.camera.core.impl.utils.executor.CameraXExecutors
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadow.api.Shadow
+import org.robolectric.shadows.ShadowCameraCharacteristics
+import org.robolectric.shadows.ShadowCameraManager
+import org.robolectric.util.ReflectionHelpers
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(
+    minSdk = Build.VERSION_CODES.LOLLIPOP,
+    instrumentedPackages = ["androidx.camera.camera2.internal"]
+)
+class Camera2CameraFactoryTest {
+    @Test
+    fun filterOutIncompatibleCameras_withoutAvailableCameraSelector() {
+        // Customizes Build.FINGERPRINT to be not "fingerprint", so that cameras without
+        // REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE will be filtered.
+        ReflectionHelpers.setStaticField(Build::class.java, "FINGERPRINT", "fake-fingerprint")
+
+        setupCameras()
+
+        val camera2CameraFactory = Camera2CameraFactory(
+            ApplicationProvider.getApplicationContext(),
+            CameraThreadConfig.create(
+                CameraXExecutors.mainThreadExecutor(),
+                Handler(Looper.getMainLooper())
+            ),
+            null)
+
+        assertThat(camera2CameraFactory.availableCameraIds).containsExactly("0", "1", "2")
+    }
+
+    @Test
+    fun filterOutIncompatibleCameras_withAvailableCameraSelector() {
+        // Customizes Build.FINGERPRINT to be not "fingerprint", so that cameras without
+        // REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE will be filtered.
+        ReflectionHelpers.setStaticField(Build::class.java, "FINGERPRINT", "fake-fingerprint")
+
+        setupCameras()
+
+        val camera2CameraFactory = Camera2CameraFactory(
+            ApplicationProvider.getApplicationContext(),
+            CameraThreadConfig.create(
+                CameraXExecutors.mainThreadExecutor(),
+                Handler(Looper.getMainLooper())
+            ),
+            CameraSelector.DEFAULT_BACK_CAMERA)
+
+        assertThat(camera2CameraFactory.availableCameraIds).containsExactly("0", "2")
+    }
+
+    @Test
+    fun NotFilterOutIncompatibleCameras_whenBuildFingerprintIsRobolectric() {
+        setupCameras()
+
+        val camera2CameraFactory = Camera2CameraFactory(
+            ApplicationProvider.getApplicationContext(),
+            CameraThreadConfig.create(
+                CameraXExecutors.mainThreadExecutor(),
+                Handler(Looper.getMainLooper())
+            ),
+            null)
+
+        assertThat(camera2CameraFactory.availableCameraIds).containsExactly("0", "1", "2", "3")
+    }
+
+    private fun setupCameras() {
+        val capabilities =
+            intArrayOf(CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)
+        // Camera "0" and "1" won't be filtered out even they don't have
+        // REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE.
+        initCharacterisic("0", CameraCharacteristics.LENS_FACING_BACK, null)
+        initCharacterisic("1", CameraCharacteristics.LENS_FACING_FRONT, null)
+        initCharacterisic("2", CameraCharacteristics.LENS_FACING_BACK, capabilities)
+        // Do not set REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE for the camera, so that
+        // it will be filtered out if Build.FINGERPRINT is no "robolectric".
+        // Do not set REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE for the camera, so that
+        // it will be filtered out if Build.FINGERPRINT is no "robolectric".
+        initCharacterisic("3", CameraCharacteristics.LENS_FACING_BACK, null)
+    }
+
+    private fun initCharacterisic(cameraId: String, lensFacing: Int, capabilities: IntArray?) {
+        val characteristics = ShadowCameraCharacteristics.newCameraCharacteristics()
+        val shadowCharacteristics = Shadow.extract<ShadowCameraCharacteristics>(characteristics)
+        shadowCharacteristics.set(
+            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL,
+            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL
+        )
+
+        // Add a lens facing to the camera
+        shadowCharacteristics.set(CameraCharacteristics.LENS_FACING, lensFacing)
+
+        capabilities?.let {
+            shadowCharacteristics.set(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES,
+                capabilities
+            )
+        }
+
+        // Add the camera to the camera service
+        (Shadow.extract<Any>(
+            ApplicationProvider.getApplicationContext<Context>()
+                .getSystemService(Context.CAMERA_SERVICE)
+        ) as ShadowCameraManager)
+            .addCamera(cameraId, characteristics)
+    }
+}
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
index 0720e88..51582d9 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
@@ -138,6 +138,7 @@
     @Before
     @SuppressWarnings("deprecation")  /* defaultDisplay */
     public void setUp() throws IllegalAccessException {
+        DisplayInfoManager.releaseInstance();
         WindowManager windowManager =
                 (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         Shadows.shadowOf(windowManager.getDefaultDisplay()).setRealWidth(mDisplaySize.getWidth());
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt
new file mode 100644
index 0000000..2815d19
--- /dev/null
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/DisplayInfoManagerTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.internal
+
+import android.content.Context
+import android.graphics.Point
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.util.Size
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadows.ShadowDisplayManager
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+@Suppress("DEPRECATION") // getRealSize
+class DisplayInfoManagerTest {
+    private fun addDisplay(width: Int, height: Int) {
+        val displayStr = String.format("w%ddp-h%ddp", width, height)
+        ShadowDisplayManager.addDisplay(displayStr)
+    }
+
+    @After
+    fun tearDown() {
+        DisplayInfoManager.releaseInstance()
+    }
+
+    @Test
+    fun canReturnMaxSizeDisplay_oneDisplay() {
+        // Arrange
+        val displayManager = (ApplicationProvider.getApplicationContext() as Context)
+            .getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+        val currentDisplaySize = Point()
+        displayManager.displays.get(0).getRealSize(currentDisplaySize)
+
+        // Act
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        val size = Point()
+        displayInfoManager.maxSizeDisplay.getRealSize(size)
+
+        // Assert
+        assertThat(size).isEqualTo(currentDisplaySize)
+    }
+
+    @Test
+    fun canReturnMaxSizeDisplay_multipleDisplay() {
+        // Arrange
+        addDisplay(2000, 3000)
+        addDisplay(480, 640)
+
+        // Act
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        val size = Point()
+        displayInfoManager.maxSizeDisplay.getRealSize(size)
+
+        // Assert
+        assertThat(size).isEqualTo(Point(2000, 3000))
+    }
+
+    @Test
+    fun canReturnPreviewSize_displaySmallerThan1080P() {
+        // Arrange
+        addDisplay(480, 640)
+
+        // Act & Assert
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        assertThat(displayInfoManager.previewSize).isEqualTo(Size(640, 480))
+    }
+
+    @Test
+    fun canReturnPreviewSize_displayLargerThan1080P() {
+        // Arrange
+        addDisplay(2000, 3000)
+
+        // Act & Assert
+        val displayInfoManager = DisplayInfoManager
+            .getInstance(ApplicationProvider.getApplicationContext())
+        assertThat(displayInfoManager.previewSize).isEqualTo(Size(1920, 1080))
+    }
+
+    @Test
+    fun canReturnDifferentPreviewSize_refreshIsCalled() {
+        // Arrange
+        val displayInfoManager = spy(
+            DisplayInfoManager
+                .getInstance(ApplicationProvider.getApplicationContext())
+        )
+
+        // Act
+        displayInfoManager.previewSize
+        displayInfoManager.refresh()
+        displayInfoManager.previewSize
+
+        // Assert
+        verify(displayInfoManager, times(2)).maxSizeDisplay
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
index 3561b59..d632a57 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
@@ -61,6 +61,7 @@
 import androidx.camera.core.impl.SurfaceConfig.ConfigType;
 import androidx.camera.core.impl.UseCaseConfig;
 import androidx.camera.core.impl.UseCaseConfigFactory;
+import androidx.camera.core.impl.utils.CompareSizesByArea;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 import androidx.camera.core.internal.CameraUseCaseAdapter;
 import androidx.camera.testing.CameraUtil;
@@ -169,6 +170,7 @@
     @Before
     @SuppressWarnings("deprecation") /* defaultDisplay */
     public void setUp() throws IllegalAccessException {
+        DisplayInfoManager.releaseInstance();
         WindowManager windowManager =
                 (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         Shadows.shadowOf(windowManager.getDefaultDisplay()).setRealWidth(mDisplaySize.getWidth());
@@ -1204,7 +1206,7 @@
         }
 
         // The testing sizes array will be equal to mSupportedSizes after sorting.
-        Arrays.sort(sizes, new SupportedSurfaceCombination.CompareSizesByArea(true));
+        Arrays.sort(sizes, new CompareSizesByArea(true));
         assertThat(Arrays.asList(sizes)).isEqualTo(Arrays.asList(mSupportedSizes));
     }
 
diff --git a/camera/camera-core/build.gradle b/camera/camera-core/build.gradle
index 0d05b94..2e2f826 100644
--- a/camera/camera-core/build.gradle
+++ b/camera/camera-core/build.gradle
@@ -106,5 +106,9 @@
     description = "Core components for the Jetpack Camera Library, a library providing a " +
             "consistent and reliable camera foundation that enables great camera driven " +
             "experiences across all of Android."
-}
 
+    license {
+        name = "BSD License"
+        url = "https://chromium.googlesource.com/libyuv/libyuv/+/refs/heads/main/README.chromium"
+    }
+}
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/MetadataImageReaderTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/MetadataImageReaderTest.java
index 8a0a68f..2bd8d10 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/MetadataImageReaderTest.java
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/MetadataImageReaderTest.java
@@ -253,15 +253,11 @@
 
         final AtomicReference<ImageProxy> receivedImage = new AtomicReference<>();
 
-        ImageReaderProxy.OnImageAvailableListener outputListener =
-                new ImageReaderProxy.OnImageAvailableListener() {
-                    @Override
-                    public void onImageAvailable(@NonNull ImageReaderProxy imageReader) {
+        ImageReaderProxy.OnImageAvailableListener outputListener = imageReader -> {
                         // The First ImageProxy is output without closing.
                         ImageProxy resultImage = imageReader.acquireNextImage();
                         receivedImage.set(resultImage);
                         mSemaphore.release();
-                    }
                 };
         mMetadataImageReader.setOnImageAvailableListener(outputListener, mBackgroundExecutor);
         // Feeds the first Image.
@@ -271,25 +267,19 @@
         assertThat(receivedImage.get().getImageInfo().getTimestamp()).isEqualTo(
                 TIMESTAMP_0);
 
-        final AtomicBoolean hasReceivedSecondImage = new AtomicBoolean(false);
-        outputListener =
-                new ImageReaderProxy.OnImageAvailableListener() {
-                    @Override
-                    public void onImageAvailable(@NonNull ImageReaderProxy imageReader) {
-                        // The second ImageProxy should be dropped, otherwise fail the test case.
-                        hasReceivedSecondImage.set(true);
-                        mSemaphore.release();
-                    }
-                };
+        Semaphore secondSemaphore = new Semaphore(0);
+        outputListener = imageReader -> {
+            // The second ImageProxy should be dropped, otherwise fail the test case.
+            secondSemaphore.release();
+        };
         mMetadataImageReader.setOnImageAvailableListener(outputListener, mBackgroundExecutor);
         // Feeds the second Image.
         TagBundle tagBundle = TagBundle.create(new Pair<>("FakeCaptureStageId", 0));
-        assertThat(mImageReader.triggerImageAvailable(tagBundle, TIMESTAMP_1, 50,
-                TimeUnit.MILLISECONDS)).isFalse();
-
+        mImageReader.triggerImageAvailable(tagBundle, TIMESTAMP_1);
         HandlerUtil.waitForLooperToIdle(mBackgroundHandler);
 
-        assertThat(hasReceivedSecondImage.get()).isFalse();
+        // OnImageAvailableListener won't be called for the 2nd image.
+        assertThat(secondSemaphore.tryAcquire(1, TimeUnit.SECONDS)).isFalse();
     }
 
     @Test
diff --git a/camera/camera-core/src/main/cpp/image_processing_util_jni.cc b/camera/camera-core/src/main/cpp/image_processing_util_jni.cc
index 253ff25..a8b033e 100644
--- a/camera/camera-core/src/main/cpp/image_processing_util_jni.cc
+++ b/camera/camera-core/src/main/cpp/image_processing_util_jni.cc
@@ -357,14 +357,14 @@
         // NV21
         result = libyuv::NV12ToI420Rotate(src_y_ptr,
                                           src_stride_y,
-                                          src_u_ptr,
-                                          src_stride_u,
+                                          src_v_ptr,
+                                          src_stride_v,
                                           rotated_y_ptr,
                                           rotated_stride_y,
-                                          rotated_u_ptr,
-                                          rotated_stride_u,
                                           rotated_v_ptr,
                                           rotated_stride_v,
+                                          rotated_u_ptr,
+                                          rotated_stride_u,
                                           width,
                                           height,
                                           mode);
@@ -372,8 +372,8 @@
         // NV12
         result = libyuv::NV12ToI420Rotate(src_y_ptr,
                                           src_stride_y,
-                                          src_v_ptr,
-                                          src_stride_v,
+                                          src_u_ptr,
+                                          src_stride_u,
                                           rotated_y_ptr,
                                           rotated_stride_y,
                                           rotated_u_ptr,
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java
index 3c37a1b..325c32f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CamcorderProfileProxy.java
@@ -16,13 +16,34 @@
 
 package androidx.camera.core.impl;
 
-import android.media.CamcorderProfile;
+import static android.media.MediaRecorder.AudioEncoder.AAC;
+import static android.media.MediaRecorder.AudioEncoder.AAC_ELD;
+import static android.media.MediaRecorder.AudioEncoder.AMR_NB;
+import static android.media.MediaRecorder.AudioEncoder.AMR_WB;
+import static android.media.MediaRecorder.AudioEncoder.HE_AAC;
+import static android.media.MediaRecorder.AudioEncoder.OPUS;
+import static android.media.MediaRecorder.AudioEncoder.VORBIS;
+import static android.media.MediaRecorder.VideoEncoder.H263;
+import static android.media.MediaRecorder.VideoEncoder.H264;
+import static android.media.MediaRecorder.VideoEncoder.HEVC;
+import static android.media.MediaRecorder.VideoEncoder.MPEG_4_SP;
+import static android.media.MediaRecorder.VideoEncoder.VP8;
 
+import android.media.CamcorderProfile;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.media.MediaRecorder;
+
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.google.auto.value.AutoValue;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * CamcorderProfileProxy defines the get methods that is mapping to the fields of
  * {@link CamcorderProfile}.
@@ -31,17 +52,31 @@
 @AutoValue
 public abstract class CamcorderProfileProxy {
 
+    /** Constant representing no codec profile. */
+    public static int CODEC_PROFILE_NONE = -1;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({H263, H264, HEVC, VP8, MPEG_4_SP, MediaRecorder.VideoEncoder.DEFAULT})
+    @interface VideoEncoder {
+    }
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({AAC, AAC_ELD, AMR_NB, AMR_WB, HE_AAC, OPUS, VORBIS,
+            MediaRecorder.AudioEncoder.DEFAULT})
+    @interface AudioEncoder {
+    }
+
     /** Creates a CamcorderProfileProxy instance. */
     @NonNull
     public static CamcorderProfileProxy create(int duration,
             int quality,
             int fileFormat,
-            int videoCodec,
+            @VideoEncoder int videoCodec,
             int videoBitRate,
             int videoFrameRate,
             int videoFrameWidth,
             int videoFrameHeight,
-            int audioCodec,
+            @AudioEncoder int audioCodec,
             int audioBitRate,
             int audioSampleRate,
             int audioChannels) {
@@ -91,6 +126,7 @@
     public abstract int getFileFormat();
 
     /** @see CamcorderProfile#videoCodec */
+    @VideoEncoder
     public abstract int getVideoCodec();
 
     /** @see CamcorderProfile#videoBitRate */
@@ -106,6 +142,7 @@
     public abstract int getVideoFrameHeight();
 
     /** @see CamcorderProfile#audioCodec */
+    @AudioEncoder
     public abstract int getAudioCodec();
 
     /** @see CamcorderProfile#audioBitRate */
@@ -116,5 +153,89 @@
 
     /** @see CamcorderProfile#audioChannels */
     public abstract int getAudioChannels();
-}
 
+    /**
+     * Returns a mime-type string for the video codec type returned by {@link #getVideoCodec()}.
+     *
+     * @return A mime-type string or {@code null} if the codec type is
+     * {@link android.media.MediaRecorder.VideoEncoder#DEFAULT}, as this type is under-defined
+     * and cannot be resolved to a specific mime type without more information.
+     */
+    @Nullable
+    public String getVideoCodecMimeType() {
+        // Mime-type definitions taken from
+        // frameworks/av/media/libstagefright/foundation/MediaDefs.cpp
+        switch (getVideoCodec()) {
+            case H263:
+                return MediaFormat.MIMETYPE_VIDEO_H263;
+            case H264:
+                return MediaFormat.MIMETYPE_VIDEO_AVC;
+            case HEVC:
+                return MediaFormat.MIMETYPE_VIDEO_HEVC;
+            case VP8:
+                return MediaFormat.MIMETYPE_VIDEO_VP8;
+            case MPEG_4_SP:
+                return MediaFormat.MIMETYPE_VIDEO_MPEG4;
+            case MediaRecorder.VideoEncoder.DEFAULT:
+                break;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns a mime-type string for the audio codec type returned by {@link #getAudioCodec()}.
+     *
+     * @return A mime-type string or {@code null} if the codec type is
+     * {@link android.media.MediaRecorder.AudioEncoder#DEFAULT}, as this type is under-defined
+     * and cannot be resolved to a specific mime type without more information.
+     */
+    @Nullable
+    public String getAudioCodecMimeType() {
+        // Mime-type definitions taken from
+        // frameworks/av/media/libstagefright/foundation/MediaDefs.cpp
+        switch (getAudioCodec()) {
+            case AAC: // Should use aac-profile LC
+            case HE_AAC: // Should use aac-profile HE
+            case AAC_ELD: // Should use aac-profile ELD
+                return MediaFormat.MIMETYPE_AUDIO_AAC;
+            case AMR_NB:
+                return MediaFormat.MIMETYPE_AUDIO_AMR_NB;
+            case AMR_WB:
+                return MediaFormat.MIMETYPE_AUDIO_AMR_WB;
+            case OPUS:
+                return MediaFormat.MIMETYPE_AUDIO_OPUS;
+            case VORBIS:
+                return MediaFormat.MIMETYPE_AUDIO_VORBIS;
+            case MediaRecorder.AudioEncoder.DEFAULT:
+                break;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the required audio profile for the audio encoder given by {@link #getAudioCodec()}.
+     *
+     * <p>For example, this can be used to differentiate between AAC encoders
+     * {@link android.media.MediaRecorder.AudioEncoder#AAC},
+     * {@link android.media.MediaRecorder.AudioEncoder#AAC_ELD},
+     * and {@link android.media.MediaRecorder.AudioEncoder#HE_AAC}.
+     * Should be used with the {@link MediaCodecInfo.CodecProfileLevel#profile} field.
+     *
+     * @return The profile required by the audio codec. If no profile is required, returns
+     * {@link #CODEC_PROFILE_NONE}.
+     */
+    public int getRequiredAudioProfile() {
+        switch (getAudioCodec()) {
+            case AAC:
+                return MediaCodecInfo.CodecProfileLevel.AACObjectLC;
+            case AAC_ELD:
+                return MediaCodecInfo.CodecProfileLevel.AACObjectELD;
+            case HE_AAC:
+                return MediaCodecInfo.CodecProfileLevel.AACObjectHE;
+            default:
+                return CODEC_PROFILE_NONE;
+        }
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CompareSizesByArea.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CompareSizesByArea.java
new file mode 100644
index 0000000..a5ce6a8
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/CompareSizesByArea.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.core.impl.utils;
+
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import java.util.Comparator;
+
+/** Comparator based on area of the given {@link Size} objects. */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class CompareSizesByArea implements Comparator<Size> {
+    private boolean mReverse = false;
+
+    /** Creates a comparator with standard total ordering. */
+    public CompareSizesByArea() {
+        this(false);
+    }
+
+    /** Creates a comparator which can reverse the total ordering. */
+    public CompareSizesByArea(boolean reverse) {
+        mReverse = reverse;
+    }
+
+    @Override
+    public int compare(@NonNull Size lhs, @NonNull Size rhs) {
+        // We cast here to ensure the multiplications won't overflow
+        int result =
+                Long.signum(
+                        (long) lhs.getWidth() * lhs.getHeight()
+                                - (long) rhs.getWidth() * rhs.getHeight());
+
+        if (mReverse) {
+            result *= -1;
+        }
+
+        return result;
+    }
+}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
index 7423901..4f9bacc 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
+++ b/camera/camera-core/src/test/java/androidx/camera/core/ImageAnalysisTest.java
@@ -24,6 +24,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.SystemClock;
 import android.util.Pair;
 import android.view.Surface;
 
@@ -53,6 +54,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -256,6 +258,64 @@
                 .containsExactly(TIMESTAMP_1, TIMESTAMP_2, TIMESTAMP_3);
     }
 
+    /*
+     *  Verify that ImageAnalysis#setAnalyzer won't cause any image leakage.
+     */
+    @Test
+    public void analyzerSetMultipleTimesInKeepOnlyLatestMode() throws InterruptedException,
+            CameraUseCaseAdapter.CameraException {
+        setUpImageAnalysisWithStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST);
+
+        assertCanReceiveAnalysisImage(mImageAnalysis);
+
+        List<ImageProxy> postedImageProxies = new ArrayList<>();
+        ImageAnalysis.Analyzer slowImageAnalyzer = image -> {
+            // image left as unclosed until we closed all images in postedImageProxies.
+            postedImageProxies.add(image);
+        };
+
+        mImageAnalysis.setAnalyzer(CameraXExecutors.directExecutor(), slowImageAnalyzer);
+        triggerNextImage();  // +1 unclosed image (mPostedImage)
+        triggerNextImage();  // +1 unclosed image (mCachedImage) if the image leakage happens.
+
+        // If setAnalysis does thing inappropriately(e.g, clear mCachedImage reference without
+        // closing it), previous unclosed image(mCachedImage) won't be closed.
+        mImageAnalysis.setAnalyzer(CameraXExecutors.directExecutor(), slowImageAnalyzer);
+        triggerNextImage();  //+1 unclosed image (mCachedImage) if the image leakage happens.
+
+        mImageAnalysis.setAnalyzer(CameraXExecutors.directExecutor(), slowImageAnalyzer);
+        triggerNextImage(); // +1 unclosed image (mCachedImage) if the image leakage happens.
+
+        mImageAnalysis.setAnalyzer(CameraXExecutors.directExecutor(), slowImageAnalyzer);
+        triggerNextImage(); // +1 unclosed image (mCachedImage) if the image leakage happens.
+                                  // If unclosed image reaches 5 (MaxImages == 4), it will throw
+                                  // IllegalStateException(MaxImages) and no image can be received.
+
+        // Closed all posted ImageProxies to ensure the analyzer can receive ImageProxy normally.
+        for (ImageProxy imagePendingProxy : postedImageProxies) {
+            imagePendingProxy.close();
+        }
+
+        // If image leakage happens, 4 unclosed image will never be closed. It means the analyzer
+        // won't be able to receive images anymore.
+        assertCanReceiveAnalysisImage(mImageAnalysis);
+    }
+
+    void assertCanReceiveAnalysisImage(ImageAnalysis imageAnalysis) throws InterruptedException {
+        CountDownLatch latch = new CountDownLatch(1);
+        imageAnalysis.setAnalyzer(CameraXExecutors.directExecutor(), image -> {
+            image.close();
+            latch.countDown();
+        });
+        triggerNextImage();
+        assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
+    }
+
+    void triggerNextImage() throws InterruptedException {
+        mFakeImageReaderProxy.triggerImageAvailable(mTagBundle, SystemClock.elapsedRealtime());
+        flushHandler(mBackgroundHandler);
+    }
+
     private void setUpImageAnalysisWithStrategy(
             @ImageAnalysis.BackpressureStrategy int backpressureStrategy) throws
             CameraUseCaseAdapter.CameraException {
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
index da94576..29c6e3e 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeImageReaderProxy.java
@@ -35,7 +35,6 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
 
 /**
  * A fake implementation of ImageReaderProxy where the values are settable and the
@@ -77,7 +76,10 @@
      */
     public FakeImageReaderProxy(int maxImages) {
         mMaxImages = maxImages;
-        mImageProxyBlockingQueue = new LinkedBlockingQueue<>(maxImages);
+        // Allows more image to be produced than what can be resumed(acquired) to align with the
+        // actual ImageReader behavior. It means triggerImageAvailable can still succeed even when
+        // acquired images reaches maxImages and all are not closed.
+        mImageProxyBlockingQueue = new LinkedBlockingQueue<>(maxImages + 2);
         mImageProxyAcquisitionQueue = new LinkedBlockingQueue<>(maxImages);
     }
 
@@ -96,6 +98,7 @@
         return fakeImageReaderProxy;
     }
 
+    @Nullable
     @Override
     public ImageProxy acquireLatestImage() {
         ImageProxy imageProxy = null;
@@ -113,11 +116,12 @@
                     "Unable to acquire latest image from empty FakeImageReader");
         }
 
+        checkIfExceedMaxImages();
         mOutboundImageProxy.add(imageProxy);
-
         return imageProxy;
     }
 
+    @Nullable
     @Override
     public ImageProxy acquireNextImage() {
         ImageProxy imageProxy;
@@ -129,9 +133,18 @@
                     "Unable to acquire next image from empty FakeImageReader");
         }
 
+        checkIfExceedMaxImages();
         return imageProxy;
     }
 
+    private void checkIfExceedMaxImages() {
+        if (mImageProxyBlockingQueue.size() > mMaxImages) {
+            throw new IllegalStateException("maxImages (" + mMaxImages
+                    + ") has already been acquired, call #close before acquiring more.");
+
+        }
+    }
+
     @Override
     public void close() {
         for (ImageProxy imageProxy : mOutboundImageProxy) {
@@ -213,37 +226,6 @@
         triggerImageAvailableListener();
     }
 
-    /**
-     * Manually trigger OnImageAvailableListener to notify the Image is ready. If unable to add an
-     * {@link ImageProxy} after the timeout occurs then will return false.
-     *
-     * <p> Blocks until successfully added an ImageProxy. This can block if the maximum number of
-     * ImageProxy have been triggered without a {@link #acquireLatestImage()} or {@link
-     * #acquireNextImage()} being called.
-     *
-     * @return true if able to trigger the OnImageAvailableListener. Otherwise will return false if
-     * it fails to trigger the callback after the timeout period.
-     */
-    public boolean triggerImageAvailable(@NonNull TagBundle tagBundle, long timestamp, long timeout,
-            @NonNull TimeUnit timeUnit) throws InterruptedException {
-        FakeImageProxy fakeImageProxy = generateFakeImageProxy(tagBundle, timestamp);
-
-        final ListenableFuture<Void> future = fakeImageProxy.getCloseFuture();
-        if (mImageProxyBlockingQueue.offer(future, timeout, timeUnit)) {
-            future.addListener(() -> mImageProxyBlockingQueue.remove(future),
-                    CameraXExecutors.directExecutor()
-            );
-
-            mImageProxyAcquisitionQueue.put(fakeImageProxy);
-
-            triggerImageAvailableListener();
-
-            return true;
-        }
-
-        return false;
-    }
-
     private FakeImageProxy generateFakeImageProxy(TagBundle tagBundle, long timestamp) {
         FakeImageInfo fakeImageInfo = new FakeImageInfo();
         fakeImageInfo.setTag(tagBundle);
diff --git a/camera/camera-video/api/current.txt b/camera/camera-video/api/current.txt
index cca6186..94e5745 100644
--- a/camera/camera-video/api/current.txt
+++ b/camera/camera-video/api/current.txt
@@ -12,6 +12,13 @@
     field public static final int AUDIO_STATE_SOURCE_SILENCED = 2; // 0x2
   }
 
+  @RequiresApi(21) public class FallbackStrategy {
+    method public static androidx.camera.video.FallbackStrategy higherQualityOrLowerThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy higherQualityThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityOrHigherThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityThan(androidx.camera.video.Quality);
+  }
+
   @RequiresApi(21) public final class FileDescriptorOutputOptions extends androidx.camera.video.OutputOptions {
     method public long getFileSizeLimit();
     method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
@@ -64,29 +71,23 @@
     method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public androidx.camera.video.PendingRecording withAudioEnabled();
   }
 
-  @RequiresApi(21) public class QualitySelector {
-    method public static androidx.camera.video.QualitySelector.Procedure firstTry(int);
-    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, int);
-    method public static java.util.List<java.lang.Integer!> getSupportedQualities(androidx.camera.core.CameraInfo);
-    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, int);
-    method public static androidx.camera.video.QualitySelector of(int);
-    method public static androidx.camera.video.QualitySelector of(int, int);
-    field public static final int FALLBACK_STRATEGY_HIGHER = 1; // 0x1
-    field public static final int FALLBACK_STRATEGY_LOWER = 3; // 0x3
-    field public static final int FALLBACK_STRATEGY_STRICTLY_HIGHER = 2; // 0x2
-    field public static final int FALLBACK_STRATEGY_STRICTLY_LOWER = 4; // 0x4
-    field public static final int QUALITY_FHD = 6; // 0x6
-    field public static final int QUALITY_HD = 5; // 0x5
-    field public static final int QUALITY_HIGHEST = 1; // 0x1
-    field public static final int QUALITY_LOWEST = 0; // 0x0
-    field public static final int QUALITY_SD = 4; // 0x4
-    field public static final int QUALITY_UHD = 8; // 0x8
+  @RequiresApi(21) public class Quality {
+    field public static final androidx.camera.video.Quality FHD;
+    field public static final androidx.camera.video.Quality HD;
+    field public static final androidx.camera.video.Quality HIGHEST;
+    field public static final androidx.camera.video.Quality LOWEST;
+    field public static final androidx.camera.video.Quality SD;
+    field public static final androidx.camera.video.Quality UHD;
   }
 
-  public static class QualitySelector.Procedure {
-    method public androidx.camera.video.QualitySelector finallyTry(int);
-    method public androidx.camera.video.QualitySelector finallyTry(int, int);
-    method public androidx.camera.video.QualitySelector.Procedure thenTry(int);
+  @RequiresApi(21) public final class QualitySelector {
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality);
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality, androidx.camera.video.FallbackStrategy);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>, androidx.camera.video.FallbackStrategy);
+    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+    method public static java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.CameraInfo);
+    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
   }
 
   @RequiresApi(21) public final class Recorder implements androidx.camera.video.VideoOutput {
diff --git a/camera/camera-video/api/public_plus_experimental_current.txt b/camera/camera-video/api/public_plus_experimental_current.txt
index cca6186..94e5745 100644
--- a/camera/camera-video/api/public_plus_experimental_current.txt
+++ b/camera/camera-video/api/public_plus_experimental_current.txt
@@ -12,6 +12,13 @@
     field public static final int AUDIO_STATE_SOURCE_SILENCED = 2; // 0x2
   }
 
+  @RequiresApi(21) public class FallbackStrategy {
+    method public static androidx.camera.video.FallbackStrategy higherQualityOrLowerThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy higherQualityThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityOrHigherThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityThan(androidx.camera.video.Quality);
+  }
+
   @RequiresApi(21) public final class FileDescriptorOutputOptions extends androidx.camera.video.OutputOptions {
     method public long getFileSizeLimit();
     method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
@@ -64,29 +71,23 @@
     method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public androidx.camera.video.PendingRecording withAudioEnabled();
   }
 
-  @RequiresApi(21) public class QualitySelector {
-    method public static androidx.camera.video.QualitySelector.Procedure firstTry(int);
-    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, int);
-    method public static java.util.List<java.lang.Integer!> getSupportedQualities(androidx.camera.core.CameraInfo);
-    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, int);
-    method public static androidx.camera.video.QualitySelector of(int);
-    method public static androidx.camera.video.QualitySelector of(int, int);
-    field public static final int FALLBACK_STRATEGY_HIGHER = 1; // 0x1
-    field public static final int FALLBACK_STRATEGY_LOWER = 3; // 0x3
-    field public static final int FALLBACK_STRATEGY_STRICTLY_HIGHER = 2; // 0x2
-    field public static final int FALLBACK_STRATEGY_STRICTLY_LOWER = 4; // 0x4
-    field public static final int QUALITY_FHD = 6; // 0x6
-    field public static final int QUALITY_HD = 5; // 0x5
-    field public static final int QUALITY_HIGHEST = 1; // 0x1
-    field public static final int QUALITY_LOWEST = 0; // 0x0
-    field public static final int QUALITY_SD = 4; // 0x4
-    field public static final int QUALITY_UHD = 8; // 0x8
+  @RequiresApi(21) public class Quality {
+    field public static final androidx.camera.video.Quality FHD;
+    field public static final androidx.camera.video.Quality HD;
+    field public static final androidx.camera.video.Quality HIGHEST;
+    field public static final androidx.camera.video.Quality LOWEST;
+    field public static final androidx.camera.video.Quality SD;
+    field public static final androidx.camera.video.Quality UHD;
   }
 
-  public static class QualitySelector.Procedure {
-    method public androidx.camera.video.QualitySelector finallyTry(int);
-    method public androidx.camera.video.QualitySelector finallyTry(int, int);
-    method public androidx.camera.video.QualitySelector.Procedure thenTry(int);
+  @RequiresApi(21) public final class QualitySelector {
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality);
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality, androidx.camera.video.FallbackStrategy);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>, androidx.camera.video.FallbackStrategy);
+    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+    method public static java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.CameraInfo);
+    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
   }
 
   @RequiresApi(21) public final class Recorder implements androidx.camera.video.VideoOutput {
diff --git a/camera/camera-video/api/restricted_current.txt b/camera/camera-video/api/restricted_current.txt
index 028e269..83ddacd 100644
--- a/camera/camera-video/api/restricted_current.txt
+++ b/camera/camera-video/api/restricted_current.txt
@@ -12,6 +12,13 @@
     field public static final int AUDIO_STATE_SOURCE_SILENCED = 2; // 0x2
   }
 
+  @RequiresApi(21) public class FallbackStrategy {
+    method public static androidx.camera.video.FallbackStrategy higherQualityOrLowerThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy higherQualityThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityOrHigherThan(androidx.camera.video.Quality);
+    method public static androidx.camera.video.FallbackStrategy lowerQualityThan(androidx.camera.video.Quality);
+  }
+
   @RequiresApi(21) public final class FileDescriptorOutputOptions extends androidx.camera.video.OutputOptions {
     method public long getFileSizeLimit();
     method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
@@ -64,29 +71,23 @@
     method @RequiresPermission(android.Manifest.permission.RECORD_AUDIO) public androidx.camera.video.PendingRecording withAudioEnabled();
   }
 
-  @RequiresApi(21) public class QualitySelector {
-    method public static androidx.camera.video.QualitySelector.Procedure firstTry(int);
-    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, int);
-    method public static java.util.List<java.lang.Integer!> getSupportedQualities(androidx.camera.core.CameraInfo);
-    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, int);
-    method public static androidx.camera.video.QualitySelector of(int);
-    method public static androidx.camera.video.QualitySelector of(int, int);
-    field public static final int FALLBACK_STRATEGY_HIGHER = 1; // 0x1
-    field public static final int FALLBACK_STRATEGY_LOWER = 3; // 0x3
-    field public static final int FALLBACK_STRATEGY_STRICTLY_HIGHER = 2; // 0x2
-    field public static final int FALLBACK_STRATEGY_STRICTLY_LOWER = 4; // 0x4
-    field public static final int QUALITY_FHD = 6; // 0x6
-    field public static final int QUALITY_HD = 5; // 0x5
-    field public static final int QUALITY_HIGHEST = 1; // 0x1
-    field public static final int QUALITY_LOWEST = 0; // 0x0
-    field public static final int QUALITY_SD = 4; // 0x4
-    field public static final int QUALITY_UHD = 8; // 0x8
+  @RequiresApi(21) public class Quality {
+    field public static final androidx.camera.video.Quality FHD;
+    field public static final androidx.camera.video.Quality HD;
+    field public static final androidx.camera.video.Quality HIGHEST;
+    field public static final androidx.camera.video.Quality LOWEST;
+    field public static final androidx.camera.video.Quality SD;
+    field public static final androidx.camera.video.Quality UHD;
   }
 
-  public static class QualitySelector.Procedure {
-    method public androidx.camera.video.QualitySelector finallyTry(int);
-    method public androidx.camera.video.QualitySelector finallyTry(int, int);
-    method public androidx.camera.video.QualitySelector.Procedure thenTry(int);
+  @RequiresApi(21) public final class QualitySelector {
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality);
+    method public static androidx.camera.video.QualitySelector from(androidx.camera.video.Quality, androidx.camera.video.FallbackStrategy);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>);
+    method public static androidx.camera.video.QualitySelector fromOrderedList(java.util.List<androidx.camera.video.Quality!>, androidx.camera.video.FallbackStrategy);
+    method public static android.util.Size? getResolution(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
+    method public static java.util.List<androidx.camera.video.Quality!> getSupportedQualities(androidx.camera.core.CameraInfo);
+    method public static boolean isQualitySupported(androidx.camera.core.CameraInfo, androidx.camera.video.Quality);
   }
 
   @RequiresApi(21) public final class Recorder implements androidx.camera.video.VideoOutput {
diff --git a/camera/camera-video/build.gradle b/camera/camera-video/build.gradle
index 51f13dfd..0fe8c7c 100644
--- a/camera/camera-video/build.gradle
+++ b/camera/camera-video/build.gradle
@@ -45,6 +45,7 @@
     testImplementation(libs.truth)
     testImplementation(libs.robolectric)
     testImplementation(libs.mockitoCore)
+    testImplementation("androidx.core:core-ktx:1.1.0")
     testImplementation(project(":camera:camera-testing"), {
         exclude group: "androidx.camera", module: "camera-core"
     })
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
index 90f132f..730c55d 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/RecorderTest.kt
@@ -135,14 +135,14 @@
         val cameraInfo = cameraUseCaseAdapter.cameraInfo
         val candidates = mutableSetOf<Size>().apply {
             if (testName.methodName == "setFileSizeLimit") {
-                QualitySelector.getResolution(cameraInfo, QualitySelector.QUALITY_FHD)
+                QualitySelector.getResolution(cameraInfo, Quality.FHD)
                     ?.let { add(it) }
-                QualitySelector.getResolution(cameraInfo, QualitySelector.QUALITY_HD)
+                QualitySelector.getResolution(cameraInfo, Quality.HD)
                     ?.let { add(it) }
-                QualitySelector.getResolution(cameraInfo, QualitySelector.QUALITY_SD)
+                QualitySelector.getResolution(cameraInfo, Quality.SD)
                     ?.let { add(it) }
             }
-            QualitySelector.getResolution(cameraInfo, QualitySelector.QUALITY_LOWEST)
+            QualitySelector.getResolution(cameraInfo, Quality.LOWEST)
                 ?.let { add(it) }
         }
         assumeTrue(candidates.isNotEmpty())
@@ -946,7 +946,7 @@
 
     @Test
     fun optionsOverridesDefaults() {
-        val qualitySelector = QualitySelector.of(QualitySelector.QUALITY_HIGHEST)
+        val qualitySelector = QualitySelector.from(Quality.HIGHEST)
         val recorder = Recorder.Builder()
             .setQualitySelector(qualitySelector)
             .build()
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
index 315b698..d74c267 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoCaptureDeviceTest.kt
@@ -30,7 +30,6 @@
 import androidx.camera.testing.CameraUtil
 import androidx.camera.testing.CameraXUtil
 import androidx.camera.testing.GLUtil
-import androidx.camera.video.QualitySelector.QUALITY_LOWEST
 import androidx.camera.video.VideoOutput.StreamState
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -145,7 +144,7 @@
             val targetResolution = QualitySelector.getResolution(cameraInfo, quality)
             val videoOutput = TestVideoOutput(
                 mediaSpec = MediaSpec.builder().configureVideo {
-                    it.setQualitySelector(QualitySelector.of(quality))
+                    it.setQualitySelector(QualitySelector.from(quality))
                 }.build()
             )
             val videoCapture = VideoCapture.withOutput(videoOutput)
@@ -178,7 +177,7 @@
         // Cuttlefish API 29 has inconsistent resolution issue. See b/184015059.
         assumeFalse(Build.MODEL.contains("Cuttlefish") && Build.VERSION.SDK_INT == 29)
 
-        val targetResolution = QualitySelector.getResolution(cameraInfo, QUALITY_LOWEST)
+        val targetResolution = QualitySelector.getResolution(cameraInfo, Quality.LOWEST)
 
         arrayOf(
             Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180, Surface.ROTATION_270
@@ -186,7 +185,7 @@
             // Arrange.
             val videoOutput = TestVideoOutput(
                 mediaSpec = MediaSpec.builder().configureVideo {
-                    it.setQualitySelector(QualitySelector.of(QUALITY_LOWEST))
+                    it.setQualitySelector(QualitySelector.from(Quality.LOWEST))
                 }.build()
             )
             val videoCapture = VideoCapture.withOutput(videoOutput)
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
index 92c780f..3eec001 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/VideoRecordingTest.kt
@@ -205,7 +205,7 @@
             }
 
             val recorder = Recorder.Builder()
-                .setQualitySelector(QualitySelector.of(quality)).build()
+                .setQualitySelector(QualitySelector.from(quality)).build()
 
             val videoCapture = VideoCapture.withOutput(recorder)
 
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/AudioSourceTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/AudioSourceTest.kt
index cdb46b4..a870135 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/AudioSourceTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/AudioSourceTest.kt
@@ -68,14 +68,16 @@
         }
         fakeBufferProvider.setActive(true)
 
-        audioSource = AudioSource.Builder()
-            .setExecutor(CameraXExecutors.ioExecutor())
-            .setAudioSource(AUDIO_SOURCE)
-            .setSampleRate(SAMPLE_RATE)
-            .setChannelCount(CHANNEL_COUNT)
-            .setAudioFormat(AUDIO_FORMAT)
-            .setBufferProvider(fakeBufferProvider)
-            .build()
+        audioSource = AudioSource(
+            AudioSource.Settings.builder()
+                .setAudioSource(AUDIO_SOURCE)
+                .setSampleRate(SAMPLE_RATE)
+                .setChannelCount(CHANNEL_COUNT)
+                .setAudioFormat(AUDIO_FORMAT)
+                .build(),
+            CameraXExecutors.ioExecutor()
+        )
+        audioSource.setBufferProvider(fakeBufferProvider)
     }
 
     @After
@@ -123,4 +125,44 @@
             verify(bufferFactoryInvocations, noInvocation(3000L, 6000L)).call()
         }
     }
+
+    @Test
+    fun canResetBufferProvider_beforeStarting() {
+        // Arrange
+        val localBufferFactoryInvocations = mock(Callable::class.java)
+        val localFakeBufferProvider = FakeBufferProvider {
+            localBufferFactoryInvocations.call()
+            FakeInputBuffer()
+        }
+
+        // Act
+        audioSource.setBufferProvider(localFakeBufferProvider)
+        audioSource.start()
+        localFakeBufferProvider.setActive(true)
+
+        // Assert.
+        // It should continuously send audio data by invoking BufferProvider#acquireBuffer
+        verify(localBufferFactoryInvocations, timeout(10000L).atLeast(3)).call()
+    }
+
+    @Test
+    fun canResetBufferProvider_afterStarting() {
+        // Arrange
+        val localBufferFactoryInvocations = mock(Callable::class.java)
+        val localFakeBufferProvider = FakeBufferProvider {
+            localBufferFactoryInvocations.call()
+            FakeInputBuffer()
+        }
+        audioSource.start()
+        fakeBufferProvider.setActive(true)
+        verify(bufferFactoryInvocations, timeout(10000L).atLeast(3)).call()
+
+        // Act
+        audioSource.setBufferProvider(localFakeBufferProvider)
+        localFakeBufferProvider.setActive(true)
+
+        // Assert.
+        // It should continuously send audio data by invoking BufferProvider#acquireBuffer
+        verify(localBufferFactoryInvocations, timeout(10000L).atLeast(3)).call()
+    }
 }
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt
new file mode 100644
index 0000000..36147c4
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolverTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.content.Context
+import android.util.Range
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CameraXUtil
+import androidx.camera.video.AudioSpec
+import androidx.camera.video.Quality
+import androidx.camera.video.VideoCapabilities
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.TimeUnit
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class AudioEncoderConfigCamcorderProfileResolverTest {
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
+    private val defaultAudioSpec = AudioSpec.builder().build()
+
+    private lateinit var cameraUseCaseAdapter: CameraUseCaseAdapter
+    private lateinit var videoCapabilities: VideoCapabilities
+
+    @Before
+    fun setUp() {
+        Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
+
+        CameraXUtil.initialize(
+            context,
+            Camera2Config.defaultConfig()
+        ).get()
+
+        val cameraInfo = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
+        videoCapabilities = VideoCapabilities.from(cameraInfo)
+    }
+
+    @After
+    fun tearDown() {
+        if (this::cameraUseCaseAdapter.isInitialized) {
+            runBlocking(Dispatchers.Main) {
+                cameraUseCaseAdapter.removeUseCases(cameraUseCaseAdapter.useCases)
+            }
+        }
+
+        CameraXUtil.shutdown().get(10, TimeUnit.SECONDS)
+    }
+
+    @Test
+    fun defaultAudioSpecAndAudioSourceProducesValidSettings() {
+        val supportedProfiles = videoCapabilities.supportedQualities.map {
+            videoCapabilities.getProfile(it)!!
+        }
+
+        supportedProfiles.forEach {
+            val sourceSettings =
+                AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, it).get()
+            val config = AudioEncoderConfigCamcorderProfileResolver(
+                it.audioCodecMimeType!!,
+                it.requiredAudioProfile,
+                defaultAudioSpec,
+                sourceSettings,
+                it
+            ).get()
+
+            assertThat(config.mimeType).isEqualTo(it.audioCodecMimeType)
+            assertThat(config.bitrate).isEqualTo(it.audioBitRate)
+            assertThat(config.sampleRate).isEqualTo(it.audioSampleRate)
+            assertThat(config.channelCount).isEqualTo(it.audioChannels)
+        }
+    }
+
+    @Test
+    fun increasedChannelCountIncreasesBitrate() {
+        // Get default channel count
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val defaultSourceSettings =
+            AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+        val defaultConfig =
+            AudioEncoderConfigCamcorderProfileResolver(
+                profile.audioCodecMimeType!!,
+                profile.requiredAudioProfile,
+                defaultAudioSpec,
+                defaultSourceSettings,
+                profile
+            ).get()
+        val defaultChannelCount = defaultConfig.channelCount
+
+        val higherChannelCountSourceSettings =
+            defaultSourceSettings.toBuilder().setChannelCount(defaultChannelCount * 2).build()
+
+        val higherChannelCountConfig = AudioEncoderConfigCamcorderProfileResolver(
+            profile.audioCodecMimeType!!,
+            profile.requiredAudioProfile,
+            defaultAudioSpec,
+            higherChannelCountSourceSettings,
+            profile
+        ).get()
+
+        assertThat(higherChannelCountConfig.bitrate).isGreaterThan(defaultConfig.bitrate)
+    }
+
+    @Test
+    fun increasedSampleRateIncreasesBitrate() {
+        // Get default sample rate
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val defaultSourceSettings =
+            AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+        val defaultConfig =
+            AudioEncoderConfigCamcorderProfileResolver(
+                profile.audioCodecMimeType!!,
+                profile.requiredAudioProfile,
+                defaultAudioSpec,
+                defaultSourceSettings,
+                profile
+            ).get()
+        val defaultSampleRate = defaultConfig.sampleRate
+
+        val higherSampleRateSourceSettings =
+            defaultSourceSettings.toBuilder().setChannelCount(defaultSampleRate * 2).build()
+
+        val higherSampleRateConfig = AudioEncoderConfigCamcorderProfileResolver(
+            profile.audioCodecMimeType!!,
+            profile.requiredAudioProfile,
+            defaultAudioSpec,
+            higherSampleRateSourceSettings,
+            profile
+        ).get()
+
+        assertThat(higherSampleRateConfig.bitrate).isGreaterThan(defaultConfig.bitrate)
+    }
+
+    @Test
+    fun bitrateRangeInVideoSpecClampsBitrate() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val defaultSourceSettings =
+            AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile).get()
+
+        val defaultBitrate = profile.audioBitRate
+
+        // Create audio spec with limit 20% higher than default.
+        val higherBitrate = (defaultBitrate * 1.2).toInt()
+        val higherAudioSpec =
+            AudioSpec.builder().setBitrate(Range(higherBitrate, Int.MAX_VALUE)).build()
+
+        // Create audio spec with limit 20% lower than default.
+        val lowerBitrate = (defaultBitrate * 0.8).toInt()
+        val lowerAudioSpec = AudioSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
+
+        assertThat(
+            AudioEncoderConfigCamcorderProfileResolver(
+                profile.audioCodecMimeType!!,
+                profile.requiredAudioProfile,
+                higherAudioSpec,
+                defaultSourceSettings,
+                profile
+            ).get().bitrate
+        ).isEqualTo(higherBitrate)
+
+        assertThat(
+            AudioEncoderConfigCamcorderProfileResolver(
+                profile.audioCodecMimeType!!,
+                profile.requiredAudioProfile,
+                lowerAudioSpec,
+                defaultSourceSettings,
+                profile
+            ).get().bitrate
+        ).isEqualTo(lowerBitrate)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolverTest.kt
new file mode 100644
index 0000000..4545f43
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolverTest.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.media.MediaCodecInfo
+import android.util.Range
+import androidx.camera.video.AudioSpec
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class AudioEncoderConfigDefaultResolverTest {
+
+    companion object {
+        const val MIME_TYPE = "audio/mp4a-latm"
+        const val ENCODER_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC
+    }
+
+    private val defaultAudioSpec = AudioSpec.builder().build()
+    private val defaultAudioSourceSettings =
+        AudioSourceSettingsDefaultResolver(defaultAudioSpec).get()
+
+    @Test
+    fun defaultAudioSpecProducesValidSettings() {
+        val resolvedAudioConfig = AudioEncoderConfigDefaultResolver(
+            MIME_TYPE,
+            ENCODER_PROFILE,
+            defaultAudioSpec,
+            defaultAudioSourceSettings
+        ).get()
+
+        assertThat(resolvedAudioConfig.mimeType).isEqualTo(MIME_TYPE)
+        assertThat(resolvedAudioConfig.profile).isEqualTo(ENCODER_PROFILE)
+        assertThat(resolvedAudioConfig.channelCount)
+            .isEqualTo(defaultAudioSourceSettings.channelCount)
+        assertThat(resolvedAudioConfig.sampleRate).isEqualTo(defaultAudioSourceSettings.sampleRate)
+        assertThat(resolvedAudioConfig.bitrate).isGreaterThan(0)
+    }
+
+    @Test
+    fun increasedChannelCountIncreasesBitrate() {
+        // Get default channel count
+        val defaultConfig =
+            AudioEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                ENCODER_PROFILE,
+                defaultAudioSpec,
+                defaultAudioSourceSettings
+            ).get()
+        val defaultChannelCount = defaultConfig.channelCount
+
+        val higherChannelCountSourceSettings =
+            defaultAudioSourceSettings.toBuilder().setChannelCount(defaultChannelCount * 2).build()
+
+        val higherChannelCountConfig = AudioEncoderConfigDefaultResolver(
+            MIME_TYPE,
+            ENCODER_PROFILE,
+            defaultAudioSpec,
+            higherChannelCountSourceSettings
+        ).get()
+
+        assertThat(higherChannelCountConfig.bitrate).isGreaterThan(defaultConfig.bitrate)
+    }
+
+    @Test
+    fun increasedSampleRateIncreasesBitrate() {
+        // Get default sample rate
+        val defaultConfig =
+            AudioEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                ENCODER_PROFILE,
+                defaultAudioSpec,
+                defaultAudioSourceSettings
+            ).get()
+        val defaultSampleRate = defaultConfig.sampleRate
+
+        val higherSampleRateSourceSettings =
+            defaultAudioSourceSettings.toBuilder().setSampleRate(defaultSampleRate * 2).build()
+
+        val higherSampleRateConfig = AudioEncoderConfigDefaultResolver(
+            MIME_TYPE,
+            ENCODER_PROFILE,
+            defaultAudioSpec,
+            higherSampleRateSourceSettings
+        ).get()
+
+        assertThat(higherSampleRateConfig.bitrate).isGreaterThan(defaultConfig.bitrate)
+    }
+
+    @Test
+    fun bitrateRangeInVideoSpecClampsBitrate() {
+        val defaultConfig =
+            AudioEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                ENCODER_PROFILE,
+                defaultAudioSpec,
+                defaultAudioSourceSettings
+            ).get()
+        val defaultBitrate = defaultConfig.bitrate
+
+        // Create audio spec with limit 20% higher than default.
+        val higherBitrate = (defaultBitrate * 1.2).toInt()
+        val higherAudioSpec =
+            AudioSpec.builder().setBitrate(Range(higherBitrate, Int.MAX_VALUE)).build()
+
+        // Create audio spec with limit 20% lower than default.
+        val lowerBitrate = (defaultBitrate * 0.8).toInt()
+        val lowerAudioSpec = AudioSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
+
+        assertThat(
+            AudioEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                ENCODER_PROFILE,
+                higherAudioSpec,
+                defaultAudioSourceSettings
+            ).get().bitrate
+        ).isEqualTo(higherBitrate)
+
+        assertThat(
+            AudioEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                ENCODER_PROFILE,
+                lowerAudioSpec,
+                defaultAudioSourceSettings
+            ).get().bitrate
+        ).isEqualTo(lowerBitrate)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt
new file mode 100644
index 0000000..bb5986b
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolverTest.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.content.Context
+import android.media.AudioFormat
+import android.media.MediaRecorder
+import android.util.Range
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.testing.AudioUtil
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CameraXUtil
+import androidx.camera.video.AudioSpec
+import androidx.camera.video.Quality
+import androidx.camera.video.VideoCapabilities
+import androidx.camera.video.internal.AudioSource
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.TimeUnit
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class AudioSourceSettingsCamcorderProfileResolverTest {
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
+    private val defaultAudioSpec = AudioSpec.builder().build()
+
+    private lateinit var cameraUseCaseAdapter: CameraUseCaseAdapter
+    private lateinit var videoCapabilities: VideoCapabilities
+
+    @Before
+    fun setUp() {
+        Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
+        // Skip for b/168175357
+        Assume.assumeTrue(AudioUtil.canStartAudioRecord(MediaRecorder.AudioSource.CAMCORDER))
+
+        CameraXUtil.initialize(
+            context,
+            Camera2Config.defaultConfig()
+        ).get()
+
+        val cameraInfo = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
+        videoCapabilities = VideoCapabilities.from(cameraInfo)
+    }
+
+    @After
+    fun tearDown() {
+        if (this::cameraUseCaseAdapter.isInitialized) {
+            runBlocking(Dispatchers.Main) {
+                cameraUseCaseAdapter.removeUseCases(cameraUseCaseAdapter.useCases)
+            }
+        }
+
+        CameraXUtil.shutdown().get(10, TimeUnit.SECONDS)
+    }
+
+    @Test
+    fun defaultAudioSpecResolvesToSupportedSettings() {
+        val resolvedSettings = videoCapabilities.supportedQualities.map {
+            val camcorderProfile = videoCapabilities.getProfile(it)
+            AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, camcorderProfile!!).get()
+        }
+
+        resolvedSettings.forEach {
+            assertThat(
+                AudioSource.isSettingsSupported(
+                    it.sampleRate,
+                    it.channelCount,
+                    it.audioFormat
+                )
+            )
+        }
+    }
+
+    @Test
+    fun nonDefaultAudioSpecResolvesToSupportedSampleRate() {
+        val audioSpecs = listOf(
+            AudioSpec.builder().setSampleRate(Range(0, 1000)).build(),
+            AudioSpec.builder().setSampleRate(Range(1000, 10000)).build(),
+            AudioSpec.builder().setSampleRate(Range(10000, 100000)).build()
+        )
+
+        val resolvedSettings = videoCapabilities.supportedQualities.flatMap { quality ->
+            val camcorderProfile = videoCapabilities.getProfile(quality)
+            audioSpecs.map {
+                AudioSourceSettingsCamcorderProfileResolver(it, camcorderProfile!!).get()
+            }
+        }
+
+        resolvedSettings.forEach {
+            assertThat(
+                AudioSource.isSettingsSupported(
+                    it.sampleRate,
+                    it.channelCount,
+                    it.audioFormat
+                )
+            )
+        }
+    }
+
+    @Test
+    fun sampleRateCanOverrideCamcorderProfile_ifSupported() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+        // Get a config using the default audio spec to retrieve the source format
+        // Note: This relies on resolution of sample rate and source format being independent.
+        // If a dependency between the two is introduced, this will stop working and will
+        // need to be rewritten.
+        val autoCamcorderProfileConfig =
+            AudioSourceSettingsCamcorderProfileResolver(defaultAudioSpec, profile!!).get()
+        // Try to find a sample rate that is supported, but not the
+        // sample rate advertised by CamcorderProfile
+        val nonReportedSampleRate = AudioSource.COMMON_SAMPLE_RATES.firstOrNull {
+            it != profile.audioSampleRate && AudioSource.isSettingsSupported(
+                it,
+                profile.audioChannels,
+                autoCamcorderProfileConfig.audioFormat
+            )
+        }
+        Assume.assumeTrue(
+            "Device does not support any other common sample rates. Cannot override.",
+            nonReportedSampleRate != null
+        )
+
+        // Create an audio spec that overrides the auto sample rate behavior
+        val audioSpec =
+            AudioSpec.builder().setSampleRate(Range(nonReportedSampleRate!!, nonReportedSampleRate))
+                .build()
+        val resolvedSampleRate =
+            AudioSourceSettingsCamcorderProfileResolver(audioSpec, profile).get().sampleRate
+
+        assertThat(resolvedSampleRate).isNotEqualTo(profile.audioSampleRate)
+        assertThat(resolvedSampleRate).isEqualTo(nonReportedSampleRate)
+    }
+
+    @Test
+    fun audioSpecDefaultProducesValidSourceEnum() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+        val audioSpec = AudioSpec.builder().build()
+        val resolvedAudioSourceEnum =
+            AudioSourceSettingsCamcorderProfileResolver(
+                audioSpec,
+                profile!!
+            ).get().audioSource
+
+        assertThat(resolvedAudioSourceEnum).isAnyOf(
+            MediaRecorder.AudioSource.CAMCORDER,
+            MediaRecorder.AudioSource.MIC
+        )
+    }
+
+    @Test
+    fun audioSpecDefaultProducesValidSourceFormat() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)
+        val audioSpec = AudioSpec.builder().build()
+        val resolvedAudioSourceFormat =
+            AudioSourceSettingsCamcorderProfileResolver(
+                audioSpec,
+                profile!!
+            ).get().audioFormat
+
+        assertThat(resolvedAudioSourceFormat).isNotEqualTo(AudioFormat.ENCODING_INVALID)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolverTest.kt
new file mode 100644
index 0000000..44e96cc
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolverTest.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.media.AudioFormat
+import android.media.MediaRecorder
+import android.util.Range
+import androidx.camera.video.AudioSpec
+import androidx.camera.video.internal.AudioSource
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class AudioSourceSettingsDefaultResolverTest {
+
+    @Test
+    fun sampleRateRangeResolvesToSupportedSampleRate() {
+        val audioSpecs = listOf(
+            AudioSpec.builder().build(),
+            AudioSpec.builder().setSampleRate(Range(0, 1000)).build(),
+            AudioSpec.builder().setSampleRate(Range(1000, 10000)).build(),
+            AudioSpec.builder().setSampleRate(Range(10000, 100000)).build()
+        )
+
+        audioSpecs.forEach {
+            val audioSettings = AudioSourceSettingsDefaultResolver(it).get()
+            assertThat(
+                AudioSource.isSettingsSupported(
+                    audioSettings.sampleRate,
+                    audioSettings.channelCount,
+                    audioSettings.audioFormat
+                )
+            )
+        }
+    }
+
+    @Test
+    fun audioSpecDefaultProducesValidSourceEnum() {
+        val audioSpec = AudioSpec.builder().build()
+        val resolvedAudioSourceEnum =
+            AudioSourceSettingsDefaultResolver(audioSpec).get().audioSource
+
+        assertThat(resolvedAudioSourceEnum).isAnyOf(
+            MediaRecorder.AudioSource.CAMCORDER,
+            MediaRecorder.AudioSource.MIC
+        )
+    }
+
+    @Test
+    fun audioSpecDefaultProducesValidSourceFormat() {
+        val audioSpec = AudioSpec.builder().build()
+        val resolvedAudioSourceFormat =
+            AudioSourceSettingsDefaultResolver(audioSpec).get().audioFormat
+
+        assertThat(resolvedAudioSourceFormat).isNotEqualTo(AudioFormat.ENCODING_INVALID)
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt
new file mode 100644
index 0000000..3a71162
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolverTest.kt
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.content.Context
+import android.util.Range
+import android.util.Size
+import androidx.camera.camera2.Camera2Config
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.internal.CameraUseCaseAdapter
+import androidx.camera.testing.CameraUtil
+import androidx.camera.testing.CameraXUtil
+import androidx.camera.video.Quality
+import androidx.camera.video.VideoCapabilities
+import androidx.camera.video.VideoSpec
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.TimeUnit
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class VideoEncoderConfigCamcorderProfileResolverTest {
+
+    companion object {
+        // TODO(b/177918193): We currently cannot communicate the frame rate to the camera,
+        //  so we only support 30fps. For now we want to ensure we only ever get an FPS of 30,
+        //  but this check can be removed once we can change frame rate.
+        const val FIXED_FRAME_RATE = 30
+    }
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
+    private val defaultVideoSpec = VideoSpec.builder().build()
+
+    private lateinit var cameraUseCaseAdapter: CameraUseCaseAdapter
+    private lateinit var videoCapabilities: VideoCapabilities
+
+    @Before
+    fun setUp() {
+        Assume.assumeTrue(CameraUtil.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK))
+
+        CameraXUtil.initialize(
+            context,
+            Camera2Config.defaultConfig()
+        ).get()
+
+        val cameraInfo = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
+        videoCapabilities = VideoCapabilities.from(cameraInfo)
+    }
+
+    @After
+    fun tearDown() {
+        if (this::cameraUseCaseAdapter.isInitialized) {
+            runBlocking(Dispatchers.Main) {
+                cameraUseCaseAdapter.removeUseCases(cameraUseCaseAdapter.useCases)
+            }
+        }
+
+        CameraXUtil.shutdown().get(10, TimeUnit.SECONDS)
+    }
+
+    @Test
+    fun defaultVideoSpecProducesValidSettings_forSurfaceSizeEquivalentToQuality() {
+        val supportedProfiles = videoCapabilities.supportedQualities.map {
+            videoCapabilities.getProfile(it)!!
+        }
+
+        supportedProfiles.forEach {
+            val config = VideoEncoderConfigCamcorderProfileResolver(
+                it.videoCodecMimeType!!,
+                defaultVideoSpec,
+                Size(it.videoFrameWidth, it.videoFrameHeight),
+                it
+            ).get()
+
+            assertThat(config.mimeType).isEqualTo(it.videoCodecMimeType)
+            // TODO(b/177918193): Frame rate ratio needs to scale bitrate since we use a fixed
+            //  frame rate. The output config frame rate may not match the profile frame rate.
+            val scaledBitrate =
+                (it.videoBitRate * config.frameRate.toDouble() / it.videoFrameRate).toInt()
+            assertThat(config.bitrate).isEqualTo(scaledBitrate)
+            assertThat(config.resolution).isEqualTo(Size(it.videoFrameWidth, it.videoFrameHeight))
+            assertThat(config.frameRate).isEqualTo(FIXED_FRAME_RATE)
+        }
+    }
+
+    @Test
+    fun bitrateIncreasesOrDecreasesWithIncreaseOrDecreaseInSurfaceSize() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+
+        val defaultBitrate = VideoEncoderConfigCamcorderProfileResolver(
+            profile.videoCodecMimeType!!,
+            defaultVideoSpec,
+            surfaceSize,
+            profile
+        ).get().bitrate
+
+        val increasedSurfaceSize = Size(surfaceSize.width + 100, surfaceSize.height + 100)
+        val decreasedSurfaceSize = Size(surfaceSize.width - 100, surfaceSize.height - 100)
+
+        assertThat(
+            VideoEncoderConfigCamcorderProfileResolver(
+                profile.videoCodecMimeType!!,
+                defaultVideoSpec,
+                increasedSurfaceSize,
+                profile
+            ).get().bitrate
+        ).isGreaterThan(defaultBitrate)
+
+        assertThat(
+            VideoEncoderConfigCamcorderProfileResolver(
+                profile.videoCodecMimeType!!,
+                defaultVideoSpec,
+                decreasedSurfaceSize,
+                profile
+            ).get().bitrate
+        ).isLessThan(defaultBitrate)
+    }
+
+    @Test
+    fun bitrateRangeInVideoSpecClampsBitrate() {
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+
+        val defaultBitrate = VideoEncoderConfigCamcorderProfileResolver(
+            profile.videoCodecMimeType!!,
+            defaultVideoSpec,
+            surfaceSize,
+            profile
+        ).get().bitrate
+
+        // Create video spec with limit 20% higher than default.
+        val higherBitrate = (defaultBitrate * 1.2).toInt()
+        val higherVideoSpec =
+            VideoSpec.builder().setBitrate(Range(higherBitrate, Int.MAX_VALUE)).build()
+
+        // Create video spec with limit 20% lower than default.
+        val lowerBitrate = (defaultBitrate * 0.8).toInt()
+        val lowerVideoSpec = VideoSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
+
+        assertThat(
+            VideoEncoderConfigCamcorderProfileResolver(
+                profile.videoCodecMimeType!!,
+                higherVideoSpec,
+                surfaceSize,
+                profile
+            ).get().bitrate
+        ).isEqualTo(higherBitrate)
+
+        assertThat(
+            VideoEncoderConfigCamcorderProfileResolver(
+                profile.videoCodecMimeType!!,
+                lowerVideoSpec,
+                surfaceSize,
+                profile
+            ).get().bitrate
+        ).isEqualTo(lowerBitrate)
+    }
+
+    // TODO(b/177918193): We currently cannot communicate the frame rate to the camera,
+    //  so we only support 30fps. Ensure the encoder config always is 30 so the encoder
+    //  gets the correct frame rate.
+    //  This test can be removed once setting the frame rate is supported.
+    @Test
+    fun frameRateIsAlways30() {
+        // Give a VideoSpec with a frame rate higher than 30
+        val videoSpec = VideoSpec.builder().setFrameRate(Range(60, 60)).build()
+        val profile = videoCapabilities.getProfile(Quality.HIGHEST)!!
+        val surfaceSize = Size(profile.videoFrameWidth, profile.videoFrameHeight)
+
+        assertThat(
+            VideoEncoderConfigCamcorderProfileResolver(
+                profile.videoCodecMimeType!!,
+                videoSpec,
+                surfaceSize,
+                profile
+            ).get().frameRate
+        ).isEqualTo(
+            FIXED_FRAME_RATE
+        )
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt
new file mode 100644
index 0000000..68e0614
--- /dev/null
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolverTest.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config
+
+import android.util.Range
+import androidx.camera.testing.CamcorderProfileUtil
+import androidx.camera.video.VideoSpec
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@SdkSuppress(minSdkVersion = 21)
+class VideoEncoderConfigDefaultResolverTest {
+
+    companion object {
+        const val MIME_TYPE = "video/avc"
+
+        // TODO(b/177918193): We currently cannot communicate the frame rate to the camera,
+        //  so we only support 30fps. For now we want to ensure we only ever get an FPS of 30,
+        //  but this check can be removed once we can change frame rate.
+        const val FIXED_FRAME_RATE = 30
+    }
+
+    private val defaultVideoSpec = VideoSpec.builder().build()
+
+    @Test
+    fun defaultVideoSpecProducesValidSettings_forDifferentSurfaceSizes() {
+        val surfaceSizeCif = CamcorderProfileUtil.RESOLUTION_CIF
+        val surfaceSize720p = CamcorderProfileUtil.RESOLUTION_720P
+        val surfaceSize1080p = CamcorderProfileUtil.RESOLUTION_1080P
+
+        val configSupplierCif =
+            VideoEncoderConfigDefaultResolver(MIME_TYPE, defaultVideoSpec, surfaceSizeCif)
+        val configSupplier720p =
+            VideoEncoderConfigDefaultResolver(MIME_TYPE, defaultVideoSpec, surfaceSize720p)
+        val configSupplier1080p =
+            VideoEncoderConfigDefaultResolver(MIME_TYPE, defaultVideoSpec, surfaceSize1080p)
+
+        val configCif = configSupplierCif.get()
+        assertThat(configCif.mimeType).isEqualTo(MIME_TYPE)
+        assertThat(configCif.bitrate).isGreaterThan(0)
+        assertThat(configCif.resolution).isEqualTo(surfaceSizeCif)
+        assertThat(configCif.frameRate).isEqualTo(FIXED_FRAME_RATE)
+
+        val config720p = configSupplier720p.get()
+        assertThat(config720p.mimeType).isEqualTo(MIME_TYPE)
+        assertThat(config720p.bitrate).isGreaterThan(0)
+        assertThat(config720p.resolution).isEqualTo(surfaceSize720p)
+        assertThat(config720p.frameRate).isEqualTo(FIXED_FRAME_RATE)
+
+        val config1080p = configSupplier1080p.get()
+        assertThat(config1080p.mimeType).isEqualTo(MIME_TYPE)
+        assertThat(config1080p.bitrate).isGreaterThan(0)
+        assertThat(config1080p.resolution).isEqualTo(surfaceSize1080p)
+        assertThat(config1080p.frameRate).isEqualTo(FIXED_FRAME_RATE)
+    }
+
+    @Test
+    fun bitrateRangeInVideoSpecClampsBitrate() {
+        val surfaceSize720p = CamcorderProfileUtil.RESOLUTION_720P
+
+        // Get default bit rate for this size
+        val defaultConfig =
+            VideoEncoderConfigDefaultResolver(MIME_TYPE, defaultVideoSpec, surfaceSize720p).get()
+        val defaultBitrate = defaultConfig.bitrate
+
+        // Create video spec with limit 20% higher than default.
+        val higherBitrate = (defaultBitrate * 1.2).toInt()
+        val higherVideoSpec =
+            VideoSpec.builder().setBitrate(Range(higherBitrate, Int.MAX_VALUE)).build()
+
+        // Create video spec with limit 20% lower than default.
+        val lowerBitrate = (defaultBitrate * 0.8).toInt()
+        val lowerVideoSpec = VideoSpec.builder().setBitrate(Range(0, lowerBitrate)).build()
+
+        assertThat(
+            VideoEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                higherVideoSpec,
+                surfaceSize720p
+            ).get().bitrate
+        ).isEqualTo(higherBitrate)
+
+        assertThat(
+            VideoEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                lowerVideoSpec,
+                surfaceSize720p
+            ).get().bitrate
+        ).isEqualTo(lowerBitrate)
+    }
+
+    // TODO(b/177918193): We currently cannot communicate the frame rate to the camera,
+    //  so we only support 30fps. Ensure the encoder config always is 30 so the encoder
+    //  gets the correct frame rate.
+    //  This test can be removed once setting the frame rate is supported.
+    @Test
+    fun frameRateIsAlways30() {
+        // Give a VideoSpec with a frame rate higher than 30
+        val videoSpec = VideoSpec.builder().setBitrate(Range(60, 60)).build()
+        val size = CamcorderProfileUtil.RESOLUTION_1080P
+
+        assertThat(
+            VideoEncoderConfigDefaultResolver(
+                MIME_TYPE,
+                videoSpec,
+                size
+            ).get().frameRate
+        ).isEqualTo(
+            FIXED_FRAME_RATE
+        )
+    }
+}
\ No newline at end of file
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
index b9dfe47..e96a2fd 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
@@ -15,6 +15,7 @@
  */
 package androidx.camera.video.internal.encoder
 
+import android.media.MediaCodecInfo
 import androidx.camera.core.impl.Observable.Observer
 import androidx.camera.core.impl.utils.executor.CameraXExecutors
 import androidx.camera.video.internal.BufferProvider
@@ -58,6 +59,7 @@
 
     companion object {
         private const val MIME_TYPE = "audio/mp4a-latm"
+        private const val ENCODER_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC
         private const val BIT_RATE = 64000
         private const val SAMPLE_RATE = 44100
         private const val CHANNEL_COUNT = 1
@@ -80,6 +82,7 @@
             CameraXExecutors.ioExecutor(),
             AudioEncoderConfig.builder()
                 .setMimeType(MIME_TYPE)
+                .setProfile(ENCODER_PROFILE)
                 .setBitrate(BIT_RATE)
                 .setSampleRate(SAMPLE_RATE)
                 .setChannelCount(CHANNEL_COUNT)
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
index 696f9ea..7a7197c 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/VideoEncoderTest.kt
@@ -38,6 +38,7 @@
 import androidx.camera.testing.CameraXUtil
 import androidx.camera.testing.SurfaceTextureProvider
 import androidx.camera.testing.SurfaceTextureProvider.SurfaceTextureCallback
+import androidx.camera.video.Quality
 import androidx.camera.video.QualitySelector
 import androidx.camera.video.internal.compat.quirk.DeactivateEncoderSurfaceBeforeStopEncoderQuirk
 import androidx.camera.video.internal.compat.quirk.DeviceQuirks
@@ -319,7 +320,7 @@
 
     private fun initVideoEncoder() {
         val cameraInfo = camera.cameraInfo as CameraInfoInternal
-        val resolution = QualitySelector.getResolution(cameraInfo, QualitySelector.QUALITY_LOWEST)
+        val resolution = QualitySelector.getResolution(cameraInfo, Quality.LOWEST)
         assumeTrue(resolution != null)
 
         videoEncoderConfig = VideoEncoderConfig.builder()
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/AudioSpec.java b/camera/camera-video/src/main/java/androidx/camera/video/AudioSpec.java
index c08e2d1..560a601 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/AudioSpec.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/AudioSpec.java
@@ -43,11 +43,11 @@
     /**
      * The audio source format representing no preference for audio source format.
      */
-    static final int SOURCE_FORMAT_AUTO = -1;
+    public static final int SOURCE_FORMAT_AUTO = -1;
     /**
      * The PCM 16 bit per sample audio source format. Guaranteed to be supported by all devices.
      */
-    static final int SOURCE_FORMAT_PCM_16BIT = AudioFormat.ENCODING_PCM_16BIT;
+    public static final int SOURCE_FORMAT_PCM_16BIT = AudioFormat.ENCODING_PCM_16BIT;
 
     @IntDef({SOURCE_FORMAT_AUTO, SOURCE_FORMAT_PCM_16BIT})
     @Retention(RetentionPolicy.SOURCE)
@@ -141,7 +141,7 @@
 
     /** Gets the audio format. */
     @SourceFormat
-    abstract int getSourceFormat();
+    public abstract int getSourceFormat();
 
     /** Gets the audio source. */
     @Source
@@ -195,7 +195,7 @@
          * <p>If not set, defaults to {@link #SOURCE_FORMAT_AUTO}.
          */
         @NonNull
-        abstract Builder setSourceFormat(@SourceFormat int audioFormat);
+        public abstract Builder setSourceFormat(@SourceFormat int audioFormat);
 
         /**
          * Sets the audio source.
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/FallbackStrategy.java b/camera/camera-video/src/main/java/androidx/camera/video/FallbackStrategy.java
new file mode 100644
index 0000000..e45ba08
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/FallbackStrategy.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.google.auto.value.AutoValue;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A class represents the strategy that will be adopted when the device does not support all the
+ * desired {@link Quality} in {@link QualitySelector} in order to select the quality as possible.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class FallbackStrategy {
+
+    // Restrict access to sealed class
+    private FallbackStrategy() {
+    }
+
+    /**
+     * Returns a fallback strategy that will choose the quality that is closest to and higher
+     * than the input quality.
+     *
+     * <p>If that can not result in a supported quality, choose the quality that is closest to
+     * and lower than the input quality.
+     */
+    @NonNull
+    public static FallbackStrategy higherQualityOrLowerThan(@NonNull Quality quality) {
+        return new AutoValue_FallbackStrategy_RuleStrategy(quality,
+                FALLBACK_RULE_HIGHER_OR_LOWER);
+    }
+
+    /**
+     * Returns a fallback strategy that will choose the quality that is closest to and higher
+     * than the input quality.
+     */
+    @NonNull
+    public static FallbackStrategy higherQualityThan(@NonNull Quality quality) {
+        return new AutoValue_FallbackStrategy_RuleStrategy(quality,
+                FALLBACK_RULE_HIGHER);
+    }
+
+    /**
+     * Returns a fallback strategy that will choose the quality that is closest to and lower than
+     * the input quality.
+     *
+     * <p>If that can not result in a supported quality, choose the quality that is closest to
+     * and higher than the input quality.
+     */
+    @NonNull
+    public static FallbackStrategy lowerQualityOrHigherThan(@NonNull Quality quality) {
+        return new AutoValue_FallbackStrategy_RuleStrategy(quality,
+                FALLBACK_RULE_LOWER_OR_HIGHER);
+    }
+
+    /**
+     * Returns a fallback strategy that will choose the quality that is closest to and higher
+     * than the input quality.
+     */
+    @NonNull
+    public static FallbackStrategy lowerQualityThan(@NonNull Quality quality) {
+        return new AutoValue_FallbackStrategy_RuleStrategy(quality,
+                FALLBACK_RULE_LOWER);
+    }
+
+    static final int FALLBACK_RULE_NONE = 0;
+
+    /**
+     * Choose the quality that is closest to and higher than the desired quality. If that can not
+     * result in a supported quality, choose the quality that is closest to and lower than the
+     * desired quality.
+     */
+    static final int FALLBACK_RULE_HIGHER_OR_LOWER = 1;
+
+    /**
+     * Choose the quality that is closest to and higher than the desired quality.
+     */
+    static final int FALLBACK_RULE_HIGHER = 2;
+
+    /**
+     * Choose the quality that is closest to and lower than the desired quality. If that can not
+     * result in a supported quality, choose the quality that is closest to and higher than the
+     * desired quality.
+     */
+    static final int FALLBACK_RULE_LOWER_OR_HIGHER = 3;
+
+    /**
+     * Choose the quality that is closest to and lower than the desired quality.
+     */
+    static final int FALLBACK_RULE_LOWER = 4;
+
+    /**
+     * The fallback strategies when desired quality is not supported.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FALLBACK_RULE_NONE,
+            FALLBACK_RULE_HIGHER_OR_LOWER,
+            FALLBACK_RULE_HIGHER,
+            FALLBACK_RULE_LOWER_OR_HIGHER,
+            FALLBACK_RULE_LOWER
+    })
+    @interface FallbackRule {
+    }
+
+    /**
+     * The strategy that no fallback strategy will be applied.
+     */
+    static final FallbackStrategy NONE =
+            new AutoValue_FallbackStrategy_RuleStrategy(Quality.NONE, FALLBACK_RULE_NONE);
+
+    @AutoValue
+    abstract static class RuleStrategy extends FallbackStrategy {
+        @NonNull
+        abstract Quality getFallbackQuality();
+
+        @FallbackRule
+        abstract int getFallbackRule();
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/MediaSpec.java b/camera/camera-video/src/main/java/androidx/camera/video/MediaSpec.java
index 43228a4..aedcfc7 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/MediaSpec.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/MediaSpec.java
@@ -17,6 +17,7 @@
 package androidx.camera.video;
 
 import android.annotation.SuppressLint;
+import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import android.media.MediaMuxer;
 
@@ -25,12 +26,14 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.RestrictTo.Scope;
+import androidx.camera.video.internal.encoder.EncoderConfig;
 import androidx.core.util.Consumer;
 
 import com.google.auto.value.AutoValue;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 
 /**
  * MediaSpec communicates the encoding type and encoder-specific options for both the
@@ -42,10 +45,12 @@
 @AutoValue
 public abstract class MediaSpec {
 
-    private static final String AUDIO_FORMAT_MPEG4 = MediaFormat.MIMETYPE_AUDIO_AAC;
-    private static final String AUDIO_FORMAT_WEBM = MediaFormat.MIMETYPE_AUDIO_VORBIS;
-    private static final String VIDEO_FORMAT_MPEG4 = MediaFormat.MIMETYPE_VIDEO_AVC;
-    private static final String VIDEO_FORMAT_WEBM = MediaFormat.MIMETYPE_VIDEO_VP8;
+    private static final String AUDIO_ENCODER_MIME_MPEG4_DEFAULT = MediaFormat.MIMETYPE_AUDIO_AAC;
+    private static final String AUDIO_ENCODER_MIME_WEBM_DEFAULT = MediaFormat.MIMETYPE_AUDIO_VORBIS;
+    private static final String VIDEO_ENCODER_MIME_MPEG4_DEFAULT = MediaFormat.MIMETYPE_VIDEO_AVC;
+    private static final String VIDEO_ENCODER_MIME_WEBM_DEFAULT = MediaFormat.MIMETYPE_VIDEO_VP8;
+
+    private static final int AAC_DEFAULT_PROFILE = MediaCodecInfo.CodecProfileLevel.AACObjectLC;
 
     /** The output format representing no preference for output format. */
     public static final int OUTPUT_FORMAT_AUTO = -1;
@@ -65,27 +70,36 @@
     static String outputFormatToAudioMime(@OutputFormat int outputFormat) {
         switch (outputFormat) {
             case MediaSpec.OUTPUT_FORMAT_WEBM:
-                return AUDIO_FORMAT_WEBM;
+                return AUDIO_ENCODER_MIME_WEBM_DEFAULT;
             case MediaSpec.OUTPUT_FORMAT_MPEG_4:
                 // Fall-through
             case MediaSpec.OUTPUT_FORMAT_AUTO:
                 // Fall-through
             default:
-                return AUDIO_FORMAT_MPEG4;
+                return AUDIO_ENCODER_MIME_MPEG4_DEFAULT;
         }
     }
 
+    static int outputFormatToAudioProfile(@OutputFormat int outputFormat) {
+        String audioMime = outputFormatToAudioMime(outputFormat);
+        if (Objects.equals(audioMime, MediaFormat.MIMETYPE_AUDIO_AAC)) {
+            return AAC_DEFAULT_PROFILE;
+        }
+
+        return EncoderConfig.CODEC_PROFILE_NONE;
+    }
+
     @NonNull
     static String outputFormatToVideoMime(@OutputFormat int outputFormat) {
         switch (outputFormat) {
             case MediaSpec.OUTPUT_FORMAT_WEBM:
-                return VIDEO_FORMAT_WEBM;
+                return VIDEO_ENCODER_MIME_WEBM_DEFAULT;
             case MediaSpec.OUTPUT_FORMAT_MPEG_4:
                 // Fall-through
             case MediaSpec.OUTPUT_FORMAT_AUTO:
                 // Fall-through
             default:
-                return VIDEO_FORMAT_MPEG4;
+                return VIDEO_ENCODER_MIME_MPEG4_DEFAULT;
         }
     }
 
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/Quality.java b/camera/camera-video/src/main/java/androidx/camera/video/Quality.java
new file mode 100644
index 0000000..2275709
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/Quality.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video;
+
+import android.media.CamcorderProfile;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.google.auto.value.AutoValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A class representing video quality constraints that will be used by {@link QualitySelector} to
+ * choose video resolution and appropriate encoding parameters.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class Quality {
+
+    // Restrict access to sealed class
+    private Quality() {
+    }
+
+    /**
+     * Standard Definition (SD) 480p video quality.
+     *
+     * <p>This video quality usually corresponds to a resolution of 720 x 480 (480p) pixels.
+     */
+    public static final Quality SD = ConstantQuality.of(CamcorderProfile.QUALITY_480P, "SD");
+
+    /**
+     * High Definition (HD) video quality.
+     *
+     * <p>This video quality usually corresponds to a resolution of 1280 x 720 (720p) pixels.
+     */
+    public static final Quality HD = ConstantQuality.of(CamcorderProfile.QUALITY_720P, "HD");
+
+    /**
+     * Full High Definition (FHD) 1080p video quality.
+     *
+     * <p>This video quality usually corresponds to a resolution of 1920 x 1080 (1080p) pixels.
+     */
+    public static final Quality FHD = ConstantQuality.of(CamcorderProfile.QUALITY_1080P, "FHD");
+
+    /**
+     * Ultra High Definition (UHD) 2160p video quality.
+     *
+     * <p>This video quality usually corresponds to a resolution of 3840 x 2160 (2160p) pixels.
+     */
+    public static final Quality UHD = ConstantQuality.of(CamcorderProfile.QUALITY_2160P, "UHD");
+
+    /**
+     * The lowest video quality supported by the video frame producer.
+     */
+    public static final Quality LOWEST = ConstantQuality.of(CamcorderProfile.QUALITY_LOW, "LOWEST");
+
+    /**
+     * The highest video quality supported by the video frame producer.
+     */
+    public static final Quality HIGHEST = ConstantQuality.of(CamcorderProfile.QUALITY_HIGH,
+            "HIGHEST");
+
+    static final Quality NONE = ConstantQuality.of(-1, "NONE");
+
+    /** All quality constants. */
+    private static final Set<Quality> QUALITIES =
+            new HashSet<>(Arrays.asList(LOWEST, HIGHEST, SD, HD, FHD, UHD));
+
+    /** Quality constants with size from large to small. */
+    private static final List<Quality> QUALITIES_ORDER_BY_SIZE =
+            Arrays.asList(UHD, FHD, HD, SD);
+
+    static boolean containsQuality(@NonNull Quality quality) {
+        return QUALITIES.contains(quality);
+    }
+
+    /**
+     * Gets all video quality constants with clearly defined size sorted from largest to smallest.
+     *
+     * <p>{@link #HIGHEST} and {@link #LOWEST} are not included.
+     */
+    @NonNull
+    static List<Quality> getSortedQualities() {
+        return new ArrayList<>(QUALITIES_ORDER_BY_SIZE);
+    }
+
+    @AutoValue
+    abstract static class ConstantQuality extends Quality {
+        @NonNull
+        static ConstantQuality of(int value, @NonNull String name) {
+            return new AutoValue_Quality_ConstantQuality(value, name);
+        }
+
+        abstract int getValue();
+
+        @NonNull
+        abstract String getName();
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java b/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
index b76cd4d..08bca34 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/QualitySelector.java
@@ -16,22 +16,16 @@
 
 package androidx.camera.video;
 
-import android.media.CamcorderProfile;
 import android.util.Size;
 
-import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
-import androidx.annotation.RestrictTo;
-import androidx.annotation.RestrictTo.Scope;
 import androidx.camera.core.CameraInfo;
 import androidx.camera.core.Logger;
 import androidx.camera.core.impl.CamcorderProfileProxy;
 import androidx.core.util.Preconditions;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -45,192 +39,57 @@
  * {@link Recorder.Builder#setQualitySelector(QualitySelector) Recorder}.
  *
  * <p>There are pre-defined quality constants that are universally used for video, such as
- * {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD} and {@link #QUALITY_UHD}, but
+ * {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD} and {@link Quality#UHD}, but
  * not all of them are supported on every device since each device has its own capabilities.
- * {@link #isQualitySupported(CameraInfo, int)} can be used to check whether a quality is
- * supported on the device or not and {@link #getResolution(CameraInfo, int)} can be used to get
+ * {@link #isQualitySupported(CameraInfo, Quality)} can be used to check whether a quality is
+ * supported on the device or not and {@link #getResolution(CameraInfo, Quality)} can be used to get
  * the actual resolution defined in the device. Aside from checking the qualities one by one,
  * QualitySelector provides a more convenient way to select a quality. The typical usage of
  * selecting a single desired quality is:
  * <pre>{@code
- *   QualitySelector qualitySelector = QualitySelector.of(QualitySelector.QUALITY_FHD)
+ *   QualitySelector qualitySelector = QualitySelector.from(Quality.FHD);
  * }</pre>
- * Or the usage of selecting a series of qualities by desired order:
+ * or the usage of selecting a series of qualities by desired order:
  * <pre>{@code
- *   QualitySelector qualitySelector = QualitySelector
- *           .firstTry(QualitySelector.QUALITY_FHD)
- *           .thenTry(QualitySelector.QUALITY_HD)
- *           .finallyTry(QualitySelector.QUALITY_HIGHEST)
+ *   QualitySelector qualitySelector = QualitySelector.fromOrderedList(
+ *           Arrays.asList(Quality.FHD, Quality.HD, Quality.HIGHEST)
+ *   );
  * }</pre>
- * The recommended way to set the {@link Procedure#finallyTry(int)} is giving guaranteed supported
- * qualities such as {@link #QUALITY_LOWEST} or {@link #QUALITY_HIGHEST}, which ensures the
+ * The recommended way is giving a guaranteed supported quality such as {@link Quality#LOWEST} or
+ * {@link Quality#HIGHEST} in the end of the desired quality list, which ensures the
  * QualitySelector can always choose a supported quality. Another way to ensure a quality will be
  * selected when none of the desired qualities are supported is to use
- * {@link Procedure#finallyTry(int, int)} with an open-ended fallback strategy such as
- * {@link #FALLBACK_STRATEGY_LOWER}:
+ * {@link #fromOrderedList(List, FallbackStrategy)} with an open-ended fallback strategy such as
+ * a fallback strategy from {@link FallbackStrategy#lowerQualityOrHigherThan(Quality)}:
  * <pre>{@code
- *   QualitySelector qualitySelector = QualitySelector
- *           .firstTry(QualitySelector.QUALITY_UHD)
- *           .finallyTry(QualitySelector.QUALITY_FHD, QualitySelector.FALLBACK_STRATEGY_LOWER)
+ *   QualitySelector qualitySelector = QualitySelector.fromOrderedList(
+ *           Arrays.asList(Quality.UHD, Quality.FHD),
+ *           FallbackStrategy.lowerQualityOrHigherThan(Quality.FHD)
+ *   );
  * }</pre>
- * If QUALITY_UHD and QUALITY_FHD are not supported on the device, QualitySelector will select
- * the quality that is closest to and lower than QUALITY_FHD. If no lower quality is supported,
- * the quality that is closest to and higher than QUALITY_FHD will be selected.
+ * If UHD and FHD are not supported on the device, QualitySelector will select the quality that
+ * is closest to and lower than FHD. If no lower quality is supported, the quality that is
+ * closest to and higher than FHD will be selected.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public class QualitySelector {
+public final class QualitySelector {
     private static final String TAG = "QualitySelector";
 
     /**
-     * A non-applicable quality.
-     *
-     * <p>Checking QUALITY_NONE via {@link #isQualitySupported(CameraInfo, int)} will return
-     * {@code false}.
-     *
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    public static final int QUALITY_NONE = -1;
-    /**
-     * The lowest video quality supported by the video frame producer.
-     */
-    public static final int QUALITY_LOWEST = CamcorderProfile.QUALITY_LOW;
-    /**
-     * The highest video quality supported by the video frame producer.
-     */
-    public static final int QUALITY_HIGHEST = CamcorderProfile.QUALITY_HIGH;
-    /**
-     * Standard Definition (SD) 480p video quality.
-     *
-     * <p>This video quality usually corresponds to a resolution of 720 x 480 (480p) pixels.
-     */
-    public static final int QUALITY_SD = CamcorderProfile.QUALITY_480P;
-    /**
-     * High Definition (HD) video quality.
-     *
-     * <p>This video quality usually corresponds to a resolution of 1280 x 720 (720p) pixels.
-     */
-    public static final int QUALITY_HD = CamcorderProfile.QUALITY_720P;
-    /**
-     * Full High Definition (FHD) 1080p video quality.
-     *
-     * <p>This video quality usually corresponds to a resolution of 1920 x 1080 (1080p) pixels.
-     */
-    public static final int QUALITY_FHD = CamcorderProfile.QUALITY_1080P;
-    /**
-     * Ultra High Definition (UHD) 2160p video quality.
-     *
-     * <p>This video quality usually corresponds to a resolution of 3840 x 2160 (2160p) pixels.
-     */
-    public static final int QUALITY_UHD = CamcorderProfile.QUALITY_2160P;
-
-    /** @hide */
-    @IntDef({QUALITY_NONE, QUALITY_LOWEST, QUALITY_HIGHEST, QUALITY_SD, QUALITY_HD, QUALITY_FHD,
-            QUALITY_UHD})
-    @Retention(RetentionPolicy.SOURCE)
-    @RestrictTo(Scope.LIBRARY)
-    public @interface VideoQuality {
-    }
-
-    /** All quality constants. */
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    static final List<Integer> QUALITIES = Arrays.asList(QUALITY_NONE, QUALITY_LOWEST,
-            QUALITY_HIGHEST, QUALITY_SD, QUALITY_HD, QUALITY_FHD, QUALITY_UHD);
-
-    /** Quality constants with size from large to small. */
-    private static final List<Integer> QUALITIES_ORDER_BY_SIZE = Arrays.asList(QUALITY_UHD,
-            QUALITY_FHD, QUALITY_HD, QUALITY_SD);
-
-    /**
-     * The strategy that no fallback strategy will be applied.
-     *
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    public static final int FALLBACK_STRATEGY_NONE = 0;
-
-    /**
-     * Choose the quality that is closest to and higher than the desired quality. If that can not
-     * result in a supported quality, choose the quality that is closest to and lower than the
-     * desired quality.
-     */
-    public static final int FALLBACK_STRATEGY_HIGHER = 1;
-
-    /**
-     * Choose the quality that is closest to and higher than the desired quality.
-     */
-    public static final int FALLBACK_STRATEGY_STRICTLY_HIGHER = 2;
-
-    /**
-     * Choose the quality that is closest to and lower than the desired quality. If that can not
-     * result in a supported quality, choose the quality that is closest to and higher than the
-     * desired quality.
-     */
-    public static final int FALLBACK_STRATEGY_LOWER = 3;
-
-    /**
-     * Choose the quality that is closest to and lower than the desired quality.
-     */
-    public static final int FALLBACK_STRATEGY_STRICTLY_LOWER = 4;
-
-    private static final int FALLBACK_STRATEGY_START = FALLBACK_STRATEGY_NONE;
-    private static final int FALLBACK_STRATEGY_END = FALLBACK_STRATEGY_STRICTLY_LOWER;
-
-    /**
-     * The fallback strategies when desired quality is not supported.
-     *
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({FALLBACK_STRATEGY_NONE,
-            FALLBACK_STRATEGY_HIGHER,
-            FALLBACK_STRATEGY_STRICTLY_HIGHER,
-            FALLBACK_STRATEGY_LOWER,
-            FALLBACK_STRATEGY_STRICTLY_LOWER
-    })
-    public @interface FallbackStrategy {
-    }
-
-    /**
-     * Checks if the input quality is one of video quality constants.
-     *
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    public static boolean containsQuality(int quality) {
-        return QUALITIES.contains(quality);
-    }
-
-    /**
-     * Gets all video quality constants with clearly defined size sorted from largest to smallest.
-     *
-     * <p>{@link #QUALITY_NONE}, {@link #QUALITY_HIGHEST} and {@link #QUALITY_LOWEST} are not
-     * included.
-     *
-     * @hide
-     */
-    @RestrictTo(Scope.LIBRARY)
-    @NonNull
-    public static List<Integer> getSortedQualities() {
-        return new ArrayList<>(QUALITIES_ORDER_BY_SIZE);
-    }
-
-    /**
      * Gets all supported qualities on the device.
      *
      * <p>The returned list is sorted by quality size from largest to smallest. For the qualities in
      * the returned list, with the same input cameraInfo,
-     * {@link #isQualitySupported(CameraInfo, int)} will return {@code true} and
-     * {@link #getResolution(CameraInfo, int)} will return the corresponding resolution.
+     * {@link #isQualitySupported(CameraInfo, Quality)} will return {@code true} and
+     * {@link #getResolution(CameraInfo, Quality)} will return the corresponding resolution.
      *
-     * <p>Note: Constants {@link #QUALITY_HIGHEST} and {@link #QUALITY_LOWEST} are not included
+     * <p>Note: Constants {@link Quality#HIGHEST} and {@link Quality#LOWEST} are not included
      * in the returned list, but their corresponding qualities are included.
      *
      * @param cameraInfo the cameraInfo
      */
     @NonNull
-    public static List<Integer> getSupportedQualities(@NonNull CameraInfo cameraInfo) {
+    public static List<Quality> getSupportedQualities(@NonNull CameraInfo cameraInfo) {
         return VideoCapabilities.from(cameraInfo).getSupportedQualities();
     }
 
@@ -240,11 +99,11 @@
      * <p>Calling this method with one of the qualities contained in the returned list of
      * {@link #getSupportedQualities} will return {@code true}.
      *
-     * <p>Possible values for {@code quality} include {@link #QUALITY_LOWEST},
-     * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD}
-     * and {@link #QUALITY_UHD}.
+     * <p>Possible values for {@code quality} include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD}
+     * and {@link Quality#UHD}.
      *
-     * <p>If this method is called with {@link #QUALITY_LOWEST} or {@link #QUALITY_HIGHEST}, it
+     * <p>If this method is called with {@link Quality#LOWEST} or {@link Quality#HIGHEST}, it
      * will return {@code true} except the case that none of the qualities can be supported.
      *
      * @param cameraInfo the cameraInfo for checking the quality.
@@ -253,129 +112,148 @@
      * @see #getSupportedQualities(CameraInfo)
      */
     public static boolean isQualitySupported(@NonNull CameraInfo cameraInfo,
-            @VideoQuality int quality) {
+            @NonNull Quality quality) {
         return VideoCapabilities.from(cameraInfo).isQualitySupported(quality);
     }
 
     /**
      * Gets the corresponding resolution from the input quality.
      *
-     * <p>Possible values for {@code quality} include {@link #QUALITY_LOWEST},
-     * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD}
-     * and {@link #QUALITY_UHD}.
+     * <p>Possible values for {@code quality} include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD}
+     * and {@link Quality#UHD}.
      *
      * @param cameraInfo the cameraInfo for checking the quality.
      * @param quality one of the quality constants.
      * @return the corresponding resolution from the input quality, or {@code null} if the
-     * quality is not supported on the device. {@link #isQualitySupported(CameraInfo, int)} can
+     * quality is not supported on the device. {@link #isQualitySupported(CameraInfo, Quality)} can
      * be used to check if the input quality is supported.
-     * @throws IllegalArgumentException if not a quality constant
+     * @throws IllegalArgumentException if quality is not one of the possible values.
      * @see #isQualitySupported
      */
     @Nullable
-    public static Size getResolution(@NonNull CameraInfo cameraInfo, @VideoQuality int quality) {
+    public static Size getResolution(@NonNull CameraInfo cameraInfo, @NonNull Quality quality) {
         checkQualityConstantsOrThrow(quality);
         CamcorderProfileProxy profile = VideoCapabilities.from(cameraInfo).getProfile(quality);
         return profile != null ? new Size(profile.getVideoFrameWidth(),
                 profile.getVideoFrameHeight()) : null;
     }
 
-    private final List<Integer> mPreferredQualityList;
-    @VideoQuality
-    private final int mFallbackQuality;
-    @FallbackStrategy
-    private final int mFallbackStrategy;
+    private final List<Quality> mPreferredQualityList;
+    private final FallbackStrategy mFallbackStrategy;
 
-    QualitySelector(@NonNull List<Integer> preferredQualityList,
-            @VideoQuality int fallbackQuality,
-            @FallbackStrategy int fallbackStrategy) {
-        Preconditions.checkArgument(preferredQualityList.size() > 0, "No preferred quality.");
-        mPreferredQualityList = Collections.unmodifiableList(preferredQualityList);
-        mFallbackQuality = fallbackQuality;
+    QualitySelector(@NonNull List<Quality> preferredQualityList,
+            @NonNull FallbackStrategy fallbackStrategy) {
+        Preconditions.checkArgument(
+                !preferredQualityList.isEmpty() || fallbackStrategy != FallbackStrategy.NONE,
+                "No preferred quality and fallback strategy.");
+        mPreferredQualityList = Collections.unmodifiableList(new ArrayList<>(preferredQualityList));
         mFallbackStrategy = fallbackStrategy;
     }
 
     /**
-     * Sets the desired quality with the highest priority.
+     * Gets an instance of QualitySelector with a desired quality.
      *
-     * <p>This method initiates a procedure for specifying the requirements of selecting
-     * qualities. Other requirements can be further added with {@link Procedure} methods.
-     *
-     * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-     * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD},
-     * or {@link #QUALITY_UHD}.
-     * @return the {@link Procedure} for specifying quality selection requirements.
-     * @throws IllegalArgumentException if the given quality is not a quality constant.
-     * @see Procedure
+     * @param quality the quality. Possible values include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD},
+     * or {@link Quality#UHD}.
+     * @return the QualitySelector instance.
+     * @throws NullPointerException if {@code quality} is {@code null}.
+     * @throws IllegalArgumentException if {@code quality} is not one of the possible values.
      */
     @NonNull
-    public static Procedure firstTry(@VideoQuality int quality) {
-        return new Procedure(quality);
+    public static QualitySelector from(@NonNull Quality quality) {
+        return from(quality, FallbackStrategy.NONE);
     }
 
     /**
-     * Gets an instance of QualitySelector with only one desired quality.
+     * Gets an instance of QualitySelector with a desired quality and a fallback strategy.
      *
-     * <p>If there are more than one desired qualities, use {@link #firstTry} for further settings.
+     * <p>If the quality is not supported, the fallback strategy will be applied. The fallback
+     * strategy can be created by {@link FallbackStrategy} API such as
+     * {@link FallbackStrategy#lowerQualityThan(Quality)}.
      *
-     * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-     * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD},
-     * or {@link #QUALITY_UHD}.
+     * @param quality the quality. Possible values include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD},
+     * or {@link Quality#UHD}.
+     * @param fallbackStrategy the fallback strategy that will be applied when the device does
+     *                         not support {@code quality}.
      * @return the QualitySelector instance.
-     * @throws IllegalArgumentException if the given quality is not a quality constant.
+     * @throws NullPointerException if {@code quality} is {@code null} or {@code fallbackStrategy}
+     * is {@code null}.
+     * @throws IllegalArgumentException if {@code quality} is not one of the possible values.
      */
     @NonNull
-    public static QualitySelector of(@VideoQuality int quality) {
-        return of(quality, FALLBACK_STRATEGY_NONE);
+    public static QualitySelector from(@NonNull Quality quality,
+            @NonNull FallbackStrategy fallbackStrategy) {
+        Preconditions.checkNotNull(quality, "quality cannot be null");
+        Preconditions.checkNotNull(fallbackStrategy, "fallbackStrategy cannot be null");
+        checkQualityConstantsOrThrow(quality);
+        return new QualitySelector(Arrays.asList(quality), fallbackStrategy);
     }
 
     /**
-     * Gets an instance of QualitySelector with only one desired quality and a fallback strategy.
+     * Gets an instance of QualitySelector with ordered desired qualities.
      *
-     * <p>If there are more than one desired qualities, use {@link #firstTry} for further settings.
+     * <p>The final quality will be selected according to the order in the quality list.
      *
-     * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-     * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD}, {@link #QUALITY_FHD},
-     * or {@link #QUALITY_UHD}.
-     * @param fallbackStrategy the fallback strategy. Possible values include
-     * {@link #FALLBACK_STRATEGY_HIGHER}, {@link #FALLBACK_STRATEGY_STRICTLY_HIGHER},
-     * {@link #FALLBACK_STRATEGY_LOWER} and {@link #FALLBACK_STRATEGY_STRICTLY_LOWER}.
+     * @param qualities the quality list. Possible values include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD},
+     * or {@link Quality#UHD}.
      * @return the QualitySelector instance.
-     * @throws IllegalArgumentException if {@code quality} is not a quality constant or
-     * {@code fallbackStrategy} is not a fallback strategy constant.
+     * @throws NullPointerException if {@code qualities} is {@code null}.
+     * @throws IllegalArgumentException if {@code qualities} is empty or contains a quality that is
+     * not one of the possible values, including a {@code null} value.
      */
     @NonNull
-    public static QualitySelector of(@VideoQuality int quality,
-            @FallbackStrategy int fallbackStrategy) {
-        return firstTry(quality).finallyTry(quality, fallbackStrategy);
+    public static QualitySelector fromOrderedList(@NonNull List<Quality> qualities) {
+        return fromOrderedList(qualities, FallbackStrategy.NONE);
+    }
+
+    /**
+     * Gets an instance of QualitySelector with ordered desired qualities and a fallback strategy.
+     *
+     * <p>The final quality will be selected according to the order in the quality list.
+     * If no quality is supported, the fallback strategy will be applied. The fallback
+     * strategy can be created by {@link FallbackStrategy} API such as
+     * {@link FallbackStrategy#lowerQualityThan(Quality)}.
+     *
+     * @param qualities the quality list. Possible values include {@link Quality#LOWEST},
+     * {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD}, {@link Quality#FHD},
+     * or {@link Quality#UHD}.
+     * @param fallbackStrategy the fallback strategy that will be applied when the device does
+     *                         not support those {@code qualities}.
+     * @throws NullPointerException if {@code qualities} is {@code null} or
+     * {@code fallbackStrategy} is {@code null}.
+     * @throws IllegalArgumentException if {@code qualities} is empty or contains a quality that is
+     * not one of the possible values, including a {@code null} value.
+     */
+    @NonNull
+    public static QualitySelector fromOrderedList(@NonNull List<Quality> qualities,
+            @NonNull FallbackStrategy fallbackStrategy) {
+        Preconditions.checkNotNull(qualities, "qualities cannot be null");
+        Preconditions.checkNotNull(fallbackStrategy, "fallbackStrategy cannot be null");
+        Preconditions.checkArgument(!qualities.isEmpty(), "qualities cannot be empty");
+        checkQualityConstantsOrThrow(qualities);
+        return new QualitySelector(qualities, fallbackStrategy);
     }
 
     /**
      * Generates a sorted quality list that matches the desired quality settings.
      *
      * <p>The method bases on the desired qualities and the fallback strategy to find a supported
-     * quality list on this device. The desired qualities can be set by a series of try methods such
-     * as {@link #firstTry(int)}, {@link #of(int)}, {@link Procedure#thenTry(int)} and
-     * {@link Procedure#finallyTry(int)}. The fallback strategy can be set via
-     * {@link #of(int, int)} and {@link Procedure#finallyTry(int, int)}. If no fallback strategy
-     * is specified, {@link #FALLBACK_STRATEGY_NONE} will be applied by default.
-     *
-     * <p>The search algorithm first checks which desired quality is supported according to the
-     * set sequence and adds to the returned list by order. Then the fallback strategy will be
-     * applied to add more valid qualities.
+     * quality list on this device. The search algorithm first checks which desired quality is
+     * supported according to the set sequence and adds to the returned list by order. Then the
+     * fallback strategy will be applied to add more valid qualities.
      *
      * @param cameraInfo the cameraInfo for checking the quality.
      * @return a sorted supported quality list according to the desired quality settings.
-     * @see Procedure
-     *
-     * @hide
      */
-    @RestrictTo(Scope.LIBRARY)
     @NonNull
-    public List<Integer> getPrioritizedQualities(@NonNull CameraInfo cameraInfo) {
+    List<Quality> getPrioritizedQualities(@NonNull CameraInfo cameraInfo) {
         VideoCapabilities videoCapabilities = VideoCapabilities.from(cameraInfo);
 
-        List<Integer> supportedQualities = videoCapabilities.getSupportedQualities();
+        List<Quality> supportedQualities = videoCapabilities.getSupportedQualities();
         if (supportedQualities.isEmpty()) {
             Logger.w(TAG, "No supported quality on the device.");
             return new ArrayList<>();
@@ -383,23 +261,25 @@
         Logger.d(TAG, "supportedQualities = " + supportedQualities);
 
         // Use LinkedHashSet to prevent from duplicate quality and keep the adding order.
-        Set<Integer> sortedQualities = new LinkedHashSet<>();
+        Set<Quality> sortedQualities = new LinkedHashSet<>();
         // Add exact quality.
-        for (Integer quality : mPreferredQualityList) {
-            if (quality == QUALITY_HIGHEST) {
+        for (Quality quality : mPreferredQualityList) {
+            if (quality == Quality.HIGHEST) {
                 // Highest means user want a quality as higher as possible, so the return list can
                 // contain all supported resolutions from large to small.
                 sortedQualities.addAll(supportedQualities);
                 break;
-            } else if (quality == QUALITY_LOWEST) {
+            } else if (quality == Quality.LOWEST) {
                 // Opposite to the highest
-                List<Integer> reversedList = new ArrayList<>(supportedQualities);
+                List<Quality> reversedList = new ArrayList<>(supportedQualities);
                 Collections.reverse(reversedList);
                 sortedQualities.addAll(reversedList);
                 break;
             } else {
                 if (supportedQualities.contains(quality)) {
                     sortedQualities.add(quality);
+                } else {
+                    Logger.w(TAG, "quality is not supported and will be ignored: " + quality);
                 }
             }
         }
@@ -415,13 +295,12 @@
     public String toString() {
         return "QualitySelector{"
                 + "preferredQualities=" + mPreferredQualityList
-                + ", fallbackQuality=" + mFallbackQuality
                 + ", fallbackStrategy=" + mFallbackStrategy
                 + "}";
     }
 
-    private void addByFallbackStrategy(@NonNull List<Integer> supportedQualities,
-            @NonNull Set<Integer> priorityQualities) {
+    private void addByFallbackStrategy(@NonNull List<Quality> supportedQualities,
+            @NonNull Set<Quality> priorityQualities) {
         if (supportedQualities.isEmpty()) {
             return;
         }
@@ -430,42 +309,45 @@
             // fallback strategy.
             return;
         }
-        Logger.d(TAG, "Select quality by fallbackStrategy = " + mFallbackStrategy
-                + " on fallback quality = " + mFallbackQuality);
+        Logger.d(TAG, "Select quality by fallbackStrategy = " + mFallbackStrategy);
         // No fallback strategy, return directly.
-        if (mFallbackStrategy == QualitySelector.FALLBACK_STRATEGY_NONE) {
+        if (mFallbackStrategy == FallbackStrategy.NONE) {
             return;
         }
+        Preconditions.checkState(mFallbackStrategy instanceof FallbackStrategy.RuleStrategy,
+                "Currently only support type RuleStrategy");
+        FallbackStrategy.RuleStrategy fallbackStrategy =
+                (FallbackStrategy.RuleStrategy) mFallbackStrategy;
 
         // Note that fallback quality could be an unsupported quality, so all quality constants
         // need to be loaded to find the position of fallback quality.
         // The list returned from getSortedQualities() is sorted from large to small.
-        List<Integer> sizeSortedQualities = getSortedQualities();
-        int fallbackQuality;
-        if (mFallbackQuality == QUALITY_HIGHEST) {
+        List<Quality> sizeSortedQualities = Quality.getSortedQualities();
+        Quality fallbackQuality;
+        if (fallbackStrategy.getFallbackQuality() == Quality.HIGHEST) {
             fallbackQuality = sizeSortedQualities.get(0);
-        } else if (mFallbackQuality == QUALITY_LOWEST) {
+        } else if (fallbackStrategy.getFallbackQuality() == Quality.LOWEST) {
             fallbackQuality = sizeSortedQualities.get(sizeSortedQualities.size() - 1);
         } else {
-            fallbackQuality = mFallbackQuality;
+            fallbackQuality = fallbackStrategy.getFallbackQuality();
         }
 
         int index = sizeSortedQualities.indexOf(fallbackQuality);
         Preconditions.checkState(index != -1); // Should not happen.
 
         // search larger supported quality
-        List<Integer> largerQualities = new ArrayList<>();
+        List<Quality> largerQualities = new ArrayList<>();
         for (int i = index - 1; i >= 0; i--) {
-            int quality = sizeSortedQualities.get(i);
+            Quality quality = sizeSortedQualities.get(i);
             if (supportedQualities.contains(quality)) {
                 largerQualities.add(quality);
             }
         }
 
         // search smaller supported quality
-        List<Integer> smallerQualities = new ArrayList<>();
+        List<Quality> smallerQualities = new ArrayList<>();
         for (int i = index + 1; i < sizeSortedQualities.size(); i++) {
-            int quality = sizeSortedQualities.get(i);
+            Quality quality = sizeSortedQualities.get(i);
             if (supportedQualities.contains(quality)) {
                 smallerQualities.add(quality);
             }
@@ -476,22 +358,22 @@
                 + ", largerQualities = " + largerQualities
                 + ", smallerQualities = " + smallerQualities);
 
-        switch (mFallbackStrategy) {
-            case QualitySelector.FALLBACK_STRATEGY_HIGHER:
+        switch (fallbackStrategy.getFallbackRule()) {
+            case FallbackStrategy.FALLBACK_RULE_HIGHER_OR_LOWER:
                 priorityQualities.addAll(largerQualities);
                 priorityQualities.addAll(smallerQualities);
                 break;
-            case QualitySelector.FALLBACK_STRATEGY_STRICTLY_HIGHER:
+            case FallbackStrategy.FALLBACK_RULE_HIGHER:
                 priorityQualities.addAll(largerQualities);
                 break;
-            case QualitySelector.FALLBACK_STRATEGY_LOWER:
+            case FallbackStrategy.FALLBACK_RULE_LOWER_OR_HIGHER:
                 priorityQualities.addAll(smallerQualities);
                 priorityQualities.addAll(largerQualities);
                 break;
-            case QualitySelector.FALLBACK_STRATEGY_STRICTLY_LOWER:
+            case FallbackStrategy.FALLBACK_RULE_LOWER:
                 priorityQualities.addAll(smallerQualities);
                 break;
-            case QualitySelector.FALLBACK_STRATEGY_NONE:
+            case FallbackStrategy.FALLBACK_RULE_NONE:
                 // No-Op
                 break;
             default:
@@ -499,108 +381,15 @@
         }
     }
 
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    static void checkQualityConstantsOrThrow(@QualitySelector.VideoQuality int quality) {
-        Preconditions.checkArgument(QualitySelector.containsQuality(quality),
-                "Unknown quality: " + quality);
+    private static void checkQualityConstantsOrThrow(@NonNull List<Quality> qualities) {
+        for (Quality quality : qualities) {
+            Preconditions.checkArgument(Quality.containsQuality(quality),
+                    "qualities contain invalid quality: " + quality);
+        }
     }
 
-    /**
-     * Procedure can be used to build {@link QualitySelector} with further settings.
-     *
-     * <p>A QualitySelector can be simply created by {@link QualitySelector#of QualitySelector.of}
-     * with a single desired quality. When more quality settings are needed, use
-     * {@link QualitySelector#firstTry} to get a Procedure, chain the desired qualities by
-     * {@link #thenTry} and generate the QualitySelector by {@link #finallyTry} with or without
-     * fallback strategy. For example:
-     *
-     * <pre>{@code
-     *   QualitySelector qualitySelector = QualitySelector
-     *           .firstTry(QualitySelector.QUALITY_UHD)
-     *           .thenTry(QualitySelector.QUALITY_HD)
-     *           .finallyTry(QualitySelector.QUALITY_SD)
-     * }</pre>
-     * or
-     <pre>{@code
-     *   QualitySelector qualitySelector = QualitySelector
-     *           .firstTry(QualitySelector.QUALITY_UHD)
-     *           .finallyTry(QualitySelector.QUALITY_HD,
-     *                   QualitySelector.FALLBACK_STRATEGY_STRICTLY_LOWER)
-     * }</pre>
-     */
-    public static class Procedure {
-        private final List<Integer> mPreferredQualityList = new ArrayList<>();
-
-        Procedure(int quality) {
-            addQuality(quality);
-        }
-
-        /**
-         * Adds a quality candidate.
-         *
-         * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-         * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD},
-         * {@link #QUALITY_FHD} or {@link #QUALITY_UHD}.
-         * @return the procedure that can continue to be set
-         * @throws IllegalArgumentException if the given quality is not a quality constant
-         */
-        @NonNull
-        public Procedure thenTry(@VideoQuality int quality) {
-            addQuality(quality);
-            return this;
-        }
-
-        /**
-         * Sets the final desired quality.
-         *
-         * <p>This method finishes the setting procedure and generates a {@link QualitySelector}
-         * with the requirements set to the procedure.
-         *
-         * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-         * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD},
-         * {@link #QUALITY_FHD} or {@link #QUALITY_UHD}.
-         * @return the {@link QualitySelector}.
-         * @throws IllegalArgumentException if the given quality is not a quality constant
-         */
-        @NonNull
-        public QualitySelector finallyTry(@VideoQuality int quality) {
-            return finallyTry(quality, FALLBACK_STRATEGY_NONE);
-        }
-
-        /**
-         * Sets the final desired quality and fallback strategy.
-         *
-         * <p>The fallback strategy will be applied on this quality when all desired qualities are
-         * not supported.
-         *
-         * <p>This method finishes the setting procedure and generates a {@link QualitySelector}
-         * with the requirements set to the procedure.
-         *
-         * @param quality the quality constant. Possible values include {@link #QUALITY_LOWEST},
-         * {@link #QUALITY_HIGHEST}, {@link #QUALITY_SD}, {@link #QUALITY_HD},
-         * {@link #QUALITY_FHD} or {@link #QUALITY_UHD}.
-         * @param fallbackStrategy the fallback strategy. Possible values include
-         * {@link #FALLBACK_STRATEGY_HIGHER}, {@link #FALLBACK_STRATEGY_STRICTLY_HIGHER},
-         * {@link #FALLBACK_STRATEGY_LOWER} and {@link #FALLBACK_STRATEGY_STRICTLY_LOWER}.
-         * @return the {@link QualitySelector}.
-         * @throws IllegalArgumentException if {@code quality} is not a quality constant or
-         * {@code fallbackStrategy} is not a fallback strategy constant.
-         */
-        @NonNull
-        public QualitySelector finallyTry(@VideoQuality int quality,
-                @FallbackStrategy int fallbackStrategy) {
-            Preconditions.checkArgument(fallbackStrategy >= FALLBACK_STRATEGY_START
-                            && fallbackStrategy <= FALLBACK_STRATEGY_END,
-                    "The value must be a fallback strategy constant.");
-            addQuality(quality);
-            return new QualitySelector(new ArrayList<>(mPreferredQualityList), quality,
-                    fallbackStrategy);
-        }
-
-        private void addQuality(@VideoQuality int quality) {
-            checkQualityConstantsOrThrow(quality);
-            Preconditions.checkArgument(quality != QUALITY_NONE, "Unsupported quality: " + quality);
-            mPreferredQualityList.add(quality);
-        }
+    private static void checkQualityConstantsOrThrow(@NonNull Quality quality) {
+        Preconditions.checkArgument(Quality.containsQuality(quality),
+                "Invalid quality: " + quality);
     }
 }
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
index 99a635a9..27d260e7 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/Recorder.java
@@ -16,10 +16,6 @@
 
 package androidx.camera.video;
 
-import static androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_HIGHER;
-import static androidx.camera.video.QualitySelector.QUALITY_FHD;
-import static androidx.camera.video.QualitySelector.QUALITY_HD;
-import static androidx.camera.video.QualitySelector.QUALITY_SD;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_ENCODING_FAILED;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_FILE_SIZE_LIMIT_REACHED;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_INVALID_OUTPUT_OPTIONS;
@@ -34,8 +30,8 @@
 import android.annotation.SuppressLint;
 import android.content.ContentValues;
 import android.content.Context;
-import android.media.MediaCodecInfo;
 import android.media.MediaMuxer;
+import android.media.MediaRecorder;
 import android.media.MediaScannerConnection;
 import android.net.Uri;
 import android.os.Build;
@@ -53,6 +49,7 @@
 import androidx.camera.core.AspectRatio;
 import androidx.camera.core.Logger;
 import androidx.camera.core.SurfaceRequest;
+import androidx.camera.core.impl.CamcorderProfileProxy;
 import androidx.camera.core.impl.MutableStateObservable;
 import androidx.camera.core.impl.Observable;
 import androidx.camera.core.impl.StateObservable;
@@ -63,18 +60,23 @@
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.camera.video.internal.AudioSource;
 import androidx.camera.video.internal.AudioSourceAccessException;
-import androidx.camera.video.internal.BufferProvider;
 import androidx.camera.video.internal.ResourceCreationException;
 import androidx.camera.video.internal.compat.Api26Impl;
 import androidx.camera.video.internal.compat.quirk.DeactivateEncoderSurfaceBeforeStopEncoderQuirk;
 import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
+import androidx.camera.video.internal.config.AudioEncoderConfigCamcorderProfileResolver;
+import androidx.camera.video.internal.config.AudioEncoderConfigDefaultResolver;
+import androidx.camera.video.internal.config.AudioSourceSettingsCamcorderProfileResolver;
+import androidx.camera.video.internal.config.AudioSourceSettingsDefaultResolver;
+import androidx.camera.video.internal.config.MimeInfo;
+import androidx.camera.video.internal.config.VideoEncoderConfigCamcorderProfileResolver;
+import androidx.camera.video.internal.config.VideoEncoderConfigDefaultResolver;
 import androidx.camera.video.internal.encoder.AudioEncoderConfig;
 import androidx.camera.video.internal.encoder.EncodeException;
 import androidx.camera.video.internal.encoder.EncodedData;
 import androidx.camera.video.internal.encoder.Encoder;
 import androidx.camera.video.internal.encoder.EncoderCallback;
 import androidx.camera.video.internal.encoder.EncoderImpl;
-import androidx.camera.video.internal.encoder.InputBuffer;
 import androidx.camera.video.internal.encoder.InvalidConfigException;
 import androidx.camera.video.internal.encoder.OutputConfig;
 import androidx.camera.video.internal.encoder.VideoEncoderConfig;
@@ -82,6 +84,7 @@
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 import androidx.core.util.Consumer;
 import androidx.core.util.Preconditions;
+import androidx.core.util.Supplier;
 
 import com.google.auto.value.AutoValue;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -89,6 +92,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
@@ -234,29 +238,16 @@
      * <p>The default quality selector chooses a video quality suitable for recordings based on
      * device and compatibility constraints. It is equivalent to:
      * <pre>{@code
-     * QualitySelector.firstTry(QUALITY_FHD)
-     *         .thenTry(QUALITY_HD)
-     *         .thenTry(QUALITY_SD)
-     *         .finallyTry(QUALITY_FHD, FALLBACK_STRATEGY_HIGHER);
+     * QualitySelector.fromOrderedList(Arrays.asList(Quality.FHD, Quality.HD, Quality.SD),
+     *         FallbackStrategy.higherQualityOrLowerThan(Quality.FHD));
      * }</pre>
      *
      * @see QualitySelector
      */
     public static final QualitySelector DEFAULT_QUALITY_SELECTOR =
-            QualitySelector.firstTry(QUALITY_FHD)
-                    .thenTry(QUALITY_HD)
-                    .thenTry(QUALITY_SD)
-                    .finallyTry(QUALITY_FHD, FALLBACK_STRATEGY_HIGHER);
+            QualitySelector.fromOrderedList(Arrays.asList(Quality.FHD, Quality.HD, Quality.SD),
+                    FallbackStrategy.higherQualityOrLowerThan(Quality.FHD));
 
-    private static final AudioSpec AUDIO_SPEC_DEFAULT =
-            AudioSpec.builder()
-                    .setSourceFormat(
-                            AudioSpec.SOURCE_FORMAT_PCM_16BIT) /* Defaults to PCM_16BIT as it's
-                            guaranteed supported on devices. May consider allowing users to set
-                            format through AudioSpec later. */
-                    .setSource(AudioSpec.SOURCE_CAMCORDER)
-                    .setChannelCount(AudioSpec.CHANNEL_COUNT_MONO)
-                    .build();
     private static final VideoSpec VIDEO_SPEC_DEFAULT =
             VideoSpec.builder()
                     .setQualitySelector(DEFAULT_QUALITY_SELECTOR)
@@ -264,16 +255,9 @@
                     .build();
     private static final MediaSpec MEDIA_SPEC_DEFAULT =
             MediaSpec.builder()
-                    .setOutputFormat(MediaSpec.OUTPUT_FORMAT_MPEG_4)
-                    .setAudioSpec(AUDIO_SPEC_DEFAULT)
+                    .setOutputFormat(MediaSpec.OUTPUT_FORMAT_AUTO)
                     .setVideoSpec(VIDEO_SPEC_DEFAULT)
                     .build();
-    private static final int AUDIO_BITRATE_DEFAULT = 88200;
-    // Default to 44100 for now as it's guaranteed supported on devices.
-    private static final int AUDIO_SAMPLE_RATE_DEFAULT = 44100;
-    private static final int VIDEO_FRAME_RATE_DEFAULT = 30;
-    private static final int VIDEO_BITRATE_DEFAULT = 10 * 1024 * 1024; // 10M
-    private static final int VIDEO_INTRA_FRAME_INTERVAL_DEFAULT = 1;
     @SuppressWarnings("deprecation")
     private static final String MEDIA_COLUMN = MediaStore.Video.Media.DATA;
     private static final Exception PENDING_RECORDING_ERROR_CAUSE_SOURCE_INACTIVE =
@@ -328,6 +312,7 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     boolean mInProgressRecordingStopping = false;
     private SurfaceRequest.TransformationInfo mSurfaceTransformationInfo = null;
+    private CamcorderProfileProxy mResolvedCamcorderProfile = null;
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     final List<ListenableFuture<Void>> mEncodingFutures = new ArrayList<>();
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
@@ -978,10 +963,25 @@
             });
             onInitialized();
         } else {
-            setupVideo(surfaceRequest);
             surfaceRequest.setTransformationInfoListener(mSequentialExecutor,
                     (transformationInfo) -> mSurfaceTransformationInfo =
                             transformationInfo);
+            Size surfaceSize = surfaceRequest.getResolution();
+            // Fetch and cache nearest camcorder profile, if one exists.
+            VideoCapabilities capabilities =
+                    VideoCapabilities.from(surfaceRequest.getCamera().getCameraInfo());
+            Quality highestSupportedQuality =
+                    capabilities.findHighestSupportedQualityFor(surfaceSize);
+            Logger.d(TAG, "Using supported quality of " + highestSupportedQuality
+                    + " for surface size " + surfaceSize);
+            if (highestSupportedQuality != Quality.NONE) {
+                mResolvedCamcorderProfile = capabilities.getProfile(highestSupportedQuality);
+                if (mResolvedCamcorderProfile == null) {
+                    throw new AssertionError("Camera advertised available quality but did not "
+                            + "produce CamcorderProfile for advertised quality.");
+                }
+            }
+            setupVideo(surfaceRequest);
         }
     }
 
@@ -1028,24 +1028,6 @@
     @NonNull
     private MediaSpec composeRecorderMediaSpec(@NonNull MediaSpec mediaSpec) {
         MediaSpec.Builder mediaSpecBuilder = mediaSpec.toBuilder();
-        if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
-            mediaSpecBuilder.setOutputFormat(MEDIA_SPEC_DEFAULT.getOutputFormat());
-        }
-
-        // Append default audio configurations
-        AudioSpec audioSpec = mediaSpec.getAudioSpec();
-        if (audioSpec.getSourceFormat() == AudioSpec.SOURCE_FORMAT_AUTO) {
-            mediaSpecBuilder.configureAudio(
-                    builder -> builder.setSourceFormat(AUDIO_SPEC_DEFAULT.getSourceFormat()));
-        }
-        if (audioSpec.getSource() == AudioSpec.SOURCE_AUTO) {
-            mediaSpecBuilder.configureAudio(
-                    builder -> builder.setSource(AUDIO_SPEC_DEFAULT.getSource()));
-        }
-        if (audioSpec.getChannelCount() == AudioSpec.CHANNEL_COUNT_AUTO) {
-            mediaSpecBuilder.configureAudio(
-                    builder -> builder.setChannelCount(AUDIO_SPEC_DEFAULT.getChannelCount()));
-        }
 
         // Append default video configurations
         VideoSpec videoSpec = mediaSpec.getVideoSpec();
@@ -1068,29 +1050,146 @@
 
     @ExecutedBy("mSequentialExecutor")
     @NonNull
-    private AudioEncoderConfig composeAudioEncoderConfig(@NonNull MediaSpec mediaSpec) {
-        return AudioEncoderConfig.builder()
-                .setMimeType(MediaSpec.outputFormatToAudioMime(mediaSpec.getOutputFormat()))
-                .setBitrate(AUDIO_BITRATE_DEFAULT)
-                .setSampleRate(selectSampleRate(mediaSpec.getAudioSpec()))
-                .setChannelCount(mediaSpec.getAudioSpec().getChannelCount())
-                .build();
+    private MimeInfo resolveAudioMimeInfo(@NonNull MediaSpec mediaSpec) {
+        String mediaSpecAudioMime = MediaSpec.outputFormatToAudioMime(mediaSpec.getOutputFormat());
+        int mediaSpecAudioProfile =
+                MediaSpec.outputFormatToAudioProfile(mediaSpec.getOutputFormat());
+        String resolvedAudioMime = mediaSpecAudioMime;
+        int resolvedAudioProfile = mediaSpecAudioProfile;
+        boolean camcorderProfileIsCompatible = false;
+        if (mResolvedCamcorderProfile != null) {
+            String camcorderProfileAudioMime = mResolvedCamcorderProfile.getAudioCodecMimeType();
+            int camcorderProfileAudioProfile = mResolvedCamcorderProfile.getRequiredAudioProfile();
+
+            if (camcorderProfileAudioMime == null) {
+                Logger.d(TAG, "CamcorderProfile contains undefined AUDIO mime type so cannot be "
+                        + "used. May rely on fallback defaults to derive settings [chosen mime "
+                        + "type: "
+                        + resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
+            } else if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
+                camcorderProfileIsCompatible = true;
+                resolvedAudioMime = camcorderProfileAudioMime;
+                resolvedAudioProfile = camcorderProfileAudioProfile;
+                Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using CamcorderProfile "
+                        + "to derive AUDIO settings [mime type: "
+                        + resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
+            } else if (Objects.equals(mediaSpecAudioMime, camcorderProfileAudioMime)
+                    && mediaSpecAudioProfile == camcorderProfileAudioProfile) {
+                camcorderProfileIsCompatible = true;
+                resolvedAudioMime = camcorderProfileAudioMime;
+                resolvedAudioProfile = camcorderProfileAudioProfile;
+                Logger.d(TAG, "MediaSpec audio mime/profile matches CamcorderProfile. "
+                        + "Using CamcorderProfile to derive AUDIO settings [mime type: "
+                        + resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
+            } else {
+                Logger.d(TAG, "MediaSpec audio mime or profile does not match CamcorderProfile, so "
+                        + "CamcorderProfile settings cannot be used. May rely on fallback "
+                        + "defaults to derive AUDIO settings [CamcorderProfile mime type: "
+                        + camcorderProfileAudioMime + "(profile: " + camcorderProfileAudioProfile
+                        + "), chosen mime type: "
+                        + resolvedAudioMime + "(profile: " + resolvedAudioProfile + ")]");
+            }
+        }
+
+        MimeInfo.Builder mimeInfoBuilder = MimeInfo.builder(resolvedAudioMime)
+                .setProfile(resolvedAudioProfile);
+        if (camcorderProfileIsCompatible) {
+            mimeInfoBuilder.setCompatibleCamcorderProfile(mResolvedCamcorderProfile);
+        }
+
+        return mimeInfoBuilder.build();
     }
 
     @ExecutedBy("mSequentialExecutor")
     @NonNull
-    private VideoEncoderConfig composeVideoEncoderConfig(@NonNull MediaSpec mediaSpec,
-            @NonNull Size surfaceSize) {
-        return VideoEncoderConfig.builder()
-                .setMimeType(MediaSpec.outputFormatToVideoMime(mediaSpec.getOutputFormat()))
-                .setResolution(surfaceSize)
-                // TODO: Add mechanism to pick a value from the specified range and
-                //  CamcorderProfile.
-                .setBitrate(VIDEO_BITRATE_DEFAULT)
-                .setFrameRate(VIDEO_FRAME_RATE_DEFAULT)
-                .setColorFormat(MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
-                .setIFrameInterval(VIDEO_INTRA_FRAME_INTERVAL_DEFAULT)
-                .build();
+    private MimeInfo resolveVideoMimeInfo(@NonNull MediaSpec mediaSpec) {
+        String mediaSpecVideoMime = MediaSpec.outputFormatToVideoMime(mediaSpec.getOutputFormat());
+        String resolvedVideoMime = mediaSpecVideoMime;
+        boolean camcorderProfileIsCompatible = false;
+        if (mResolvedCamcorderProfile != null) {
+            String camcorderProfileVideoMime = mResolvedCamcorderProfile.getVideoCodecMimeType();
+            // Use camcorder profile settings if the media spec's output format
+            // is set to auto or happens to match the CamcorderProfile's output format.
+            if (camcorderProfileVideoMime == null) {
+                Logger.d(TAG, "CamcorderProfile contains undefined VIDEO mime type so cannot be "
+                        + "used. May rely on fallback defaults to derive settings [chosen mime "
+                        + "type: " + resolvedVideoMime + "]");
+            } else if (mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO) {
+                camcorderProfileIsCompatible = true;
+                resolvedVideoMime = camcorderProfileVideoMime;
+                Logger.d(TAG, "MediaSpec contains OUTPUT_FORMAT_AUTO. Using CamcorderProfile "
+                        + "to derive VIDEO settings [mime type: " + resolvedVideoMime + "]");
+            } else if (Objects.equals(mediaSpecVideoMime, camcorderProfileVideoMime)) {
+                camcorderProfileIsCompatible = true;
+                resolvedVideoMime = camcorderProfileVideoMime;
+                Logger.d(TAG, "MediaSpec video mime matches CamcorderProfile. Using "
+                        + "CamcorderProfile to derive VIDEO settings [mime type: "
+                        + resolvedVideoMime + "]");
+            } else {
+                Logger.d(TAG, "MediaSpec video mime does not match CamcorderProfile, so "
+                        + "CamcorderProfile settings cannot be used. May rely on fallback "
+                        + "defaults to derive VIDEO settings [CamcorderProfile mime type: "
+                        + camcorderProfileVideoMime + ", chosen mime type: "
+                        + resolvedVideoMime + "]");
+            }
+        } else {
+            Logger.d(TAG,
+                    "No CamcorderProfile present. May rely on fallback defaults to derive VIDEO "
+                            + "settings [chosen mime type: " + resolvedVideoMime + "]");
+        }
+
+        MimeInfo.Builder mimeInfoBuilder = MimeInfo.builder(resolvedVideoMime);
+        if (camcorderProfileIsCompatible) {
+            mimeInfoBuilder.setCompatibleCamcorderProfile(mResolvedCamcorderProfile);
+        }
+
+        return mimeInfoBuilder.build();
+    }
+
+    @NonNull
+    private static AudioSource.Settings resolveAudioSourceSettings(@NonNull MimeInfo audioMimeInfo,
+            @NonNull AudioSpec audioSpec) {
+        Supplier<AudioSource.Settings> settingsSupplier;
+        if (audioMimeInfo.getCompatibleCamcorderProfile() != null) {
+            settingsSupplier = new AudioSourceSettingsCamcorderProfileResolver(audioSpec,
+                    audioMimeInfo.getCompatibleCamcorderProfile());
+        } else {
+            settingsSupplier = new AudioSourceSettingsDefaultResolver(audioSpec);
+        }
+
+        return settingsSupplier.get();
+    }
+
+    @NonNull
+    private static AudioEncoderConfig resolveAudioEncoderConfig(@NonNull MimeInfo audioMimeInfo,
+            @NonNull AudioSource.Settings audioSourceSettings, @NonNull AudioSpec audioSpec) {
+        Supplier<AudioEncoderConfig> configSupplier;
+        if (audioMimeInfo.getCompatibleCamcorderProfile() != null) {
+            configSupplier = new AudioEncoderConfigCamcorderProfileResolver(
+                    audioMimeInfo.getMimeType(), audioMimeInfo.getProfile(), audioSpec,
+                    audioSourceSettings, audioMimeInfo.getCompatibleCamcorderProfile());
+        } else {
+            configSupplier = new AudioEncoderConfigDefaultResolver(audioMimeInfo.getMimeType(),
+                    audioMimeInfo.getProfile(), audioSpec, audioSourceSettings);
+        }
+
+        return configSupplier.get();
+    }
+
+    @NonNull
+    private static VideoEncoderConfig resolveVideoEncoderConfig(@NonNull MimeInfo videoMimeInfo,
+            @NonNull VideoSpec videoSpec, @NonNull Size surfaceSize) {
+        Supplier<VideoEncoderConfig> configSupplier;
+        if (videoMimeInfo.getCompatibleCamcorderProfile() != null) {
+            configSupplier = new VideoEncoderConfigCamcorderProfileResolver(
+                    videoMimeInfo.getMimeType(), videoSpec, surfaceSize,
+                    videoMimeInfo.getCompatibleCamcorderProfile());
+        } else {
+            configSupplier = new VideoEncoderConfigDefaultResolver(videoMimeInfo.getMimeType(),
+                    videoSpec, surfaceSize);
+        }
+
+        return configSupplier.get();
     }
 
     /**
@@ -1103,38 +1202,41 @@
     @ExecutedBy("mSequentialExecutor")
     private void setupAudio() throws ResourceCreationException {
         MediaSpec mediaSpec = getObservableData(mMediaSpec);
-        AudioEncoderConfig config = composeAudioEncoderConfig(mediaSpec);
+        // Resolve the audio mime info
+        MimeInfo audioMimeInfo = resolveAudioMimeInfo(mediaSpec);
 
+        // Select and create the audio source
+        AudioSource.Settings audioSourceSettings =
+                resolveAudioSourceSettings(audioMimeInfo, mediaSpec.getAudioSpec());
         try {
-            mAudioEncoder = new EncoderImpl(mExecutor, config);
+            mAudioSource = setupAudioSource(audioSourceSettings);
+        } catch (AudioSourceAccessException e) {
+            throw new ResourceCreationException(e);
+        }
+
+        // Select and create the audio encoder
+        AudioEncoderConfig audioEncoderConfig = resolveAudioEncoderConfig(audioMimeInfo,
+                audioSourceSettings, mediaSpec.getAudioSpec());
+        try {
+            mAudioEncoder = new EncoderImpl(mExecutor, audioEncoderConfig);
         } catch (InvalidConfigException e) {
             throw new ResourceCreationException(e);
         }
 
+        // Connect the audio source to the audio encoder
         Encoder.EncoderInput bufferProvider = mAudioEncoder.getInput();
         if (!(bufferProvider instanceof Encoder.ByteBufferInput)) {
             throw new AssertionError("The EncoderInput of audio isn't a ByteBufferInput.");
         }
-        try {
-            mAudioSource = setupAudioSource((Encoder.ByteBufferInput) bufferProvider,
-                    mediaSpec.getAudioSpec());
-        } catch (AudioSourceAccessException e) {
-            throw new ResourceCreationException(e);
-        }
+        mAudioSource.setBufferProvider((Encoder.ByteBufferInput) bufferProvider);
     }
 
     @RequiresPermission(Manifest.permission.RECORD_AUDIO)
     @NonNull
-    private AudioSource setupAudioSource(@NonNull BufferProvider<InputBuffer> bufferProvider,
-            @NonNull AudioSpec audioSpec) throws AudioSourceAccessException {
-        AudioSource audioSource = new AudioSource.Builder()
-                .setExecutor(CameraXExecutors.ioExecutor())
-                .setBufferProvider(bufferProvider)
-                .setAudioSource(audioSpec.getSource())
-                .setSampleRate(selectSampleRate(audioSpec))
-                .setChannelCount(audioSpec.getChannelCount())
-                .setAudioFormat(audioSpec.getSourceFormat())
-                .build();
+    private AudioSource setupAudioSource(@NonNull AudioSource.Settings audioSourceSettings)
+            throws AudioSourceAccessException {
+        AudioSource audioSource = new AudioSource(audioSourceSettings,
+                CameraXExecutors.ioExecutor());
         audioSource.setAudioSourceCallback(mSequentialExecutor,
                 new AudioSource.AudioSourceCallback() {
                     @Override
@@ -1162,30 +1264,11 @@
     }
 
     @ExecutedBy("mSequentialExecutor")
-    private int selectSampleRate(AudioSpec audioSpec) {
-        // The default sample rate should work on most devices. May consider throw an
-        // exception or have other way to notify users that the specified sample rate
-        // can not be satisfied.
-        int selectedSampleRate = AUDIO_SAMPLE_RATE_DEFAULT;
-        for (int sampleRate : AudioSource.COMMON_SAMPLE_RATES) {
-            if (audioSpec.getSampleRate().contains(sampleRate)) {
-                if (AudioSource.isSettingsSupported(sampleRate, audioSpec.getChannelCount(),
-                        audioSpec.getSourceFormat())) {
-                    // Choose the largest valid sample rate as the list has descending order.
-                    selectedSampleRate = sampleRate;
-                    break;
-                }
-            }
-        }
-
-        return selectedSampleRate;
-    }
-
-    @ExecutedBy("mSequentialExecutor")
     private void setupVideo(@NonNull SurfaceRequest surfaceRequest) {
         MediaSpec mediaSpec = getObservableData(mMediaSpec);
-        VideoEncoderConfig config = composeVideoEncoderConfig(mediaSpec,
-                surfaceRequest.getResolution());
+        MimeInfo videoMimeInfo = resolveVideoMimeInfo(mediaSpec);
+        VideoEncoderConfig config = resolveVideoEncoderConfig(videoMimeInfo,
+                mediaSpec.getVideoSpec(), surfaceRequest.getResolution());
 
         try {
             mVideoEncoder = new EncoderImpl(mExecutor, config);
@@ -1293,8 +1376,13 @@
             }
 
             try {
-                int muxerOutputFormat = MediaSpec.outputFormatToMuxerFormat(
-                        getObservableData(mMediaSpec).getOutputFormat());
+                MediaSpec mediaSpec = getObservableData(mMediaSpec);
+                int muxerOutputFormat =
+                        mediaSpec.getOutputFormat() == MediaSpec.OUTPUT_FORMAT_AUTO
+                                ? supportedMuxerFormatOrDefaultFrom(mResolvedCamcorderProfile,
+                                MediaSpec.outputFormatToMuxerFormat(
+                                        MEDIA_SPEC_DEFAULT.getOutputFormat()))
+                                : MediaSpec.outputFormatToMuxerFormat(mediaSpec.getOutputFormat());
                 mMediaMuxer = recordingToStart.performOneTimeMediaMuxerCreation(muxerOutputFormat,
                         uri -> mOutputUri = uri);
             } catch (IOException e) {
@@ -2143,6 +2231,23 @@
         mAudioState = audioState;
     }
 
+    private static int supportedMuxerFormatOrDefaultFrom(
+            @Nullable CamcorderProfileProxy profileProxy, int defaultMuxerFormat) {
+        if (profileProxy != null) {
+            switch (profileProxy.getFileFormat()) {
+                case MediaRecorder.OutputFormat.MPEG_4:
+                    return MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
+                case MediaRecorder.OutputFormat.WEBM:
+                    return MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
+                case MediaRecorder.OutputFormat.THREE_GPP:
+                    return MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP;
+                default:
+                    break;
+            }
+        }
+        return defaultMuxerFormat;
+    }
+
     @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     @AutoValue
     abstract static class RecordingRecord implements AutoCloseable {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
index 65626a4..4ed6cdd 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapabilities.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.video;
 
+import android.util.Size;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -26,6 +28,7 @@
 import androidx.camera.core.impl.CamcorderProfileProvider;
 import androidx.camera.core.impl.CamcorderProfileProxy;
 import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.utils.CompareSizesByArea;
 import androidx.camera.video.internal.compat.quirk.DeviceQuirks;
 import androidx.camera.video.internal.compat.quirk.VideoQualityNotSupportQuirk;
 import androidx.core.util.Preconditions;
@@ -36,6 +39,7 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * VideoCapabilities is used to query video recording capabilities on the device.
@@ -53,7 +57,9 @@
      * The supported @link CamcorderProfileProxy} map from quality to CamcorderProfileProxy. The
      * order is from size large to small.
      */
-    private final Map<Integer, CamcorderProfileProxy> mSupportedProfileMap = new LinkedHashMap<>();
+    private final Map<Quality, CamcorderProfileProxy> mSupportedProfileMap = new LinkedHashMap<>();
+    private final TreeMap<Size, Quality> mAreaSortedSizeToQualityMap =
+            new TreeMap<>(new CompareSizesByArea());
     private final CamcorderProfileProxy mHighestProfile;
     private final CamcorderProfileProxy mLowestProfile;
 
@@ -69,16 +75,24 @@
                 cameraInfoInternal.getCamcorderProfileProvider();
 
         // Construct supported profile map
-        for (@QualitySelector.VideoQuality int quality : QualitySelector.getSortedQualities()) {
+        for (Quality quality : Quality.getSortedQualities()) {
             // SortedQualities is from size large to small
+            Preconditions.checkState(quality instanceof Quality.ConstantQuality,
+                    "Currently only support ConstantQuality");
+            int qualityValue = ((Quality.ConstantQuality) quality).getValue();
 
             // Get CamcorderProfile
-            if (!camcorderProfileProvider.hasProfile(quality) || !isDeviceValidQuality(quality)) {
+            if (!camcorderProfileProvider.hasProfile(qualityValue) || !isDeviceValidQuality(
+                    quality)) {
                 continue;
             }
-            CamcorderProfileProxy profile = camcorderProfileProvider.get(quality);
+            CamcorderProfileProxy profile =
+                    Preconditions.checkNotNull(camcorderProfileProvider.get(qualityValue));
+            Size profileSize = new Size(profile.getVideoFrameWidth(),
+                    profile.getVideoFrameHeight());
             Logger.d(TAG, "profile = " + profile);
             mSupportedProfileMap.put(quality, profile);
+            mAreaSortedSizeToQualityMap.put(profileSize, quality);
         }
         if (mSupportedProfileMap.isEmpty()) {
             Logger.e(TAG, "No supported CamcorderProfile");
@@ -102,14 +116,13 @@
      * Gets all supported qualities on the device.
      *
      * <p>The returned list is sorted by quality size from large to small. For the qualities in
-     * the returned list, calling {@link #getProfile(int)} with these qualities will return a
+     * the returned list, calling {@link #getProfile(Quality)} with these qualities will return a
      * non-null result.
      *
-     * <p>Note: Constants {@link QualitySelector#QUALITY_HIGHEST} and
-     * {@link QualitySelector#QUALITY_LOWEST} are not included.
+     * <p>Note: Constants {@link Quality#HIGHEST} and {@link Quality#LOWEST} are not included.
      */
     @NonNull
-    public List<Integer> getSupportedQualities() {
+    public List<Quality> getSupportedQualities() {
         return new ArrayList<>(mSupportedProfileMap.keySet());
     }
 
@@ -117,13 +130,12 @@
      * Checks if the quality is supported.
      *
      * @param quality one of the quality constants. Possible values include
-     * {@link QualitySelector#QUALITY_LOWEST}, {@link QualitySelector#QUALITY_HIGHEST},
-     * {@link QualitySelector#QUALITY_SD}, {@link QualitySelector#QUALITY_HD},
-     * {@link QualitySelector#QUALITY_FHD}, or {@link QualitySelector#QUALITY_UHD}.
+     * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link {@link Quality#SD},
+     * {@link Quality#HD}, {@link {@link Quality#FHD}, or {@link Quality#UHD}.
      * @return {@code true} if the quality is supported; {@code false} otherwise.
      * @throws IllegalArgumentException if not a quality constant.
      */
-    public boolean isQualitySupported(@QualitySelector.VideoQuality int quality) {
+    public boolean isQualitySupported(@NonNull Quality quality) {
         checkQualityConstantsOrThrow(quality);
         return getProfile(quality) != null;
     }
@@ -132,29 +144,60 @@
      * Gets the corresponding {@link CamcorderProfileProxy} of the input quality.
      *
      * @param quality one of the quality constants. Possible values include
-     * {@link QualitySelector#QUALITY_LOWEST}, {@link QualitySelector#QUALITY_HIGHEST},
-     * {@link QualitySelector#QUALITY_SD}, {@link QualitySelector#QUALITY_HD},
-     * {@link QualitySelector#QUALITY_FHD}, or {@link QualitySelector#QUALITY_UHD}.
+     * {@link Quality#LOWEST}, {@link Quality#HIGHEST}, {@link Quality#SD}, {@link Quality#HD},
+     * {@link Quality#FHD}, or {@link Quality#UHD}.
      * @return the CamcorderProfileProxy
      * @throws IllegalArgumentException if not a quality constant
      */
     @Nullable
-    public CamcorderProfileProxy getProfile(@QualitySelector.VideoQuality int quality) {
+    public CamcorderProfileProxy getProfile(@NonNull Quality quality) {
         checkQualityConstantsOrThrow(quality);
-        if (quality == QualitySelector.QUALITY_HIGHEST) {
+        if (quality == Quality.HIGHEST) {
             return mHighestProfile;
-        } else if (quality == QualitySelector.QUALITY_LOWEST) {
+        } else if (quality == Quality.LOWEST) {
             return mLowestProfile;
         }
         return mSupportedProfileMap.get(quality);
     }
 
-    private static void checkQualityConstantsOrThrow(@QualitySelector.VideoQuality int quality) {
-        Preconditions.checkArgument(QualitySelector.containsQuality(quality),
+    /**
+     * Finds the nearest quality by number of pixels to the given {@link Size}.
+     *
+     * <p>If the size aligns exactly with the pixel count of a supported quality, that quality
+     * will be selected. If the size falls between two qualities, the higher quality will always
+     * be selected. Otherwise, the nearest single quality will be selected, whether that
+     * quality's size is above or below the given size.
+     * @param size The size representing the number of pixels for comparison. Pixels are assumed
+     *             to be square.
+     * @return The quality constant defined in {@link Quality}. If no qualities are supported,
+     * then {@link Quality#NONE} is returned.
+     */
+    @NonNull
+    public Quality findHighestSupportedQualityFor(@NonNull Size size) {
+        Map.Entry<Size, Quality> ceilEntry = mAreaSortedSizeToQualityMap.ceilingEntry(size);
+
+        if (ceilEntry != null) {
+            // The ceiling entry will either be equivalent or higher in size, so always return it.
+            return ceilEntry.getValue();
+        } else {
+            // If a ceiling entry doesn't exist and a floor entry exists, it is the closest we have,
+            // so return it.
+            Map.Entry<Size, Quality> floorEntry = mAreaSortedSizeToQualityMap.floorEntry(size);
+            if (floorEntry != null) {
+                return floorEntry.getValue();
+            }
+        }
+
+        // No supported qualities.
+        return Quality.NONE;
+    }
+
+    private static void checkQualityConstantsOrThrow(@NonNull Quality quality) {
+        Preconditions.checkArgument(Quality.containsQuality(quality),
                 "Unknown quality: " + quality);
     }
 
-    private boolean isDeviceValidQuality(@QualitySelector.VideoQuality int quality) {
+    private boolean isDeviceValidQuality(@NonNull Quality quality) {
         VideoQualityNotSupportQuirk quirk = DeviceQuirks.get(VideoQualityNotSupportQuirk.class);
         return quirk == null || !quirk.isProblematicVideoQuality(quality);
     }
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
index 09c594c..08d13bf 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCapture.java
@@ -511,10 +511,10 @@
         Preconditions.checkArgument(mediaSpec != null,
                 "Unable to update target resolution by null MediaSpec.");
 
-        List<Integer> supportedQualities = QualitySelector.getSupportedQualities(cameraInfo);
+        List<Quality> supportedQualities = QualitySelector.getSupportedQualities(cameraInfo);
         if (supportedQualities.isEmpty()) {
             // When the device does not have any supported quality, even the most flexible
-            // QualitySelector such as QualitySelector.of(QUALITY_HIGHEST), still cannot
+            // QualitySelector such as QualitySelector.from(Quality.HIGHEST), still cannot
             // find any resolution. This should be a rare case but will cause VideoCapture
             // to always fail to bind. The workaround is not set any resolution and leave it to
             // auto resolution mechanism.
@@ -524,7 +524,7 @@
 
         QualitySelector qualitySelector = mediaSpec.getVideoSpec().getQualitySelector();
 
-        List<Integer> selectedQualities = qualitySelector.getPrioritizedQualities(cameraInfo);
+        List<Quality> selectedQualities = qualitySelector.getPrioritizedQualities(cameraInfo);
 
         Logger.d(TAG,
                 "Found selectedQualities " + selectedQualities + " by " + qualitySelector);
@@ -535,7 +535,7 @@
         }
 
         List<Size> supportedResolutions = new ArrayList<>();
-        for (Integer selectedQuality : selectedQualities) {
+        for (Quality selectedQuality : selectedQualities) {
             supportedResolutions.add(QualitySelector.getResolution(cameraInfo, selectedQuality));
         }
         Logger.d(TAG, "Set supported resolutions = " + supportedResolutions);
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoSpec.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoSpec.java
index a1efbe28..94f15ac 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoSpec.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoSpec.java
@@ -16,11 +16,6 @@
 
 package androidx.camera.video;
 
-import static androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_HIGHER;
-import static androidx.camera.video.QualitySelector.QUALITY_FHD;
-import static androidx.camera.video.QualitySelector.QUALITY_HD;
-import static androidx.camera.video.QualitySelector.QUALITY_SD;
-
 import android.util.Range;
 
 import androidx.annotation.IntDef;
@@ -33,6 +28,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 
 /**
  * Video specification that is options to config video encoding.
@@ -71,10 +67,8 @@
      */
     @NonNull
     public static final QualitySelector QUALITY_SELECTOR_AUTO =
-            QualitySelector.firstTry(QUALITY_FHD)
-                    .thenTry(QUALITY_HD)
-                    .thenTry(QUALITY_SD)
-                    .finallyTry(QUALITY_FHD, FALLBACK_STRATEGY_HIGHER);
+            QualitySelector.fromOrderedList(Arrays.asList(Quality.FHD, Quality.HD, Quality.SD),
+                    FallbackStrategy.higherQualityOrLowerThan(Quality.FHD));
 
     /**
      * The aspect ratio representing no preference for aspect ratio.
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
index 6a6dd23..99d899c 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
@@ -21,6 +21,7 @@
 import static androidx.camera.video.internal.AudioSource.InternalState.STARTED;
 
 import android.Manifest;
+import android.annotation.SuppressLint;
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioRecord;
@@ -28,6 +29,7 @@
 import android.media.AudioTimestamp;
 import android.os.Build;
 
+import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -43,6 +45,8 @@
 import androidx.camera.video.internal.encoder.InputBuffer;
 import androidx.core.util.Preconditions;
 
+import com.google.auto.value.AutoValue;
+
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collections;
@@ -55,7 +59,7 @@
  * AudioSource is used to obtain audio raw data and write to the buffer from {@link BufferProvider}.
  *
  * <p>The audio raw data could be one of sources from the device. The target source can be
- * specified with {@link Builder#setAudioSource(int)}.
+ * specified with {@link Settings.Builder#setAudioSource(int)}.
  *
  * <p>Calling {@link #start} will start reading audio data from the target source and then write
  * the data into the buffer from {@link BufferProvider}. Calling {@link #stop} will stop sending
@@ -87,8 +91,6 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     final Executor mExecutor;
 
-    private final BufferProvider<InputBuffer> mBufferProvider;
-
     private AudioManager.AudioRecordingCallback mAudioRecordingCallback;
 
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
@@ -115,28 +117,50 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     AudioSourceCallback mAudioSourceCallback;
 
+    // The following should only be accessed by mExecutor
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
+    BufferProvider<InputBuffer> mBufferProvider;
+    private FutureCallback<InputBuffer> mAcquireBufferCallback;
+    private Observable.Observer<BufferProvider.State> mStateObserver;
+
+
+    /**
+     * Creates an AudioSource for the given settings.
+     *
+     * <p>It should be verified the combination of sample rate, channel count and audio format is
+     * supported with {@link #isSettingsSupported(int, int, int)} before passing the settings to
+     * this constructor, or an {@link UnsupportedOperationException} will be thrown.
+     *
+     * @throws UnsupportedOperationException if the combination of sample rate, channel count,
+     * and audio format in the provided settings is unsupported.
+     * @throws AudioSourceAccessException if the audio device is not available or cannot be
+     * initialized with the given settings.
+     */
     @RequiresPermission(Manifest.permission.RECORD_AUDIO)
-    AudioSource(@NonNull Executor executor,
-            @NonNull BufferProvider<InputBuffer> bufferProvider,
-            int audioSource,
-            int sampleRate,
-            int channelCount,
-            int audioFormat)
+    public AudioSource(@NonNull Settings settings, @NonNull Executor executor)
             throws AudioSourceAccessException {
-        int minBufferSize = getMinBufferSize(sampleRate, channelCount, audioFormat);
+        if (!isSettingsSupported(settings.getSampleRate(), settings.getChannelCount(),
+                settings.getAudioFormat())) {
+            throw new UnsupportedOperationException(String.format(
+                    "The combination of sample rate %d, channel count %d and audio format"
+                            + " %d is not supported.",
+                    settings.getSampleRate(), settings.getChannelCount(),
+                    settings.getAudioFormat()));
+        }
+
+        int minBufferSize = getMinBufferSize(settings.getSampleRate(), settings.getChannelCount(),
+                settings.getAudioFormat());
         // The minBufferSize should be a positive value since the settings had already been checked
         // by the isSettingsSupported().
         Preconditions.checkState(minBufferSize > 0);
 
         mExecutor = CameraXExecutors.newSequentialExecutor(executor);
-        mBufferProvider = bufferProvider;
         mBufferSize = minBufferSize * 2;
         try {
-            mAudioRecord = new AudioRecord(audioSource,
-                    sampleRate,
-                    channelCountToChannelConfig(channelCount),
-                    audioFormat,
+            mAudioRecord = new AudioRecord(settings.getAudioSource(),
+                    settings.getSampleRate(),
+                    channelCountToChannelConfig(settings.getChannelCount()),
+                    settings.getAudioFormat(),
                     mBufferSize);
         } catch (IllegalArgumentException e) {
             throw new AudioSourceAccessException("Unable to create AudioRecord", e);
@@ -152,8 +176,6 @@
             Api29Impl.registerAudioRecordingCallback(mAudioRecord, mExecutor,
                     mAudioRecordingCallback);
         }
-
-        mBufferProvider.addObserver(mExecutor, mStateObserver);
     }
 
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
@@ -178,9 +200,38 @@
         }
     }
 
+
+    /**
+     * Sets the {@link BufferProvider}.
+     *
+     * <p>A buffer provider is required to stream audio. If no buffer provider is provided, then
+     * audio will be dropped until one is provided and active.
+     *
+     * @param bufferProvider The new buffer provider to use.
+     */
+    public void setBufferProvider(@NonNull BufferProvider<InputBuffer> bufferProvider) {
+        mExecutor.execute(() -> {
+            switch (mState) {
+                case CONFIGURED:
+                    // Fall-through
+                case STARTED:
+                    if (mBufferProvider != bufferProvider) {
+                        resetBufferProvider(bufferProvider);
+                    }
+                    break;
+                case RELEASED:
+                    throw new IllegalStateException("AudioRecorder is released");
+            }
+        });
+    }
+
     /**
      * Starts the AudioSource.
      *
+     * <p>Before starting, a {@link BufferProvider} should be set with
+     * {@link #setBufferProvider(BufferProvider)}. If a buffer provider is not set, audio data
+     * will be dropped.
+     *
      * <p>Audio data will start being sent to the {@link BufferProvider} when
      * {@link BufferProvider}'s state is {@link BufferProvider.State#ACTIVE}.
      *
@@ -236,7 +287,7 @@
                 case STARTED:
                     // Fall-through
                 case CONFIGURED:
-                    mBufferProvider.removeObserver(mStateObserver);
+                    resetBufferProvider(null);
                     if (Build.VERSION.SDK_INT >= 29) {
                         Api29Impl.unregisterAudioRecordingCallback(mAudioRecord,
                                 mAudioRecordingCallback);
@@ -277,6 +328,75 @@
         });
     }
 
+    @ExecutedBy("mExecutor")
+    private void resetBufferProvider(@Nullable BufferProvider<InputBuffer> bufferProvider) {
+        if (mBufferProvider != null) {
+            mBufferProvider.removeObserver(mStateObserver);
+            mBufferProvider = null;
+            mStateObserver = null;
+            mAcquireBufferCallback = null;
+        }
+        mBufferProviderState = BufferProvider.State.INACTIVE;
+        updateSendingAudio();
+        if (bufferProvider != null) {
+            mBufferProvider = bufferProvider;
+            mStateObserver = new Observable.Observer<BufferProvider.State>() {
+                @ExecutedBy("mExecutor")
+                @Override
+                public void onNewData(@Nullable BufferProvider.State state) {
+                    if (mBufferProvider == bufferProvider) {
+                        Logger.d(TAG, "Receive BufferProvider state change: "
+                                + mBufferProviderState + " to " + state);
+                        mBufferProviderState = state;
+                        updateSendingAudio();
+                    }
+                }
+
+                @ExecutedBy("mExecutor")
+                @Override
+                public void onError(@NonNull Throwable throwable) {
+                    if (mBufferProvider == bufferProvider) {
+                        notifyError(throwable);
+                    }
+                }
+            };
+
+            mAcquireBufferCallback = new FutureCallback<InputBuffer>() {
+                @ExecutedBy("mExecutor")
+                @Override
+                public void onSuccess(InputBuffer inputBuffer) {
+                    if (!mIsSendingAudio || mBufferProvider != bufferProvider) {
+                        inputBuffer.cancel();
+                        return;
+                    }
+                    ByteBuffer byteBuffer = inputBuffer.getByteBuffer();
+
+                    int length = mAudioRecord.read(byteBuffer, mBufferSize);
+                    if (length > 0) {
+                        byteBuffer.limit(length);
+                        inputBuffer.setPresentationTimeUs(generatePresentationTimeUs());
+                        inputBuffer.submit();
+                    } else {
+                        Logger.w(TAG, "Unable to read data from AudioRecord.");
+                        inputBuffer.cancel();
+                    }
+                    sendNextAudio();
+                }
+
+                @ExecutedBy("mExecutor")
+                @Override
+                public void onFailure(Throwable throwable) {
+                    if (mBufferProvider != bufferProvider) {
+                        Logger.d(TAG, "Unable to get input buffer, the BufferProvider "
+                                + "could be transitioning to INACTIVE state.");
+                        notifyError(throwable);
+                    }
+                }
+            };
+            mBufferProvider.addObserver(mExecutor, mStateObserver);
+        }
+    }
+
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     void notifyError(Throwable throwable) {
         if (mCallbackExecutor != null && mAudioSourceCallback != null) {
@@ -368,56 +488,6 @@
         return presentationTimeUs;
     }
 
-    private final FutureCallback<InputBuffer> mAcquireBufferCallback =
-            new FutureCallback<InputBuffer>() {
-                @ExecutedBy("mExecutor")
-                @Override
-                public void onSuccess(InputBuffer inputBuffer) {
-                    if (!mIsSendingAudio) {
-                        inputBuffer.cancel();
-                        return;
-                    }
-                    ByteBuffer byteBuffer = inputBuffer.getByteBuffer();
-
-                    int length = mAudioRecord.read(byteBuffer, mBufferSize);
-                    if (length > 0) {
-                        byteBuffer.limit(length);
-                        inputBuffer.setPresentationTimeUs(generatePresentationTimeUs());
-                        inputBuffer.submit();
-                    } else {
-                        Logger.w(TAG, "Unable to read data from AudioRecord.");
-                        inputBuffer.cancel();
-                    }
-                    sendNextAudio();
-                }
-
-                @ExecutedBy("mExecutor")
-                @Override
-                public void onFailure(Throwable throwable) {
-                    Logger.d(TAG, "Unable to get input buffer, the BufferProvider "
-                            + "could be transitioning to INACTIVE state.");
-                    notifyError(throwable);
-                }
-            };
-
-    private final Observable.Observer<BufferProvider.State> mStateObserver =
-            new Observable.Observer<BufferProvider.State>() {
-                @ExecutedBy("mExecutor")
-                @Override
-                public void onNewData(@Nullable BufferProvider.State state) {
-                    Logger.d(TAG, "Receive BufferProvider state change: "
-                            + mBufferProviderState + " to " + state);
-                    mBufferProviderState = state;
-                    updateSendingAudio();
-                }
-
-                @ExecutedBy("mExecutor")
-                @Override
-                public void onError(@NonNull Throwable throwable) {
-                    notifyError(throwable);
-                }
-            };
-
     /** Check if the combination of sample rate, channel count and audio format is supported. */
     public static boolean isSettingsSupported(int sampleRate, int channelCount, int audioFormat) {
         if (sampleRate <= 0 || channelCount <= 0) {
@@ -436,124 +506,133 @@
     }
 
     /**
-     * The builder of the AudioSource.
+     * Settings required to configure the audio source.
      */
-    public static class Builder {
-        private Executor mExecutor;
-        private int mAudioSource = -1;
-        private int mSampleRate = -1;
-        private int mChannelCount = -1;
-        private int mAudioFormat = -1;
-        private BufferProvider<InputBuffer> mBufferProvider;
+    @AutoValue
+    public abstract static class Settings {
 
-        /** Sets the executor to run the background task. */
+        /** Creates a builder for these settings. */
+        @SuppressLint("Range") // Need to initialize as invalid values
         @NonNull
-        public Builder setExecutor(@NonNull Executor executor) {
-            mExecutor = Preconditions.checkNotNull(executor);
-            return this;
+        public static Settings.Builder builder() {
+            return new AutoValue_AudioSource_Settings.Builder()
+                    .setAudioSource(-1)
+                    .setSampleRate(-1)
+                    .setChannelCount(-1)
+                    .setAudioFormat(-1);
         }
 
+        /** Creates a {@link Builder} initialized with the same settings as this instance. */
+        @NonNull
+        public abstract Builder toBuilder();
+
         /**
-         * Sets the device audio source.
+         * Gets the device audio source.
          *
          * @see android.media.MediaRecorder.AudioSource#MIC
          * @see android.media.MediaRecorder.AudioSource#CAMCORDER
          */
-        @NonNull
-        public Builder setAudioSource(int audioSource) {
-            mAudioSource = audioSource;
-            return this;
-        }
+        public abstract int getAudioSource();
 
         /**
-         * Sets the audio sample rate.
-         *
-         * <p>It has to ensure the combination of sample rate, channel count and audio format is
-         * supported by {@link AudioSource#isSettingsSupported(int, int, int)}.
-         *
-         * @throws IllegalArgumentException if the sample rate is not positive.
+         * Gets the audio sample rate.
          */
-        @NonNull
-        public Builder setSampleRate(int sampleRate) {
-            Preconditions.checkArgument(sampleRate > 0);
-            mSampleRate = sampleRate;
-            return this;
-        }
+        @IntRange(from = 1)
+        public abstract int getSampleRate();
 
         /**
-         * Sets the channel count.
-         *
-         * <p>It has to ensure the combination of sample rate, channel count and audio format is
-         * supported by {@link AudioSource#isSettingsSupported(int, int, int)}.
-         *
-         * @throws IllegalArgumentException if the channel count is not positive.
+         * Gets the channel count.
          */
-        @NonNull
-        public Builder setChannelCount(int channelCount) {
-            Preconditions.checkArgument(channelCount > 0);
-            mChannelCount = channelCount;
-            return this;
-        }
+        @IntRange(from = 1)
+        public abstract int getChannelCount();
 
         /**
          * Sets the audio format.
          *
-         * <p>It has to ensure the combination of sample rate, channel count and audio format is
-         * supported by {@link AudioSource#isSettingsSupported(int, int, int)}.
-         *
          * @see AudioFormat#ENCODING_PCM_16BIT
          */
-        @NonNull
-        public Builder setAudioFormat(int audioFormat) {
-            mAudioFormat = audioFormat;
-            return this;
+        public abstract int getAudioFormat();
+
+        // Should not be instantiated directly
+        Settings() {
         }
 
-        /** Sets the {@link BufferProvider}. */
-        @NonNull
-        public Builder setBufferProvider(@NonNull BufferProvider<InputBuffer> bufferProvider) {
-            mBufferProvider = Preconditions.checkNotNull(bufferProvider);
-            return this;
-        }
+        /**
+         * A Builder for {@link AudioSource.Settings}
+         */
+        @AutoValue.Builder
+        public abstract static class Builder {
+            /**
+             * Sets the device audio source.
+             *
+             * @see android.media.MediaRecorder.AudioSource#MIC
+             * @see android.media.MediaRecorder.AudioSource#CAMCORDER
+             */
+            @NonNull
+            public abstract Builder setAudioSource(int audioSource);
 
-        /** Build the AudioSource. */
-        @RequiresPermission(Manifest.permission.RECORD_AUDIO)
-        @NonNull
-        public AudioSource build() throws AudioSourceAccessException {
-            String missing = "";
-            if (mExecutor == null) {
-                missing += " executor";
+            /**
+             * Sets the audio sample rate in Hertz.
+             */
+            @NonNull
+            public abstract Builder setSampleRate(@IntRange(from = 1) int sampleRate);
+
+            /**
+             * Sets the channel count.
+             */
+            @NonNull
+            public abstract Builder setChannelCount(@IntRange(from = 1) int channelCount);
+
+            /**
+             * Sets the audio format.
+             *
+             * @see AudioFormat#ENCODING_PCM_16BIT
+             */
+            @NonNull
+            public abstract Builder setAudioFormat(int audioFormat);
+
+            abstract Settings autoBuild(); // Actual build method. Not public.
+
+            /**
+             * Returns the built config after performing settings validation.
+             *
+             * <p>It should be verified that combination of sample rate, channel count and audio
+             * format is supported by {@link AudioSource#isSettingsSupported(int, int, int)} or
+             * an {@link UnsupportedOperationException} will be thrown when passing the settings
+             * to the
+             * {@linkplain AudioSource#AudioSource(Settings, Executor) AudioSource
+             * constructor}.
+             *
+             * @throws IllegalArgumentException if a setting is missing or invalid.
+             */
+            @NonNull
+            public final Settings build() {
+                Settings settings = autoBuild();
+                String missingOrInvalid = "";
+                if (settings.getAudioSource() == -1) {
+                    missingOrInvalid += " audioSource";
+                }
+                if (settings.getSampleRate() <= 0) {
+                    missingOrInvalid += " sampleRate";
+                }
+                if (settings.getChannelCount() <= 0) {
+                    missingOrInvalid += " channelCount";
+                }
+                if (settings.getAudioFormat() == -1) {
+                    missingOrInvalid += " audioFormat";
+                }
+
+                if (!missingOrInvalid.isEmpty()) {
+                    throw new IllegalArgumentException("Required settings missing or "
+                            + "non-positive:" + missingOrInvalid);
+                }
+
+                return settings;
             }
-            if (mBufferProvider == null) {
-                missing += " bufferProvider";
+
+            // Should not be instantiated directly
+            Builder() {
             }
-            if (mAudioSource == -1) {
-                missing += " audioSource";
-            }
-            if (mSampleRate == -1) {
-                missing += " sampleRate";
-            }
-            if (mChannelCount == -1) {
-                missing += " channelCount";
-            }
-            if (mAudioFormat == -1) {
-                missing += " audioFormat";
-            }
-            if (!missing.isEmpty()) {
-                throw new IllegalStateException("Missing required properties:" + missing);
-            }
-            if (!isSettingsSupported(mSampleRate, mChannelCount, mAudioFormat)) {
-                throw new IllegalStateException(String.format("The combination of sample rate %d "
-                                + ", channel count %d and audio format %d is not supported.",
-                        mSampleRate, mChannelCount, mAudioFormat));
-            }
-            return new AudioSource(mExecutor,
-                    mBufferProvider,
-                    mAudioSource,
-                    mSampleRate,
-                    mChannelCount,
-                    mAudioFormat
-            );
         }
     }
 
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/VideoQualityNotSupportQuirk.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/VideoQualityNotSupportQuirk.java
index 5d461ba..a307aa0 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/VideoQualityNotSupportQuirk.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/compat/quirk/VideoQualityNotSupportQuirk.java
@@ -20,10 +20,11 @@
 import android.media.MediaRecorder.VideoEncoder;
 import android.os.Build;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.camera.core.impl.CamcorderProfileProvider;
 import androidx.camera.core.impl.Quirk;
-import androidx.camera.video.QualitySelector;
+import androidx.camera.video.Quality;
 import androidx.camera.video.VideoCapabilities;
 
 /**
@@ -52,7 +53,7 @@
     }
 
     /** Checks if the given mime type is a problematic quality. */
-    public boolean isProblematicVideoQuality(@QualitySelector.VideoQuality int quality) {
-        return quality == QualitySelector.QUALITY_UHD;
+    public boolean isProblematicVideoQuality(@NonNull Quality quality) {
+        return quality == Quality.UHD;
     }
 }
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java
new file mode 100644
index 0000000..f388b3b
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioConfigUtil.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+import android.util.Rational;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.video.AudioSpec;
+import androidx.camera.video.internal.AudioSource;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A collection of utilities used for resolving and debugging audio configurations.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class AudioConfigUtil {
+    private static final String TAG = "AudioConfigUtil";
+
+    // Default to 44100 for now as it's guaranteed supported on devices.
+    static final int AUDIO_SAMPLE_RATE_DEFAULT = 44100;
+    // Default to mono since that should be supported on the most devices.
+    static final int AUDIO_CHANNEL_COUNT_DEFAULT = AudioSpec.CHANNEL_COUNT_MONO;
+    // Defaults to PCM_16BIT as it's guaranteed supported on devices.
+    static final int AUDIO_SOURCE_FORMAT_DEFAULT = AudioSpec.SOURCE_FORMAT_PCM_16BIT;
+    // Defaults to Camcorder as this should be the source closest to the camera
+    static final int AUDIO_SOURCE_DEFAULT = AudioSpec.SOURCE_CAMCORDER;
+
+    // Should not be instantiated.
+    private AudioConfigUtil() {
+    }
+
+    static int resolveAudioSource(@NonNull AudioSpec audioSpec) {
+        int resolvedAudioSource = audioSpec.getSource();
+        if (resolvedAudioSource == AudioSpec.SOURCE_AUTO) {
+            resolvedAudioSource = AUDIO_SOURCE_DEFAULT;
+            Logger.d(TAG, "Using default AUDIO source: " + resolvedAudioSource);
+        } else {
+            Logger.d(TAG, "Using provided AUDIO source: " + resolvedAudioSource);
+        }
+
+        return resolvedAudioSource;
+    }
+
+    static int resolveAudioSourceFormat(@NonNull AudioSpec audioSpec) {
+        int resolvedAudioSourceFormat = audioSpec.getSourceFormat();
+        if (resolvedAudioSourceFormat == AudioSpec.SOURCE_FORMAT_AUTO) {
+            // TODO: This should come from a priority list and may need to be combined with
+            //  AudioSource.isSettingsSupported.
+            resolvedAudioSourceFormat = AUDIO_SOURCE_FORMAT_DEFAULT;
+            Logger.d(TAG, "Using default AUDIO source format: " + resolvedAudioSourceFormat);
+        } else {
+            Logger.d(
+                    TAG, "Using provided AUDIO source format: " + resolvedAudioSourceFormat);
+        }
+
+        return resolvedAudioSourceFormat;
+    }
+
+    static int selectSampleRateOrNearestSupported(@NonNull Range<Integer> targetRange,
+            int channelCount, int sourceFormat, int initialTargetSampleRate) {
+        int selectedSampleRate = initialTargetSampleRate;
+        // Sample rates sorted by proximity to initial target.
+        List<Integer> sortedCommonSampleRates = null;
+        int i = 0;
+        do {
+            if (targetRange.contains(selectedSampleRate)) {
+                if (AudioSource.isSettingsSupported(selectedSampleRate, channelCount,
+                        sourceFormat)) {
+                    return selectedSampleRate;
+                } else {
+                    Logger.d(TAG, "Sample rate " + selectedSampleRate + "Hz is not supported by "
+                            + "audio source with channel count " + channelCount + " and source "
+                            + "format " + sourceFormat);
+                }
+            } else {
+                Logger.d(TAG, "Sample rate " + selectedSampleRate + "Hz is not in target range "
+                        + targetRange);
+            }
+
+            // If the initial target isn't supported, sort the array of published common sample
+            // rates by closeness to target  and step through until we've found one that is
+            // supported.
+            if (sortedCommonSampleRates == null) {
+                Logger.d(TAG,
+                        "Trying common sample rates in proximity order to target "
+                                + initialTargetSampleRate + "Hz");
+                sortedCommonSampleRates = new ArrayList<>(AudioSource.COMMON_SAMPLE_RATES);
+                Collections.sort(sortedCommonSampleRates, (x, y) -> {
+                    int relativeDifference = Math.abs(x - initialTargetSampleRate) - Math.abs(
+                            y - initialTargetSampleRate);
+                    // If the relative difference is zero, i.e., the target is halfway
+                    // between the two, always prefer the larger sample rate for quality.
+                    if (relativeDifference == 0) {
+                        return (int) Math.signum(x - y);
+                    }
+
+                    return (int) Math.signum(relativeDifference);
+                });
+            }
+
+            if (i < sortedCommonSampleRates.size()) {
+                selectedSampleRate = sortedCommonSampleRates.get(i++);
+            } else {
+                break;
+            }
+        } while (true);
+
+        // No supported sample rate found. The default sample rate should work on most devices. May
+        // consider throw an exception or have other way to notify users that the specified
+        // sample rate can not be satisfied.
+        Logger.d(TAG, "No sample rate found in target range or supported by audio source. Falling"
+                + " back to default sample rate of " + AUDIO_SAMPLE_RATE_DEFAULT + "Hz");
+        return AUDIO_SAMPLE_RATE_DEFAULT;
+    }
+
+    static int scaleAndClampBitrate(int baseBitrate,
+            int actualChannelCount, int baseChannelCount,
+            int actualSampleRate, int baseSampleRate,
+            Range<Integer> clampedRange) {
+        // Scale bitrate based on source number of channels relative to base channel count.
+        Rational channelCountRatio = new Rational(actualChannelCount, baseChannelCount);
+        // Scale bitrate based on source sample rate relative to profile sample rate.
+        Rational sampleRateRatio = new Rational(actualSampleRate, baseSampleRate);
+
+        int resolvedBitrate = (int) (baseBitrate * channelCountRatio.doubleValue()
+                * sampleRateRatio.doubleValue());
+
+        String debugString = "";
+        if (Logger.isDebugEnabled(TAG)) {
+            debugString = String.format("Base Bitrate(%dbps) * Channel Count Ratio(%d / %d) * "
+                            + "Sample Rate Ratio(%d / %d) = %d", baseBitrate, actualChannelCount,
+                    baseChannelCount, actualSampleRate, baseSampleRate, resolvedBitrate);
+        }
+
+        if (!AudioSpec.BITRATE_RANGE_AUTO.equals(clampedRange)) {
+            resolvedBitrate = clampedRange.clamp(resolvedBitrate);
+            if (Logger.isDebugEnabled(TAG)) {
+                debugString += String.format("\nClamped to range %s -> %dbps", clampedRange,
+                        resolvedBitrate);
+            }
+        }
+        Logger.d(TAG, debugString);
+        return resolvedBitrate;
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java
new file mode 100644
index 0000000..381510b5
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigCamcorderProfileResolver.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.video.AudioSpec;
+import androidx.camera.video.internal.AudioSource;
+import androidx.camera.video.internal.encoder.AudioEncoderConfig;
+import androidx.core.util.Supplier;
+
+/**
+ * An {@link AudioEncoderConfig} supplier that resolves requested encoder settings from an
+ * {@link AudioSpec} for the given {@link AudioSource.Settings} using the provided
+ * {@link CamcorderProfileProxy}.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class AudioEncoderConfigCamcorderProfileResolver implements
+        Supplier<AudioEncoderConfig> {
+
+    private static final String TAG = "AudioEncCmcrdrPrflRslvr";
+
+    private final String mMimeType;
+    private final int mAudioProfile;
+    private final AudioSpec mAudioSpec;
+    private final AudioSource.Settings mAudioSourceSettings;
+    private final CamcorderProfileProxy mCamcorderProfile;
+
+    /**
+     * Constructor for an AudioEncoderConfigCamcorderProfileResolver.
+     *
+     * @param mimeType            The mime type for the audio encoder
+     * @param audioProfile        The profile required for the audio encoder
+     * @param audioSpec           The {@link AudioSpec} which defines the settings that should be
+     *                            used with the audio encoder.
+     * @param audioSourceSettings The settings used to configure the source of audio.
+     * @param camcorderProfile    The {@link CamcorderProfileProxy} used to resolve automatic and
+     *                            range settings.
+     */
+    public AudioEncoderConfigCamcorderProfileResolver(@NonNull String mimeType,
+            int audioProfile, @NonNull AudioSpec audioSpec,
+            @NonNull AudioSource.Settings audioSourceSettings,
+            @NonNull CamcorderProfileProxy camcorderProfile) {
+        mMimeType = mimeType;
+        mAudioProfile = audioProfile;
+        mAudioSpec = audioSpec;
+        mAudioSourceSettings = audioSourceSettings;
+        mCamcorderProfile = camcorderProfile;
+    }
+
+    @Override
+    @NonNull
+    public AudioEncoderConfig get() {
+        Logger.d(TAG, "Using resolved AUDIO bitrate from CamcorderProfile");
+        Range<Integer> audioSpecBitrateRange = mAudioSpec.getBitrate();
+        int resolvedBitrate = AudioConfigUtil.scaleAndClampBitrate(
+                mCamcorderProfile.getAudioBitRate(),
+                mAudioSourceSettings.getChannelCount(), mCamcorderProfile.getAudioChannels(),
+                mAudioSourceSettings.getSampleRate(), mCamcorderProfile.getAudioSampleRate(),
+                audioSpecBitrateRange);
+
+        return AudioEncoderConfig.builder()
+                .setMimeType(mMimeType)
+                .setProfile(mAudioProfile)
+                .setChannelCount(mAudioSourceSettings.getChannelCount())
+                .setSampleRate(mAudioSourceSettings.getSampleRate())
+                .setBitrate(resolvedBitrate)
+                .build();
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolver.java
new file mode 100644
index 0000000..0b756a8
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioEncoderConfigDefaultResolver.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.video.AudioSpec;
+import androidx.camera.video.internal.AudioSource;
+import androidx.camera.video.internal.encoder.AudioEncoderConfig;
+import androidx.core.util.Supplier;
+
+/**
+ * An {@link AudioEncoderConfig} supplier that resolves requested encoder settings from a
+ * {@link AudioSpec} for the given {@link AudioSource.Settings} using pre-defined default values.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class AudioEncoderConfigDefaultResolver implements Supplier<AudioEncoderConfig> {
+
+    private static final String TAG = "AudioEncCfgDefaultRslvr";
+
+    private final String mMimeType;
+    private final int mAudioProfile;
+    private final AudioSpec mAudioSpec;
+    private final AudioSource.Settings mAudioSourceSettings;
+
+    // Base config based on generic 720p AAC(LC) quality will be scaled by actual source settings.
+    // TODO: These should vary based on quality/codec and be derived from actual devices
+    private static final int AUDIO_BITRATE_BASE = 156000;
+    private static final int AUDIO_CHANNEL_COUNT_BASE = 2;
+    private static final int AUDIO_SAMPLE_RATE_BASE = 48000;
+
+    /**
+     * Constructor for an AudioEncoderConfigDefaultResolver.
+     *
+     * @param mimeType            The mime type for the audio encoder
+     * @param audioProfile        The profile required for the audio encoder
+     * @param audioSpec           The {@link AudioSpec} which defines the settings that should be
+     *                            used with the audio encoder.
+     * @param audioSourceSettings The settings used to configure the source of audio.
+     */
+    public AudioEncoderConfigDefaultResolver(@NonNull String mimeType,
+            int audioProfile, @NonNull AudioSpec audioSpec,
+            @NonNull AudioSource.Settings audioSourceSettings) {
+        mMimeType = mimeType;
+        mAudioProfile = audioProfile;
+        mAudioSpec = audioSpec;
+        mAudioSourceSettings = audioSourceSettings;
+    }
+
+    @Override
+    @NonNull
+    public AudioEncoderConfig get() {
+        Range<Integer> audioSpecBitrateRange = mAudioSpec.getBitrate();
+        Logger.d(TAG, "Using fallback AUDIO bitrate");
+        // We have no other information to go off of. Scale based on fallback defaults.
+        int resolvedBitrate = AudioConfigUtil.scaleAndClampBitrate(
+                AUDIO_BITRATE_BASE,
+                mAudioSourceSettings.getChannelCount(), AUDIO_CHANNEL_COUNT_BASE,
+                mAudioSourceSettings.getSampleRate(), AUDIO_SAMPLE_RATE_BASE,
+                audioSpecBitrateRange);
+
+        return AudioEncoderConfig.builder()
+                .setMimeType(mMimeType)
+                .setProfile(mAudioProfile)
+                .setChannelCount(mAudioSourceSettings.getChannelCount())
+                .setSampleRate(mAudioSourceSettings.getSampleRate())
+                .setBitrate(resolvedBitrate)
+                .build();
+    }
+
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java
new file mode 100644
index 0000000..8d6de0f
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsCamcorderProfileResolver.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.video.AudioSpec;
+import androidx.camera.video.internal.AudioSource;
+import androidx.core.util.Supplier;
+
+/**
+ * An {@link AudioSource.Settings} supplier that resolves requested source settings from an
+ * {@link AudioSpec} using a {@link CamcorderProfileProxy}.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class AudioSourceSettingsCamcorderProfileResolver implements
+        Supplier<AudioSource.Settings> {
+
+    private static final String TAG = "AudioSrcCmcrdrPrflRslvr";
+
+    private final AudioSpec mAudioSpec;
+    private final CamcorderProfileProxy mCamcorderProfile;
+
+    /**
+     * Constructor for an AudioSourceSettingsCamcorderProfileResolver.
+     *
+     * @param camcorderProfile The {@link CamcorderProfileProxy} used to resolve automatic and
+     *                         range settings.
+     * @param audioSpec        The {@link AudioSpec} which defines the settings that should be
+     *                         used with the audio source.
+     */
+    public AudioSourceSettingsCamcorderProfileResolver(@NonNull AudioSpec audioSpec,
+            @NonNull CamcorderProfileProxy camcorderProfile) {
+        mAudioSpec = audioSpec;
+        mCamcorderProfile = camcorderProfile;
+    }
+
+    @Override
+    @NonNull
+    public AudioSource.Settings get() {
+        // Resolve audio source
+        int resolvedAudioSource = AudioConfigUtil.resolveAudioSource(mAudioSpec);
+
+        // Resolve source format
+        int resolvedSourceFormat = AudioConfigUtil.resolveAudioSourceFormat(
+                mAudioSpec);
+
+        int audioSpecChannelCount = mAudioSpec.getChannelCount();
+        Range<Integer> audioSpecSampleRate = mAudioSpec.getSampleRate();
+        int resolvedSampleRate;
+        int resolvedChannelCount;
+        int camcorderProfileChannelCount = mCamcorderProfile.getAudioChannels();
+        if (audioSpecChannelCount == AudioSpec.CHANNEL_COUNT_AUTO) {
+            resolvedChannelCount = camcorderProfileChannelCount;
+            Logger.d(TAG, "Resolved AUDIO channel count from CamcorderProfile: "
+                    + resolvedChannelCount);
+        } else {
+            resolvedChannelCount = audioSpecChannelCount;
+            Logger.d(TAG, "Media spec AUDIO channel count overrides CamcorderProfile "
+                    + "[CamcorderProfile channel count: " + camcorderProfileChannelCount
+                    + ", Resolved Channel Count: " + resolvedChannelCount + "]");
+        }
+
+        int camcorderProfileAudioSampleRate = mCamcorderProfile.getAudioSampleRate();
+        resolvedSampleRate = AudioConfigUtil.selectSampleRateOrNearestSupported(
+                audioSpecSampleRate, resolvedChannelCount, resolvedSourceFormat,
+                camcorderProfileAudioSampleRate);
+        Logger.d(TAG, "Using resolved AUDIO sample rate or nearest supported from "
+                + "CamcorderProfile: " + resolvedSampleRate + "Hz. [CamcorderProfile sample rate: "
+                + camcorderProfileAudioSampleRate + "Hz]");
+
+        return AudioSource.Settings.builder()
+                .setAudioSource(resolvedAudioSource)
+                .setAudioFormat(resolvedSourceFormat)
+                .setChannelCount(resolvedChannelCount)
+                .setSampleRate(resolvedSampleRate)
+                .build();
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolver.java
new file mode 100644
index 0000000..70fbad1
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/AudioSourceSettingsDefaultResolver.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.video.AudioSpec;
+import androidx.camera.video.internal.AudioSource;
+import androidx.core.util.Supplier;
+
+/**
+ * An {@link AudioSource.Settings} supplier that resolves requested source settings from an
+ * {@link AudioSpec} using pre-defined default values.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class AudioSourceSettingsDefaultResolver implements Supplier<AudioSource.Settings> {
+
+    private static final String TAG = "DefAudioSrcResolver";
+
+    private final AudioSpec mAudioSpec;
+
+    /**
+     * Constructor for an AudioSourceSettingsDefaultResolver.
+     *
+     * @param audioSpec The {@link AudioSpec} which defines the settings that should be used with
+     *                  the audio source.
+     */
+    public AudioSourceSettingsDefaultResolver(@NonNull AudioSpec audioSpec) {
+        mAudioSpec = audioSpec;
+    }
+
+    @Override
+    @NonNull
+    public AudioSource.Settings get() {
+        // Resolve audio source
+        int resolvedAudioSource = AudioConfigUtil.resolveAudioSource(mAudioSpec);
+
+        // Resolve source format
+        int resolvedSourceFormat = AudioConfigUtil.resolveAudioSourceFormat(mAudioSpec);
+
+        // Resolve channel count
+        int audioSpecChannelCount = mAudioSpec.getChannelCount();
+        int resolvedChannelCount;
+        if (audioSpecChannelCount == AudioSpec.CHANNEL_COUNT_AUTO) {
+            resolvedChannelCount = AudioConfigUtil.AUDIO_CHANNEL_COUNT_DEFAULT;
+            Logger.d(TAG, "Using fallback AUDIO channel count: " + resolvedChannelCount);
+        } else {
+            resolvedChannelCount = audioSpecChannelCount;
+            Logger.d(TAG, "Using supplied AUDIO channel count: " + audioSpecChannelCount);
+        }
+
+        // Resolve sample rate
+        Range<Integer> audioSpecSampleRateRange = mAudioSpec.getSampleRate();
+        int resolvedSampleRate;
+        if (AudioSpec.SAMPLE_RATE_RANGE_AUTO.equals(audioSpecSampleRateRange)) {
+            resolvedSampleRate = AudioConfigUtil.AUDIO_SAMPLE_RATE_DEFAULT;
+            Logger.d(TAG, "Using fallback AUDIO sample rate: " + resolvedSampleRate + "Hz");
+        } else {
+            resolvedSampleRate = AudioConfigUtil.selectSampleRateOrNearestSupported(
+                    audioSpecSampleRateRange,
+                    resolvedChannelCount, resolvedSourceFormat,
+                    audioSpecSampleRateRange.getUpper());
+            Logger.d(TAG, "Using AUDIO sample rate resolved from AudioSpec: " + resolvedSampleRate
+                    + "Hz");
+        }
+
+        return AudioSource.Settings.builder()
+                .setAudioSource(resolvedAudioSource)
+                .setAudioFormat(resolvedSourceFormat)
+                .setChannelCount(resolvedChannelCount)
+                .setSampleRate(resolvedSampleRate)
+                .build();
+    }
+
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java
new file mode 100644
index 0000000..4fbbd71
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/MimeInfo.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.video.internal.encoder.EncoderConfig;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * Data class containing information about a media mime.
+ *
+ * <p>The information included in this class can include the mime type, profile and any
+ * compatible configuration types that can be used to resolve settings, such as
+ * {@link androidx.camera.core.impl.CamcorderProfileProxy}.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+@AutoValue
+public abstract class MimeInfo {
+
+    /** Returns the mime type. */
+    @NonNull
+    public abstract String getMimeType();
+
+    /**
+     * Returns the profile for the given mime.
+     *
+     * <p>The returned integer will generally come from
+     * {@link android.media.MediaCodecInfo.CodecProfileLevel}, or if no profile is required,
+     * {@link androidx.camera.video.internal.encoder.EncoderConfig#CODEC_PROFILE_NONE}.
+     */
+    public abstract int getProfile();
+
+    /**
+     * Returns compatible {@link CamcorderProfileProxy} that can be used to resolve settings.
+     *
+     * <p>If no camcorder profile is provided, returns {@code null}
+     */
+    @Nullable
+    public abstract CamcorderProfileProxy getCompatibleCamcorderProfile();
+
+    /** Creates a builder for the given mime type */
+    @NonNull
+    public static Builder builder(@NonNull String mimeType) {
+        return new AutoValue_MimeInfo.Builder()
+                .setMimeType(mimeType)
+                .setProfile(EncoderConfig.CODEC_PROFILE_NONE);
+    }
+
+    /** A Builder for a {@link androidx.camera.video.internal.config.MimeInfo} */
+    @AutoValue.Builder
+    public abstract static class Builder {
+
+        // Package-private since this should be passed to builder factory method.
+        @NonNull
+        abstract Builder setMimeType(@NonNull String mimeType);
+
+        /** Sets the mime profile */
+        @NonNull
+        public abstract Builder setProfile(int profile);
+
+        /** Sets a compatible camcorder profile */
+        @NonNull
+        public abstract Builder setCompatibleCamcorderProfile(
+                @Nullable CamcorderProfileProxy camcorderProfile);
+
+        /** Builds the {@link androidx.camera.video.internal.config.MimeInfo}. */
+        @NonNull
+        public abstract MimeInfo build();
+    }
+
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java
new file mode 100644
index 0000000..02dca7c3
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoConfigUtil.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+import android.util.Rational;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.video.VideoSpec;
+
+/**
+ * A collection of utilities used for resolving and debugging video configurations.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public final class VideoConfigUtil {
+    private static final String TAG = "VideoConfigUtil";
+
+    private static final int VIDEO_FRAME_RATE_FIXED_DEFAULT = 30;
+
+    // Should not be instantiated.
+    private VideoConfigUtil() {
+    }
+
+    static int resolveFrameRate(@NonNull VideoSpec videoSpec) {
+        // TODO(b/177918193): We currently cannot communicate the frame rate to the camera,
+        //  so we only support 30fps. This should come from MediaSpec or use
+        //  CamcorderProfile.videoFrameRate if set to AUTO framerate.
+        Range<Integer> videoSpecFrameRateRange = videoSpec.getFrameRate();
+        int resolvedFrameRate = VIDEO_FRAME_RATE_FIXED_DEFAULT;
+        if (VideoSpec.FRAME_RATE_RANGE_AUTO.equals(videoSpecFrameRateRange)
+                || videoSpecFrameRateRange.contains(VIDEO_FRAME_RATE_FIXED_DEFAULT)) {
+            Logger.d(TAG, "Using single supported VIDEO frame rate: " + resolvedFrameRate);
+        } else {
+            Logger.w(TAG,
+                    "Requested frame rate range does not include single supported frame rate. "
+                            + "Ignoring range. [range: " + videoSpecFrameRateRange + " supported "
+                            + "frame rate: " + resolvedFrameRate + "]");
+        }
+
+        return resolvedFrameRate;
+    }
+
+    static int scaleAndClampBitrate(
+            int baseBitrate,
+            int actualFrameRate, int baseFrameRate,
+            int actualWidth, int baseWidth,
+            int actualHeight, int baseHeight,
+            @NonNull Range<Integer> clampedRange) {
+        // Scale bitrate to match current frame rate
+        Rational frameRateRatio = new Rational(actualFrameRate, baseFrameRate);
+        // Scale bitrate depending on number of actual pixels relative to profile's
+        // number of pixels.
+        // TODO(b/191678894): This should come from the eventual crop rectangle rather
+        //  than the full surface size.
+        Rational widthRatio = new Rational(actualWidth, baseWidth);
+        Rational heightRatio = new Rational(actualHeight, baseHeight);
+        int resolvedBitrate =
+                (int) (baseBitrate * frameRateRatio.doubleValue() * widthRatio.doubleValue()
+                        * heightRatio.doubleValue());
+
+        String debugString = "";
+        if (Logger.isDebugEnabled(TAG)) {
+            debugString = String.format("Base Bitrate(%dbps) * Frame Rate Ratio(%d / %d) * Width "
+                            + "Ratio(%d / %d) * Height Ratio(%d / %d) = %d", baseBitrate,
+                    actualFrameRate,
+                    baseFrameRate, actualWidth, baseWidth, actualHeight, baseHeight,
+                    resolvedBitrate);
+        }
+
+        if (!VideoSpec.BITRATE_RANGE_AUTO.equals(clampedRange)) {
+            // Clamp the resolved bitrate
+            resolvedBitrate = clampedRange.clamp(resolvedBitrate);
+            if (Logger.isDebugEnabled(TAG)) {
+                debugString += String.format("\nClamped to range %s -> %dbps", clampedRange,
+                        resolvedBitrate);
+            }
+        }
+        Logger.d(TAG, debugString);
+        return resolvedBitrate;
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java
new file mode 100644
index 0000000..ba39b52
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigCamcorderProfileResolver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.core.impl.CamcorderProfileProxy;
+import androidx.camera.video.VideoSpec;
+import androidx.camera.video.internal.encoder.VideoEncoderConfig;
+import androidx.core.util.Supplier;
+
+/**
+ * A {@link VideoEncoderConfig} supplier that resolves requested encoder settings from a
+ * {@link VideoSpec} for the given surface {@link Size} using the provided
+ * {@link CamcorderProfileProxy}.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class VideoEncoderConfigCamcorderProfileResolver implements Supplier<VideoEncoderConfig> {
+
+    private static final String TAG = "VidEncCmcrdrPrflRslvr";
+
+    private final String mMimeType;
+    private final VideoSpec mVideoSpec;
+    private final Size mSurfaceSize;
+    private final CamcorderProfileProxy mCamcorderProfile;
+
+    /**
+     * Constructor for a VideoEncoderConfigCamcorderProfileResolver.
+     *
+     * @param mimeType         The mime type for the video encoder
+     * @param videoSpec        The {@link VideoSpec} which defines the settings that should be
+     *                         used with the video encoder.
+     * @param surfaceSize      The size of the surface required by the camera for the video encoder.
+     * @param camcorderProfile The {@link CamcorderProfileProxy} used to resolve automatic and
+     *                         range settings.
+     */
+    public VideoEncoderConfigCamcorderProfileResolver(@NonNull String mimeType,
+            @NonNull VideoSpec videoSpec,
+            @NonNull Size surfaceSize,
+            @NonNull CamcorderProfileProxy camcorderProfile) {
+        mMimeType = mimeType;
+        mVideoSpec = videoSpec;
+        mSurfaceSize = surfaceSize;
+        mCamcorderProfile = camcorderProfile;
+    }
+
+    @Override
+    @NonNull
+    public VideoEncoderConfig get() {
+        int resolvedFrameRate = VideoConfigUtil.resolveFrameRate(mVideoSpec);
+
+        Range<Integer> videoSpecBitrateRange = mVideoSpec.getBitrate();
+        Logger.d(TAG, "Using resolved VIDEO bitrate from CamcorderProfile");
+        int resolvedBitrate = VideoConfigUtil.scaleAndClampBitrate(
+                mCamcorderProfile.getVideoBitRate(),
+                resolvedFrameRate, mCamcorderProfile.getVideoFrameRate(),
+                mSurfaceSize.getWidth(), mCamcorderProfile.getVideoFrameWidth(),
+                mSurfaceSize.getHeight(), mCamcorderProfile.getVideoFrameHeight(),
+                videoSpecBitrateRange);
+
+        return VideoEncoderConfig.builder()
+                .setMimeType(mMimeType)
+                .setResolution(mSurfaceSize)
+                .setBitrate(resolvedBitrate)
+                .setFrameRate(resolvedFrameRate)
+                .build();
+    }
+}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolver.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolver.java
new file mode 100644
index 0000000..d61649f
--- /dev/null
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/VideoEncoderConfigDefaultResolver.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.video.internal.config;
+
+import android.util.Range;
+import android.util.Size;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+import androidx.camera.video.VideoSpec;
+import androidx.camera.video.internal.encoder.VideoEncoderConfig;
+import androidx.core.util.Supplier;
+
+/**
+ * A {@link VideoEncoderConfig} supplier that resolves requested encoder settings from a
+ * {@link VideoSpec} for the given surface {@link Size} using pre-defined default values.
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class VideoEncoderConfigDefaultResolver implements Supplier<VideoEncoderConfig> {
+
+    private static final String TAG = "VidEncCfgDefaultRslvr";
+
+    // Base config based on generic 720p H264 quality will be scaled by actual source settings.
+    // TODO: These should vary based on quality/codec and be derived from actual devices
+    private static final int VIDEO_BITRATE_BASE = 14000000;
+    private static final Size VIDEO_SIZE_BASE = new Size(1280, 720);
+    private static final int VIDEO_FRAME_RATE_BASE = 30;
+
+    private final String mMimeType;
+    private final VideoSpec mVideoSpec;
+    private final Size mSurfaceSize;
+
+    /**
+     * Constructor for a VideoEncoderConfigDefaultResolver.
+     *
+     * @param mimeType    The mime type for the video encoder
+     * @param videoSpec   The {@link VideoSpec} which defines the settings that should be used with
+     *                    the video encoder.
+     * @param surfaceSize The size of the surface required by the camera for the video encoder.
+     */
+    public VideoEncoderConfigDefaultResolver(@NonNull String mimeType,
+            @NonNull VideoSpec videoSpec, @NonNull Size surfaceSize) {
+        mMimeType = mimeType;
+        mVideoSpec = videoSpec;
+        mSurfaceSize = surfaceSize;
+    }
+
+    @Override
+    @NonNull
+    public VideoEncoderConfig get() {
+        int resolvedFrameRate = VideoConfigUtil.resolveFrameRate(mVideoSpec);
+
+        Range<Integer> videoSpecBitrateRange = mVideoSpec.getBitrate();
+        Logger.d(TAG, "Using fallback VIDEO bitrate");
+        // We have no other information to go off of. Scale based on fallback defaults.
+        int resolvedBitrate = VideoConfigUtil.scaleAndClampBitrate(
+                VIDEO_BITRATE_BASE,
+                resolvedFrameRate, VIDEO_FRAME_RATE_BASE,
+                mSurfaceSize.getWidth(), VIDEO_SIZE_BASE.getWidth(),
+                mSurfaceSize.getHeight(), VIDEO_SIZE_BASE.getHeight(),
+                videoSpecBitrateRange);
+
+        return VideoEncoderConfig.builder()
+                .setMimeType(mMimeType)
+                .setResolution(mSurfaceSize)
+                .setBitrate(resolvedBitrate)
+                .setFrameRate(resolvedFrameRate)
+                .build();
+    }
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/package-info.java
similarity index 68%
copy from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
copy to camera/camera-video/src/main/java/androidx/camera/video/internal/config/package-info.java
index d721bff..f350cca 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/config/package-info.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+/**
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+package androidx.camera.video.internal.config;
 
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemsProvider
-
-internal interface LazyListItemsProvider : LazyLayoutItemsProvider {
-    /** The list of indexes of the sticky header items */
-    val headerIndexes: List<Int>
-}
+import androidx.annotation.RestrictTo;
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/AudioEncoderConfig.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/AudioEncoderConfig.java
index 418678a..3af219d 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/AudioEncoderConfig.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/AudioEncoderConfig.java
@@ -16,7 +16,6 @@
 
 package androidx.camera.video.internal.encoder;
 
-import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 
 import androidx.annotation.NonNull;
@@ -24,6 +23,8 @@
 
 import com.google.auto.value.AutoValue;
 
+import java.util.Objects;
+
 /** {@inheritDoc} */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 @AutoValue
@@ -36,7 +37,8 @@
     /** Returns a build for this config. */
     @NonNull
     public static Builder builder() {
-        return new AutoValue_AudioEncoderConfig.Builder();
+        return new AutoValue_AudioEncoderConfig.Builder()
+                .setProfile(EncoderConfig.CODEC_PROFILE_NONE);
     }
 
     /** {@inheritDoc} */
@@ -44,6 +46,14 @@
     @NonNull
     public abstract String getMimeType();
 
+    /**
+     * {@inheritDoc}
+     *
+     * <p>Default is {@link EncoderConfig#CODEC_PROFILE_NONE}.
+     */
+    @Override
+    public abstract int getProfile();
+
     /** Gets the bitrate. */
     public abstract int getBitrate();
 
@@ -60,10 +70,14 @@
         MediaFormat mediaFormat = MediaFormat.createAudioFormat(getMimeType(), getSampleRate(),
                 getChannelCount());
         mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, getBitrate());
-        if (getMimeType().equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
-            mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
-                    MediaCodecInfo.CodecProfileLevel.AACObjectLC);
+        if (getProfile() != CODEC_PROFILE_NONE) {
+            if (getMimeType().equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+                mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, getProfile());
+            } else {
+                mediaFormat.setInteger(MediaFormat.KEY_PROFILE, getProfile());
+            }
         }
+
         return mediaFormat;
     }
 
@@ -74,10 +88,21 @@
         Builder() {
         }
 
-        /** Sets the mime type. */
+        /**
+         * Sets the mime type.
+         *
+         * <p>If the mime type is set to AAC, i.e. {@link MediaFormat#MIMETYPE_AUDIO_AAC}, then a
+         * profile must be set with {@link #setProfile(int)}. If a profile isn't set or is set to
+         * {@link EncoderConfig#CODEC_PROFILE_NONE}, an IllegalArgumentException will be thrown by
+         * {@link #build()}.
+         */
         @NonNull
         public abstract Builder setMimeType(@NonNull String mimeType);
 
+        /** Sets (optional) profile for the mime type specified by {@link #setMimeType(String)}. */
+        @NonNull
+        public abstract Builder setProfile(int profile);
+
         /** Sets the bitrate. */
         @NonNull
         public abstract Builder setBitrate(int bitrate);
@@ -90,8 +115,20 @@
         @NonNull
         public abstract Builder setChannelCount(int channelCount);
 
+        @NonNull
+        abstract AudioEncoderConfig autoBuild();
+
         /** Builds the config instance. */
         @NonNull
-        public abstract AudioEncoderConfig build();
+        public AudioEncoderConfig build() {
+            AudioEncoderConfig config = autoBuild();
+            if (Objects.equals(config.getMimeType(), MediaFormat.MIMETYPE_AUDIO_AAC)
+                    && config.getProfile() == CODEC_PROFILE_NONE) {
+                throw new IllegalArgumentException("Encoder mime set to AAC, but no AAC profile "
+                        + "was provided.");
+            }
+
+            return config;
+        }
     }
 }
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
index 8c7436c..5a1a228 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/EncoderConfig.java
@@ -20,6 +20,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.CamcorderProfileProxy;
 
 /**
  * The configuration represents the required parameters to configure an encoder.
@@ -28,6 +29,10 @@
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface EncoderConfig {
+
+    /** Constant corresponding to no profile for the encoder */
+    int CODEC_PROFILE_NONE = CamcorderProfileProxy.CODEC_PROFILE_NONE;
+
     /**
      * The mime type of the encoder.
      *
@@ -39,6 +44,17 @@
     String getMimeType();
 
     /**
+     * The (optional) profile for the mime type returned by {@link #getMimeType()}.
+     *
+     * <p>For example, for AAC-ELD (enhanced low delay) audio encoder, the mime type is
+     * "audio/mp4a-latm" and the profile needs to be
+     * {@link android.media.MediaCodecInfo.CodecProfileLevel#AACObjectELD}.
+     *
+     * <p>Not all mime types require a profile, so this is optional.
+     */
+    int getProfile();
+
+    /**
      * Transfers the config to a {@link MediaFormat}.
      *
      * @return the result {@link MediaFormat}
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/VideoEncoderConfig.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/VideoEncoderConfig.java
index cdcb3ba..d3ff4af 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/VideoEncoderConfig.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/encoder/VideoEncoderConfig.java
@@ -16,6 +16,7 @@
 
 package androidx.camera.video.internal.encoder;
 
+import android.media.MediaCodecInfo;
 import android.media.MediaFormat;
 import android.util.Size;
 
@@ -29,6 +30,10 @@
 @AutoValue
 public abstract class VideoEncoderConfig implements EncoderConfig {
 
+    private static final int VIDEO_INTRA_FRAME_INTERVAL_DEFAULT = 1;
+    private static final int VIDEO_COLOR_FORMAT_DEFAULT =
+            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
+
     // Restrict constructor to same package
     VideoEncoderConfig() {
     }
@@ -36,14 +41,19 @@
     /** Returns a build for this config. */
     @NonNull
     public static Builder builder() {
-        return new AutoValue_VideoEncoderConfig.Builder();
+        return new AutoValue_VideoEncoderConfig.Builder()
+                .setProfile(EncoderConfig.CODEC_PROFILE_NONE)
+                .setIFrameInterval(VIDEO_INTRA_FRAME_INTERVAL_DEFAULT)
+                .setColorFormat(VIDEO_COLOR_FORMAT_DEFAULT);
     }
 
-    /** {@inheritDoc} */
     @Override
     @NonNull
     public abstract String getMimeType();
 
+    @Override
+    public abstract int getProfile();
+
     /** Gets the resolution. */
     @NonNull
     public abstract Size getResolution();
@@ -71,6 +81,9 @@
         format.setInteger(MediaFormat.KEY_BIT_RATE, getBitrate());
         format.setInteger(MediaFormat.KEY_FRAME_RATE, getFrameRate());
         format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, getIFrameInterval());
+        if (getProfile() != EncoderConfig.CODEC_PROFILE_NONE) {
+            format.setInteger(MediaFormat.KEY_PROFILE, getProfile());
+        }
         return format;
     }
 
@@ -85,6 +98,10 @@
         @NonNull
         public abstract Builder setMimeType(@NonNull String mimeType);
 
+        /** Sets (optional) profile for the mime type specified by {@link #setMimeType(String)}. */
+        @NonNull
+        public abstract Builder setProfile(int profile);
+
         /** Sets the resolution. */
         @NonNull
         public abstract Builder setResolution(@NonNull Size resolution);
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
index aaffc65..8e7dd14 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/QualitySelectorTest.kt
@@ -26,17 +26,6 @@
 import androidx.camera.testing.CamcorderProfileUtil.RESOLUTION_720P
 import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
 import androidx.camera.testing.fakes.FakeCameraInfoInternal
-import androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_HIGHER
-import androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_LOWER
-import androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_STRICTLY_HIGHER
-import androidx.camera.video.QualitySelector.FALLBACK_STRATEGY_STRICTLY_LOWER
-import androidx.camera.video.QualitySelector.QUALITY_FHD
-import androidx.camera.video.QualitySelector.QUALITY_HD
-import androidx.camera.video.QualitySelector.QUALITY_HIGHEST
-import androidx.camera.video.QualitySelector.QUALITY_LOWEST
-import androidx.camera.video.QualitySelector.QUALITY_NONE
-import androidx.camera.video.QualitySelector.QUALITY_SD
-import androidx.camera.video.QualitySelector.QUALITY_UHD
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.assertThrows
 import org.junit.Test
@@ -45,8 +34,6 @@
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
 
-private const val NOT_QUALITY_CONSTANT = -111
-private const val NOT_FALLBACK_STRATEGY_CONSTANT = -1
 private const val CAMERA_ID_0 = "0"
 private const val CAMERA_ID_1 = "1"
 private val CAMERA_0_PROFILE_HIGH = CamcorderProfileUtil.asHighQuality(PROFILE_2160P)
@@ -80,12 +67,12 @@
 
     @Test
     fun getSortedQualities_fromLargeToSmall() {
-        val sortedQualities = QualitySelector.getSortedQualities()
+        val sortedQualities = Quality.getSortedQualities()
 
-        assertThat(sortedQualities[0]).isEqualTo(QUALITY_UHD)
-        assertThat(sortedQualities[1]).isEqualTo(QUALITY_FHD)
-        assertThat(sortedQualities[2]).isEqualTo(QUALITY_HD)
-        assertThat(sortedQualities[3]).isEqualTo(QUALITY_SD)
+        assertThat(sortedQualities[0]).isEqualTo(Quality.UHD)
+        assertThat(sortedQualities[1]).isEqualTo(Quality.FHD)
+        assertThat(sortedQualities[2]).isEqualTo(Quality.HD)
+        assertThat(sortedQualities[3]).isEqualTo(Quality.SD)
     }
 
     @Test
@@ -93,129 +80,94 @@
         // camera0 supports 2160P(UHD) and 720P(HD)
         val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo0)
 
-        assertThat(supportedQualities[0]).isEqualTo(QUALITY_UHD)
-        assertThat(supportedQualities[1]).isEqualTo(QUALITY_HD)
+        assertThat(supportedQualities[0]).isEqualTo(Quality.UHD)
+        assertThat(supportedQualities[1]).isEqualTo(Quality.HD)
     }
 
     @Test
     fun isQualitySupported_returnCorrectResult() {
         // camera0 supports 2160P(UHD) and 720P(HD)
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_NONE)).isFalse()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_HIGHEST)).isTrue()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_LOWEST)).isTrue()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_UHD)).isTrue()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_FHD)).isFalse()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_HD)).isTrue()
-        assertThat(QualitySelector.isQualitySupported(cameraInfo0, QUALITY_SD)).isFalse()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.HIGHEST)).isTrue()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.LOWEST)).isTrue()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.UHD)).isTrue()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.FHD)).isFalse()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.HD)).isTrue()
+        assertThat(QualitySelector.isQualitySupported(cameraInfo0, Quality.SD)).isFalse()
     }
 
     @Test
     fun getResolution_returnCorrectResolution() {
         // camera0 supports 2160P(UHD) and 720P(HD)
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_NONE)
-        ).isNull()
-        assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_HIGHEST)
+            QualitySelector.getResolution(cameraInfo0, Quality.HIGHEST)
         ).isEqualTo(RESOLUTION_2160P)
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_LOWEST)
+            QualitySelector.getResolution(cameraInfo0, Quality.LOWEST)
         ).isEqualTo(RESOLUTION_720P)
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_UHD)
+            QualitySelector.getResolution(cameraInfo0, Quality.UHD)
         ).isEqualTo(RESOLUTION_2160P)
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_FHD)
+            QualitySelector.getResolution(cameraInfo0, Quality.FHD)
         ).isNull()
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_HD)
+            QualitySelector.getResolution(cameraInfo0, Quality.HD)
         ).isEqualTo(RESOLUTION_720P)
         assertThat(
-            QualitySelector.getResolution(cameraInfo0, QUALITY_SD)
+            QualitySelector.getResolution(cameraInfo0, Quality.SD)
         ).isNull()
     }
 
     @Test
-    fun of_setNonQualityConstant_throwException() {
+    fun fromOrderedList_containNull_throwException() {
         // Assert.
         assertThrows(IllegalArgumentException::class.java) {
             // Act.
-            QualitySelector.of(NOT_QUALITY_CONSTANT)
+            QualitySelector.fromOrderedList(listOf(Quality.FHD, null))
         }
     }
 
     @Test
-    fun thenTry_setNonQualityConstant_throwException() {
+    fun fromOrderedList_setEmptyQualityList_throwException() {
         // Assert.
         assertThrows(IllegalArgumentException::class.java) {
             // Act.
-            QualitySelector.firstTry(QUALITY_FHD)
-                .thenTry(NOT_QUALITY_CONSTANT)
+            QualitySelector.fromOrderedList(emptyList())
         }
     }
 
     @Test
-    fun finallyTry_setNonQualityConstant_throwException() {
-        // Assert.
-        assertThrows(IllegalArgumentException::class.java) {
-            // Act.
-            QualitySelector.firstTry(QUALITY_FHD)
-                .thenTry(QUALITY_HD)
-                .finallyTry(NOT_QUALITY_CONSTANT)
-        }
-    }
-
-    @Test
-    fun of_setNonFallbackStrategyConstant_throwException() {
-        // Assert.
-        assertThrows(IllegalArgumentException::class.java) {
-            // Act.
-            QualitySelector.of(QUALITY_FHD, NOT_FALLBACK_STRATEGY_CONSTANT)
-        }
-    }
-
-    @Test
-    fun finallyTry_setNonFallbackStrategyConstant_throwException() {
-        // Assert.
-        assertThrows(IllegalArgumentException::class.java) {
-            // Act.
-            QualitySelector.firstTry(QUALITY_FHD)
-                .finallyTry(QUALITY_HD, NOT_FALLBACK_STRATEGY_CONSTANT)
-        }
-    }
-
-    @Test
-    fun getPrioritizedQualities_byFirstTry() {
+    fun getPrioritizedQualities_selectSingleQuality() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_UHD)
-            .finallyTry(QUALITY_SD)
+        val qualitySelector = QualitySelector.from(Quality.UHD)
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.UHD))
     }
 
     @Test
-    fun getPrioritizedQualities_byOf() {
+    fun getPrioritizedQualities_selectQualityByOrder() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(QUALITY_UHD)
+        val qualitySelector =
+            QualitySelector.fromOrderedList(listOf(Quality.FHD, Quality.UHD, Quality.HD))
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.UHD, Quality.HD))
     }
 
     @Test
-    fun getPrioritizedQualities_byOf_noFallbackStrategy() {
+    fun getPrioritizedQualities_noFallbackStrategy() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(QUALITY_FHD)
+        val qualitySelector = QualitySelector.from(Quality.FHD)
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
@@ -225,182 +177,146 @@
     }
 
     @Test
-    fun getPrioritizedQualities_byOf_withFallbackStrategy() {
+    fun getPrioritizedQualities_withFallbackStrategy() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_FHD,
-            FALLBACK_STRATEGY_LOWER
+        val qualitySelector = QualitySelector.from(
+            Quality.FHD,
+            FallbackStrategy.lowerQualityOrHigherThan(Quality.FHD)
         )
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_byThenTry() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .thenTry(QUALITY_UHD)
-            .finallyTry(QUALITY_FHD)
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_UHD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_byFinallyTry() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .thenTry(QUALITY_SD)
-            .finallyTry(QUALITY_UHD)
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_UHD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_byFinallyTry_noFallbackStrategy() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .finallyTry(QUALITY_SD)
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEmpty()
-    }
-
-    @Test
-    fun getPrioritizedQualities_byFinallyTry_withFallbackStrategy() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .finallyTry(QUALITY_SD, FALLBACK_STRATEGY_HIGHER)
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.HD, Quality.UHD))
     }
 
     @Test
     fun getPrioritizedQualities_containHighestQuality_addAll() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .finallyTry(QUALITY_HIGHEST)
+        val qualitySelector = QualitySelector.fromOrderedList(listOf(Quality.FHD, Quality.HIGHEST))
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_UHD, QUALITY_HD))
+        assertThat(qualities).isEqualTo(listOf(Quality.UHD, Quality.HD))
     }
 
     @Test
     fun getPrioritizedQualities_containLowestQuality_addAllReversely() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_FHD)
-            .finallyTry(QUALITY_LOWEST)
+        val qualitySelector = QualitySelector.fromOrderedList(listOf(Quality.FHD, Quality.LOWEST))
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.HD, Quality.UHD))
     }
 
     @Test
     fun getPrioritizedQualities_addDuplicateQuality_getSingleQualityWithCorrectOrder() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.firstTry(QUALITY_SD)
-            .thenTry(QUALITY_FHD)
-            .thenTry(QUALITY_HD)
-            .thenTry(QUALITY_UHD)
-            // start duplicate qualities
-            .thenTry(QUALITY_SD)
-            .thenTry(QUALITY_HD)
-            .thenTry(QUALITY_FHD)
-            .thenTry(QUALITY_UHD)
-            .thenTry(QUALITY_LOWEST)
-            .thenTry(QUALITY_HIGHEST)
-            .finallyTry(QUALITY_LOWEST, FALLBACK_STRATEGY_STRICTLY_HIGHER)
+        val qualitySelector = QualitySelector.fromOrderedList(
+            listOf(
+                Quality.SD,
+                Quality.FHD,
+                Quality.HD,
+                Quality.UHD,
+                // start duplicate qualities
+                Quality.SD,
+                Quality.HD,
+                Quality.FHD,
+                Quality.UHD,
+                Quality.LOWEST,
+                Quality.HIGHEST
+            ),
+            FallbackStrategy.higherQualityThan(Quality.LOWEST)
+        )
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.HD, Quality.UHD))
+    }
+
+    @Test
+    fun getPrioritizedQualities_fallbackLowerOrHigher_getLower() {
+        // Arrange.
+        // camera0 supports 2160P(UHD) and 720P(HD)
+        val qualitySelector = QualitySelector.from(
+            Quality.FHD,
+            FallbackStrategy.lowerQualityOrHigherThan(Quality.FHD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.HD, Quality.UHD))
+    }
+
+    @Test
+    fun getPrioritizedQualities_fallbackLowerOrHigher_fallbackQualityNotIncluded() {
+        // Arrange.
+        // camera0 supports 2160P(UHD) and 720P(HD)
+        val qualitySelector = QualitySelector.from(
+            Quality.SD,
+            FallbackStrategy.higherQualityThan(Quality.HD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.UHD))
+    }
+
+    @Test
+    fun getPrioritizedQualities_fallbackLowerOrHigher_getHigher() {
+        // Arrange.
+        // camera0 supports 2160P(UHD) and 720P(HD)
+        val qualitySelector = QualitySelector.from(
+            Quality.SD,
+            FallbackStrategy.lowerQualityOrHigherThan(Quality.SD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.HD, Quality.UHD))
     }
 
     @Test
     fun getPrioritizedQualities_fallbackLower_getLower() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_FHD, FALLBACK_STRATEGY_LOWER
+        val qualitySelector = QualitySelector.from(
+            Quality.FHD,
+            FallbackStrategy.lowerQualityThan(Quality.FHD)
         )
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
+        assertThat(qualities).isEqualTo(listOf(Quality.HD))
     }
 
     @Test
-    fun getPrioritizedQualities_fallbackLower_getHigher() {
+    fun getPrioritizedQualities_fallbackLower_getNone() {
         // Arrange.
         // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_SD, FALLBACK_STRATEGY_LOWER
-        )
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD, QUALITY_UHD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_fallbackStrictLower_getLower() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_FHD, FALLBACK_STRATEGY_STRICTLY_LOWER
-        )
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo0)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_HD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_fallbackStrictLower_getNone() {
-        // Arrange.
-        // camera0 supports 2160P(UHD) and 720P(HD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_SD, FALLBACK_STRATEGY_STRICTLY_LOWER
+        val qualitySelector = QualitySelector.from(
+            Quality.SD,
+            FallbackStrategy.lowerQualityThan(Quality.SD)
         )
 
         // Act.
@@ -411,57 +327,76 @@
     }
 
     @Test
+    fun getPrioritizedQualities_fallbackHigherOrLower_getHigher() {
+        // Arrange.
+        // camera1 supports 1080P(FHD) and 480P(SD)
+        val qualitySelector = QualitySelector.from(
+            Quality.HD,
+            FallbackStrategy.higherQualityOrLowerThan(Quality.HD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.FHD, Quality.SD))
+    }
+
+    @Test
+    fun getPrioritizedQualities_fallbackHigher_fallbackQualityNotIncluded() {
+        // Arrange.
+        // camera1 supports 1080P(FHD) and 480P(SD)
+        val qualitySelector = QualitySelector.from(
+            Quality.UHD,
+            FallbackStrategy.higherQualityThan(Quality.SD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.FHD))
+    }
+
+    @Test
+    fun getPrioritizedQualities_fallbackHigherOrLower_getLower() {
+        // Arrange.
+        // camera1 supports 1080P(FHD) and 480P(SD)
+        val qualitySelector = QualitySelector.from(
+            Quality.UHD,
+            FallbackStrategy.higherQualityOrLowerThan(Quality.UHD)
+        )
+
+        // Act.
+        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
+
+        // Assert.
+        assertThat(qualities).isEqualTo(listOf(Quality.FHD, Quality.SD))
+    }
+
+    @Test
     fun getPrioritizedQualities_fallbackHigher_getHigher() {
         // Arrange.
         // camera1 supports 1080P(FHD) and 480P(SD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_HD,
-            FALLBACK_STRATEGY_HIGHER
+        val qualitySelector = QualitySelector.from(
+            Quality.HD,
+            FallbackStrategy.higherQualityThan(Quality.HD)
         )
 
         // Act.
         val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
 
         // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_FHD, QUALITY_SD))
+        assertThat(qualities).isEqualTo(listOf(Quality.FHD))
     }
 
     @Test
-    fun getPrioritizedQualities_fallbackHigher_getLower() {
+    fun getPrioritizedQualities_fallbackHigher_getNone() {
         // Arrange.
         // camera1 supports 1080P(FHD) and 480P(SD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_UHD, FALLBACK_STRATEGY_HIGHER
-        )
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_FHD, QUALITY_SD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_fallbackStrictHigher_getHigher() {
-        // Arrange.
-        // camera1 supports 1080P(FHD) and 480P(SD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_HD, FALLBACK_STRATEGY_STRICTLY_HIGHER
-        )
-
-        // Act.
-        val qualities = qualitySelector.getPrioritizedQualities(cameraInfo1)
-
-        // Assert.
-        assertThat(qualities).isEqualTo(listOf(QUALITY_FHD))
-    }
-
-    @Test
-    fun getPrioritizedQualities_fallbackStrictHigher_getNone() {
-        // Arrange.
-        // camera1 supports 1080P(FHD) and 480P(SD)
-        val qualitySelector = QualitySelector.of(
-            QUALITY_UHD, FALLBACK_STRATEGY_STRICTLY_HIGHER
+        val qualitySelector = QualitySelector.from(
+            Quality.UHD,
+            FallbackStrategy.higherQualityThan(Quality.UHD)
         )
 
         // Act.
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
index d08276e..29f8235 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCapabilitiesTest.kt
@@ -17,11 +17,14 @@
 package androidx.camera.video
 
 import android.os.Build
+import android.util.Size
 import androidx.camera.testing.CamcorderProfileUtil
 import androidx.camera.testing.CamcorderProfileUtil.PROFILE_2160P
 import androidx.camera.testing.CamcorderProfileUtil.PROFILE_720P
 import androidx.camera.testing.fakes.FakeCamcorderProfileProvider
 import androidx.camera.testing.fakes.FakeCameraInfoInternal
+import androidx.core.util.component1
+import androidx.core.util.component2
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -39,38 +42,78 @@
 
     private val cameraInfo = FakeCameraInfoInternal().apply {
         camcorderProfileProvider = FakeCamcorderProfileProvider.Builder()
-            .addProfile(PROFILE_HIGH)
-            .addProfile(PROFILE_2160P)
-            .addProfile(PROFILE_720P)
-            .addProfile(PROFILE_LOW)
+            .addProfile(PROFILE_HIGH) // UHD (2160p) per above definition
+            .addProfile(PROFILE_2160P) // UHD (2160p)
+            .addProfile(PROFILE_720P) // HD (720p)
+            .addProfile(PROFILE_LOW) // HD (720p) per above definition
             .build()
     }
 
     @Test
     fun isQualitySupported() {
         val videoCapabilities = VideoCapabilities.from(cameraInfo)
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_NONE)).isFalse()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_HIGHEST)).isTrue()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_LOWEST)).isTrue()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_UHD)).isTrue()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_FHD)).isFalse()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_HD)).isTrue()
-        assertThat(videoCapabilities.isQualitySupported(QualitySelector.QUALITY_SD)).isFalse()
+        assertThat(videoCapabilities.isQualitySupported(Quality.HIGHEST)).isTrue()
+        assertThat(videoCapabilities.isQualitySupported(Quality.LOWEST)).isTrue()
+        assertThat(videoCapabilities.isQualitySupported(Quality.UHD)).isTrue()
+        assertThat(videoCapabilities.isQualitySupported(Quality.FHD)).isFalse()
+        assertThat(videoCapabilities.isQualitySupported(Quality.HD)).isTrue()
+        assertThat(videoCapabilities.isQualitySupported(Quality.SD)).isFalse()
     }
 
     @Test
     fun getProfile() {
         val videoCapabilities = VideoCapabilities.from(cameraInfo)
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_NONE)).isNull()
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_HIGHEST))
+        assertThat(videoCapabilities.getProfile(Quality.HIGHEST))
             .isEqualTo(PROFILE_2160P)
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_LOWEST))
+        assertThat(videoCapabilities.getProfile(Quality.LOWEST))
             .isEqualTo(PROFILE_720P)
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_UHD))
+        assertThat(videoCapabilities.getProfile(Quality.UHD))
             .isEqualTo(PROFILE_2160P)
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_FHD)).isNull()
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_HD))
+        assertThat(videoCapabilities.getProfile(Quality.FHD)).isNull()
+        assertThat(videoCapabilities.getProfile(Quality.HD))
             .isEqualTo(PROFILE_720P)
-        assertThat(videoCapabilities.getProfile(QualitySelector.QUALITY_SD)).isNull()
+        assertThat(videoCapabilities.getProfile(Quality.SD)).isNull()
+    }
+
+    @Test
+    fun findHighestSupportedQuality_returnsHigherQuality() {
+        val videoCapabilities = VideoCapabilities.from(cameraInfo)
+        // Create a size between 720p and 2160p
+        val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+        val inBetweenSize = Size(width720p + 10, height720p)
+
+        assertThat(videoCapabilities.findHighestSupportedQualityFor(inBetweenSize))
+            .isEqualTo(Quality.UHD)
+    }
+
+    @Test
+    fun findHighestSupportedQuality_returnsHighestQuality_whenAboveHighest() {
+        val videoCapabilities = VideoCapabilities.from(cameraInfo)
+        // Create a size between greater than the max quality (UHD)
+        val (width2160p, height2160p) = CamcorderProfileUtil.RESOLUTION_2160P
+        val aboveHighestSize = Size(width2160p + 10, height2160p)
+
+        assertThat(videoCapabilities.findHighestSupportedQualityFor(aboveHighestSize))
+            .isEqualTo(Quality.UHD)
+    }
+
+    @Test
+    fun findHighestSupportedQuality_returnsLowestQuality_whenBelowLowest() {
+        val videoCapabilities = VideoCapabilities.from(cameraInfo)
+        // Create a size below the lowest quality (HD)
+        val (width720p, height720p) = CamcorderProfileUtil.RESOLUTION_720P
+        val belowLowestSize = Size(width720p - 10, height720p)
+
+        assertThat(videoCapabilities.findHighestSupportedQualityFor(belowLowestSize))
+            .isEqualTo(Quality.HD)
+    }
+
+    @Test
+    fun findHighestSupportedQuality_returnsExactQuality_whenExactSizeGiven() {
+        val videoCapabilities = VideoCapabilities.from(cameraInfo)
+        val exactSize720p = CamcorderProfileUtil.RESOLUTION_720P
+
+        assertThat(videoCapabilities.findHighestSupportedQualityFor(exactSize720p))
+            .isEqualTo(Quality.HD)
     }
 }
diff --git a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
index 40cfac4..2b5276c 100644
--- a/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
+++ b/camera/camera-video/src/test/java/androidx/camera/video/VideoCaptureTest.kt
@@ -47,12 +47,6 @@
 import androidx.camera.testing.fakes.FakeCameraDeviceSurfaceManager
 import androidx.camera.testing.fakes.FakeCameraFactory
 import androidx.camera.testing.fakes.FakeCameraInfoInternal
-import androidx.camera.video.QualitySelector.QUALITY_FHD
-import androidx.camera.video.QualitySelector.QUALITY_HD
-import androidx.camera.video.QualitySelector.QUALITY_HIGHEST
-import androidx.camera.video.QualitySelector.QUALITY_LOWEST
-import androidx.camera.video.QualitySelector.QUALITY_SD
-import androidx.camera.video.QualitySelector.QUALITY_UHD
 import androidx.camera.video.VideoOutput.StreamState
 import androidx.camera.video.impl.VideoCaptureConfig
 import androidx.core.util.Consumer
@@ -170,10 +164,10 @@
 
         // Camera 0 support 2160P(UHD) and 720P(HD)
         val qualityList = arrayOf(
-            QUALITY_UHD to RESOLUTION_2160P,
-            QUALITY_HD to RESOLUTION_720P,
-            QUALITY_HIGHEST to RESOLUTION_2160P,
-            QUALITY_LOWEST to RESOLUTION_720P,
+            Quality.UHD to RESOLUTION_2160P,
+            Quality.HD to RESOLUTION_720P,
+            Quality.HIGHEST to RESOLUTION_2160P,
+            Quality.LOWEST to RESOLUTION_720P,
         )
         qualityList.forEach { (quality, resolution) ->
             surfaceManager.setSuggestedResolution(
@@ -184,7 +178,7 @@
 
             val videoOutput = createVideoOutput(
                 mediaSpec = MediaSpec.builder().configureVideo {
-                    it.setQualitySelector(QualitySelector.of(quality))
+                    it.setQualitySelector(QualitySelector.from(quality))
                 }.build()
             )
             val videoCapture = VideoCapture.Builder(videoOutput)
@@ -223,10 +217,14 @@
         val videoOutput = createVideoOutput(
             mediaSpec = MediaSpec.builder().configureVideo {
                 it.setQualitySelector(
-                    QualitySelector.firstTry(QUALITY_UHD) // 2160P
-                        .thenTry(QUALITY_SD) // 480P
-                        .thenTry(QUALITY_HD) // 720P
-                        .finallyTry(QUALITY_FHD) // 1080P
+                    QualitySelector.fromOrderedList(
+                        listOf(
+                            Quality.UHD, // 2160P
+                            Quality.SD, // 480P
+                            Quality.HD, // 720P
+                            Quality.FHD // 1080P
+                        )
+                    )
                 )
             }.build()
         )
@@ -254,7 +252,7 @@
         // Camera 0 support 2160P(UHD) and 720P(HD)
         val videoOutput = createVideoOutput(
             mediaSpec = MediaSpec.builder().configureVideo {
-                it.setQualitySelector(QualitySelector.of(QUALITY_FHD))
+                it.setQualitySelector(QualitySelector.from(Quality.FHD))
             }.build()
         )
         val videoCapture = VideoCapture.Builder(videoOutput)
@@ -277,7 +275,7 @@
 
         val videoOutput = createVideoOutput(
             mediaSpec = MediaSpec.builder().configureVideo {
-                it.setQualitySelector(QualitySelector.of(QUALITY_UHD))
+                it.setQualitySelector(QualitySelector.from(Quality.UHD))
             }.build()
         )
         val videoCapture = VideoCapture.Builder(videoOutput)
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
index b3286f1..84eccda 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
@@ -21,8 +21,10 @@
 import android.content.Context
 import android.content.Context.CAMERA_SERVICE
 import android.hardware.camera2.CameraCaptureSession
+import android.hardware.camera2.CameraCharacteristics
 import android.hardware.camera2.CameraDevice
 import android.hardware.camera2.CameraManager
+import android.hardware.camera2.CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
 import android.hardware.camera2.CaptureRequest
 import android.hardware.camera2.TotalCaptureResult
 import androidx.camera.camera2.interop.Camera2CameraControl
@@ -52,8 +54,8 @@
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
-import kotlinx.coroutines.withTimeout
 import org.junit.After
+import org.junit.Assert.assertTrue
 import org.junit.Assume
 import org.junit.Before
 import org.junit.Rule
@@ -127,7 +129,11 @@
     fun canUseCameraSelector_fromCamera2CameraIdAndCameraFilter(): Unit = runBlocking {
         val camera2CameraManager = ApplicationProvider.getApplicationContext<Context>()
             .getSystemService(CAMERA_SERVICE) as CameraManager
-        camera2CameraManager.cameraIdList.forEach { id ->
+        camera2CameraManager.cameraIdList.forEach continuing@{ id ->
+            if (!isBackwardCompatible(camera2CameraManager, id)) {
+                return@continuing
+            }
+
             val cameraSelector = CameraSelector.Builder()
                 .addCameraFilter {
                     it.filter { Camera2CameraInfo.from(it).cameraId == id }
@@ -147,7 +153,10 @@
     fun canUseCameraSelector_fromCamera2CameraIdAndAvailableCameraInfos(): Unit = runBlocking {
         val camera2CameraManager = ApplicationProvider.getApplicationContext<Context>()
             .getSystemService(CAMERA_SERVICE) as CameraManager
-        camera2CameraManager.cameraIdList.forEach { id ->
+        camera2CameraManager.cameraIdList.forEach continuing@{ id ->
+            if (!isBackwardCompatible(camera2CameraManager, id)) {
+                return@continuing
+            }
             withContext(Dispatchers.Main) {
                 val cameraSelector =
                     processCameraProvider!!.availableCameraInfos.find {
@@ -223,17 +232,15 @@
 
         val waitingList = mutableListOf<CaptureContainer>()
 
-        suspend fun waitFor(
+        fun waitFor(
             timeout: Long = TimeUnit.SECONDS.toMillis(5),
             numOfCaptures: Int = 1,
             verifyResults: (captureRequests: List<CaptureRequest>) -> Unit
         ) {
             val resultContainer = CaptureContainer(CountDownLatch(numOfCaptures))
             waitingList.add(resultContainer)
-            withTimeout(timeout) {
-                resultContainer.countDownLatch.await()
-                verifyResults(resultContainer.captureRequests)
-            }
+            assertTrue(resultContainer.countDownLatch.await(timeout, TimeUnit.MILLISECONDS))
+            verifyResults(resultContainer.captureRequests)
             waitingList.remove(resultContainer)
         }
 
@@ -288,4 +295,16 @@
             }
             setDeviceStateCallback(stateCallback)
         }.asStateFlow()
+
+    private fun isBackwardCompatible(cameraManager: CameraManager, cameraId: String): Boolean {
+        val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId)
+        val capabilities =
+            cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
+
+        capabilities?.let {
+            return it.contains(REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)
+        }
+
+        return false
+    }
 }
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
index 05646dc..5b915ad 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageAnalysisTest.kt
@@ -247,12 +247,12 @@
                 .setBackpressureStrategy(strategy)
                 .build()
             withContext(Dispatchers.Main) {
-            cameraProvider.bindToLifecycle(fakeLifecycleOwner, DEFAULT_CAMERA_SELECTOR, useCase)
+                cameraProvider.bindToLifecycle(fakeLifecycleOwner, DEFAULT_CAMERA_SELECTOR, useCase)
+            }
+            useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), analyzer)
+            analysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)
+            synchronized(analysisResultLock) { assertThat(analysisResults).isNotEmpty() }
         }
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), analyzer)
-        analysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)
-        synchronized(analysisResultLock) { assertThat(analysisResults).isNotEmpty() }
-    }
 
     @Test
     fun analyzerDoesNotAnalyzeImages_whenCameraIsNotOpen() = runBlocking {
@@ -351,41 +351,6 @@
         assertThat(newConfig.targetResolution == expectedTargetResolution).isTrue()
     }
 
-    // TODO(b/162298517): change the test to be deterministic instead of depend upon timing.
-    @Test
-    fun analyzerSetMultipleTimesInKeepOnlyLatestMode() = runBlocking {
-        val useCase = ImageAnalysis.Builder()
-            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
-            .build()
-        withContext(Dispatchers.Main) {
-            cameraProvider.bindToLifecycle(fakeLifecycleOwner, DEFAULT_CAMERA_SELECTOR, useCase)
-        }
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), analyzer)
-        analysisResultsSemaphore.tryAcquire(5, TimeUnit.SECONDS)
-
-        val slowAnalyzer = ImageAnalysis.Analyzer { image ->
-            try {
-                Thread.sleep(200)
-                image.close()
-            } catch (e: Exception) {
-            }
-        }
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), slowAnalyzer)
-        Thread.sleep(100)
-
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), slowAnalyzer)
-        Thread.sleep(100)
-
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), slowAnalyzer)
-        Thread.sleep(100)
-
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), slowAnalyzer)
-        Thread.sleep(100)
-
-        useCase.setAnalyzer(CameraXExecutors.newHandlerExecutor(handler), slowAnalyzer)
-        Thread.sleep(100)
-    }
-
     @Test
     fun useCaseConfigCanBeReset_afterUnbind() = runBlocking {
         val useCase = ImageAnalysis.Builder().build()
diff --git a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
index 795a095..15baf68 100644
--- a/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
+++ b/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/CameraXActivity.java
@@ -19,11 +19,6 @@
 import static androidx.camera.core.ImageCapture.FLASH_MODE_AUTO;
 import static androidx.camera.core.ImageCapture.FLASH_MODE_OFF;
 import static androidx.camera.core.ImageCapture.FLASH_MODE_ON;
-import static androidx.camera.video.QualitySelector.QUALITY_FHD;
-import static androidx.camera.video.QualitySelector.QUALITY_HD;
-import static androidx.camera.video.QualitySelector.QUALITY_NONE;
-import static androidx.camera.video.QualitySelector.QUALITY_SD;
-import static androidx.camera.video.QualitySelector.QUALITY_UHD;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_FILE_SIZE_LIMIT_REACHED;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE;
 import static androidx.camera.video.VideoRecordEvent.Finalize.ERROR_NONE;
@@ -94,6 +89,7 @@
 import androidx.camera.lifecycle.ProcessCameraProvider;
 import androidx.camera.video.MediaStoreOutputOptions;
 import androidx.camera.video.OutputOptions;
+import androidx.camera.video.Quality;
 import androidx.camera.video.QualitySelector;
 import androidx.camera.video.Recorder;
 import androidx.camera.video.Recording;
@@ -156,6 +152,7 @@
     private final AtomicLong mPreviewFrameCount = new AtomicLong(0);
     private final MutableLiveData<String> mImageAnalysisResult = new MutableLiveData<>();
     private static final String BACKWARD = "BACKWARD";
+    private static final Quality QUALITY_AUTO = null;
 
     private Recording mActiveRecording;
     /** The camera to use */
@@ -192,7 +189,7 @@
     private OpenGLRenderer mPreviewRenderer;
     private DisplayManager.DisplayListener mDisplayListener;
     private RecordUi mRecordUi;
-    private int mVideoQuality = QUALITY_NONE;
+    private Quality mVideoQuality;
 
     SessionImagesUriSet mSessionImagesUriSet = new SessionImagesUriSet();
 
@@ -423,21 +420,22 @@
             // Add Auto item
             final int groupId = Menu.NONE;
             final int autoOrder = 0;
-            menu.add(groupId, QUALITY_NONE, autoOrder, getQualityMenuItemName(QUALITY_NONE));
-            if (mVideoQuality == QUALITY_NONE) {
-                menu.findItem(QUALITY_NONE).setChecked(true);
+            final int autoMenuId = qualityToItemId(QUALITY_AUTO);
+            menu.add(groupId, autoMenuId, autoOrder, getQualityMenuItemName(QUALITY_AUTO));
+            if (mVideoQuality == QUALITY_AUTO) {
+                menu.findItem(autoMenuId).setChecked(true);
             }
 
             // Add device supported qualities
-            List<Integer> supportedQualities =
+            List<Quality> supportedQualities =
                     QualitySelector.getSupportedQualities(mCamera.getCameraInfo());
             // supportedQualities has been sorted by descending order.
             for (int i = 0; i < supportedQualities.size(); i++) {
-                int quality = supportedQualities.get(i);
-                menu.add(groupId, quality, autoOrder + 1 + i,
-                        getQualityMenuItemName(quality));
+                Quality quality = supportedQualities.get(i);
+                int itemId = qualityToItemId(quality);
+                menu.add(groupId, itemId, autoOrder + 1 + i, getQualityMenuItemName(quality));
                 if (mVideoQuality == quality) {
-                    menu.findItem(quality).setChecked(true);
+                    menu.findItem(itemId).setChecked(true);
                 }
 
             }
@@ -445,8 +443,9 @@
             menu.setGroupCheckable(groupId, true, true);
 
             popup.setOnMenuItemClickListener(item -> {
-                if (item.getItemId() != mVideoQuality) {
-                    mVideoQuality = item.getItemId();
+                Quality quality = itemIdToQuality(item.getItemId());
+                if (quality != mVideoQuality) {
+                    mVideoQuality = quality;
                     mRecordUi.getButtonQuality().setText(getQualityIconName(mVideoQuality));
                     // Quality changed, rebind UseCases
                     tryBindUseCases();
@@ -877,7 +876,7 @@
             mUseCases = useCases;
         } catch (IllegalArgumentException ex) {
             String msg;
-            if (mVideoQuality != QUALITY_NONE) {
+            if (mVideoQuality != QUALITY_AUTO) {
                 msg = "Bind too many use cases or video quality is too large.";
             } else {
                 msg = "Bind too many use cases.";
@@ -891,7 +890,7 @@
             mAnalysisToggle.setChecked(getImageAnalysis() != null);
             mVideoToggle.setChecked(getVideoCapture() != null);
             // Reset video quality to avoid always fail by quality too large.
-            mRecordUi.getButtonQuality().setText(getQualityIconName(mVideoQuality = QUALITY_NONE));
+            mRecordUi.getButtonQuality().setText(getQualityIconName(mVideoQuality = QUALITY_AUTO));
 
             if (!calledBySelf) {
                 // Only call self if not already calling self to avoid an infinite loop.
@@ -942,8 +941,8 @@
 
         if (mVideoToggle.isChecked()) {
             Recorder.Builder builder = new Recorder.Builder();
-            if (mVideoQuality != QUALITY_NONE) {
-                builder.setQualitySelector(QualitySelector.of(mVideoQuality));
+            if (mVideoQuality != QUALITY_AUTO) {
+                builder.setQualitySelector(QualitySelector.from(mVideoQuality));
             }
             VideoCapture<Recorder> videoCapture = VideoCapture.withOutput(builder.build());
             useCases.add(videoCapture);
@@ -1401,38 +1400,68 @@
     }
 
     @NonNull
-    private static String getQualityIconName(int quality) {
-        switch (quality) {
-            case QUALITY_NONE:
-                return "Auto";
-            case QUALITY_UHD:
-                return "UHD";
-            case QUALITY_FHD:
-                return "FHD";
-            case QUALITY_HD:
-                return "HD";
-            case QUALITY_SD:
-                return "SD";
-            default:
-                return "?";
+    private static String getQualityIconName(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return "Auto";
+        } else if (quality == Quality.UHD) {
+            return "UHD";
+        } else if (quality == Quality.FHD) {
+            return "FHD";
+        } else if (quality == Quality.HD) {
+            return "HD";
+        } else if (quality == Quality.SD) {
+            return "SD";
         }
+        return "?";
     }
 
     @NonNull
-    private static String getQualityMenuItemName(int quality) {
-        switch (quality) {
-            case QUALITY_NONE:
-                return "Auto";
-            case QUALITY_UHD:
-                return "UHD (2160P)";
-            case QUALITY_FHD:
-                return "FHD (1080P)";
-            case QUALITY_HD:
-                return "HD (720P)";
-            case QUALITY_SD:
-                return "SD (480P)";
+    private static String getQualityMenuItemName(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return "Auto";
+        } else if (quality == Quality.UHD) {
+            return "UHD (2160P)";
+        } else if (quality == Quality.FHD) {
+            return "FHD (1080P)";
+        } else if (quality == Quality.HD) {
+            return "HD (720P)";
+        } else if (quality == Quality.SD) {
+            return "SD (480P)";
+        }
+        return "Unknown quality";
+    }
+
+    private static int qualityToItemId(@Nullable Quality quality) {
+        if (quality == QUALITY_AUTO) {
+            return 0;
+        } else if (quality == Quality.UHD) {
+            return 1;
+        } else if (quality == Quality.FHD) {
+            return 2;
+        } else if (quality == Quality.HD) {
+            return 3;
+        } else if (quality == Quality.SD) {
+            return 4;
+        } else {
+            throw new IllegalArgumentException("Undefined quality: " + quality);
+        }
+    }
+
+    @Nullable
+    private static Quality itemIdToQuality(int itemId) {
+        switch (itemId) {
+            case 0:
+                return QUALITY_AUTO;
+            case 1:
+                return Quality.UHD;
+            case 2:
+                return Quality.FHD;
+            case 3:
+                return Quality.HD;
+            case 4:
+                return Quality.SD;
             default:
-                return "Unknown quality";
+                throw new IllegalArgumentException("Undefined item id: " + itemId);
         }
     }
 }
diff --git a/car/app/app-automotive/src/test/java/androidx/car/app/hardware/info/AutomotiveCarInfoTest.java b/car/app/app-automotive/src/test/java/androidx/car/app/hardware/info/AutomotiveCarInfoTest.java
index 55deed1..8bb3a03 100644
--- a/car/app/app-automotive/src/test/java/androidx/car/app/hardware/info/AutomotiveCarInfoTest.java
+++ b/car/app/app-automotive/src/test/java/androidx/car/app/hardware/info/AutomotiveCarInfoTest.java
@@ -224,9 +224,9 @@
         assertThat(tollCard.getCardState().getValue()).isEqualTo(TollCard.TOLLCARD_STATE_VALID);
     }
 
-    @Config(minSdk = 30)
+    @Config(maxSdk = 30)
     @Test
-    public void getTollCard_verifyResponseApi30() {
+    public void getTollCard_verifyResponseApi30() throws InterruptedException {
         AtomicReference<TollCard> loadedResult = new AtomicReference<>();
         OnCarDataAvailableListener<TollCard> listener = (data) -> {
             loadedResult.set(data);
diff --git a/car/app/app-samples/navigation/automotive/src/main/AndroidManifest.xml b/car/app/app-samples/navigation/automotive/src/main/AndroidManifest.xml
index a6c75ae..b199784 100644
--- a/car/app/app-samples/navigation/automotive/src/main/AndroidManifest.xml
+++ b/car/app/app-samples/navigation/automotive/src/main/AndroidManifest.xml
@@ -86,6 +86,11 @@
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
       <meta-data android:name="distractionOptimized" android:value="true"/>
     </activity>
 
diff --git a/car/app/app-samples/navigation/mobile/src/main/AndroidManifest.xml b/car/app/app-samples/navigation/mobile/src/main/AndroidManifest.xml
index 99e5e3d..1f0438d 100644
--- a/car/app/app-samples/navigation/mobile/src/main/AndroidManifest.xml
+++ b/car/app/app-samples/navigation/mobile/src/main/AndroidManifest.xml
@@ -60,6 +60,11 @@
         <action android:name="androidx.car.app.CarAppService" />
         <category android:name="androidx.car.app.category.NAVIGATION"/>
       </intent-filter>
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
     </service>
     <service
         android:name="androidx.car.app.sample.navigation.common.nav.NavigationService"
diff --git a/car/app/app-samples/showcase/automotive/src/main/AndroidManifest.xml b/car/app/app-samples/showcase/automotive/src/main/AndroidManifest.xml
index 8c6a8d6..e15984a 100644
--- a/car/app/app-samples/showcase/automotive/src/main/AndroidManifest.xml
+++ b/car/app/app-samples/showcase/automotive/src/main/AndroidManifest.xml
@@ -127,6 +127,12 @@
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
+
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
     </activity>
 
   </application>
diff --git a/car/app/app-samples/showcase/automotive/src/main/AndroidManifestWithSdkVersion.xml b/car/app/app-samples/showcase/automotive/src/main/AndroidManifestWithSdkVersion.xml
index 53e5dc9..54b62dca 100644
--- a/car/app/app-samples/showcase/automotive/src/main/AndroidManifestWithSdkVersion.xml
+++ b/car/app/app-samples/showcase/automotive/src/main/AndroidManifestWithSdkVersion.xml
@@ -134,6 +134,11 @@
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
     </activity>
 
   </application>
diff --git a/car/app/app-samples/showcase/common/build.gradle b/car/app/app-samples/showcase/common/build.gradle
index 830549e..c976cdc 100644
--- a/car/app/app-samples/showcase/common/build.gradle
+++ b/car/app/app-samples/showcase/common/build.gradle
@@ -29,7 +29,7 @@
     implementation(project(":car:app:app"))
 
     api(libs.kotlinStdlib) // Due to :annotation-experimental
-    implementation("androidx.core:core:1.6.0-alpha01")
+    implementation("androidx.core:core:1.7.0")
     implementation(project(":annotation:annotation-experimental"))
 }
 
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/RequestPermissionScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/RequestPermissionScreen.java
index 2362466..ad6e272 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/RequestPermissionScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/RequestPermissionScreen.java
@@ -18,8 +18,12 @@
 
 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
 
+import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.provider.Settings;
 
 import androidx.annotation.NonNull;
 import androidx.car.app.CarAppPermission;
@@ -33,6 +37,7 @@
 import androidx.car.app.model.OnClickListener;
 import androidx.car.app.model.ParkedOnlyOnClickListener;
 import androidx.car.app.model.Template;
+import androidx.core.location.LocationManagerCompat;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -131,10 +136,9 @@
                                 getCarContext(),
                                 String.format("Approved: %s Rejected: %s", approved, rejected),
                                 CarToast.LENGTH_LONG).show();
-                        finish();
                     });
             if (!getCarContext().getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE)) {
-                CarToast.makeText(getCarContext(), "Grant Permission on the phone",
+                CarToast.makeText(getCarContext(), "Grant Permission on the phone screen",
                         CarToast.LENGTH_LONG).show();
             }
         });
@@ -145,10 +149,39 @@
                 .setOnClickListener(listener)
                 .build();
 
-        return new LongMessageTemplate.Builder(message)
+
+        Action action2 = null;
+        LocationManager locationManager =
+                (LocationManager) getCarContext().getSystemService(Context.LOCATION_SERVICE);
+        if (!LocationManagerCompat.isLocationEnabled(locationManager)) {
+            message.append("Enable Location Permissions on device\n");
+            action2 = new Action.Builder()
+                    .setTitle("Enable Location")
+                    .setBackgroundColor(CarColor.BLUE)
+                    .setOnClickListener(ParkedOnlyOnClickListener.create(() -> {
+                        getCarContext().startActivity(
+                                new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS).addFlags(
+                                        Intent.FLAG_ACTIVITY_NEW_TASK));
+                        if (!getCarContext().getPackageManager().hasSystemFeature(
+                                FEATURE_AUTOMOTIVE)) {
+                            CarToast.makeText(getCarContext(), "Enable location on the phone "
+                                            + "screen",
+                                    CarToast.LENGTH_LONG).show();
+                        }
+                    }))
+                    .build();
+        }
+
+
+        LongMessageTemplate.Builder builder = new LongMessageTemplate.Builder(message)
                 .setTitle("Required Permissions")
                 .addAction(action)
-                .setHeaderAction(headerAction)
-                .build();
+                .setHeaderAction(headerAction);
+
+        if (action2 != null) {
+            builder.addAction(action2);
+        }
+
+        return builder.build();
     }
 }
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SearchTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SearchTemplateDemoScreen.java
index 27679a9..6f5a9e1 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SearchTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SearchTemplateDemoScreen.java
@@ -17,7 +17,6 @@
 package androidx.car.app.sample.showcase.common.templates;
 
 import static androidx.car.app.CarToast.LENGTH_LONG;
-import static androidx.car.app.CarToast.LENGTH_SHORT;
 
 import androidx.annotation.NonNull;
 import androidx.car.app.CarContext;
@@ -55,20 +54,10 @@
                 new SearchCallback() {
                     @Override
                     public void onSearchTextChanged(@NonNull String searchText) {
-                        CarToast.makeText(
-                                getCarContext(),
-                                "Search changed: " + searchText,
-                                LENGTH_SHORT)
-                                .show();
                     }
 
                     @Override
                     public void onSearchSubmitted(@NonNull String searchText) {
-                        CarToast.makeText(
-                                getCarContext(),
-                                "Search submitted: " + searchText,
-                                LENGTH_LONG)
-                                .show();
                     }
                 };
 
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
index ebdf4ab1..d5a23ef 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
@@ -69,7 +69,7 @@
             () -> getScreenManager().push(new LongMessageTemplateDemoScreen(getCarContext())));
 
     private final Action mProviderSignInAction = new Action.Builder()
-            .setTitle("Google Sign-In")
+            .setTitle("Google sign-in")
             .setOnClickListener(ParkedOnlyOnClickListener.create(() -> {
                 mState = State.PROVIDER;
                 invalidate();
diff --git a/car/app/app-samples/showcase/mobile/src/main/AndroidManifest.xml b/car/app/app-samples/showcase/mobile/src/main/AndroidManifest.xml
index 519d9ef..9972a0f 100644
--- a/car/app/app-samples/showcase/mobile/src/main/AndroidManifest.xml
+++ b/car/app/app-samples/showcase/mobile/src/main/AndroidManifest.xml
@@ -65,6 +65,11 @@
           <action android:name="androidx.car.app.CarAppService"/>
           <category android:name="androidx.car.app.category.NAVIGATION"/>
       </intent-filter>
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
     </service>
 
     <service
diff --git a/car/app/app-samples/showcase/mobile/src/main/AndroidManifestWithSdkVersion.xml b/car/app/app-samples/showcase/mobile/src/main/AndroidManifestWithSdkVersion.xml
index 9f6d52a..000a00c 100644
--- a/car/app/app-samples/showcase/mobile/src/main/AndroidManifestWithSdkVersion.xml
+++ b/car/app/app-samples/showcase/mobile/src/main/AndroidManifestWithSdkVersion.xml
@@ -72,6 +72,11 @@
           <action android:name="androidx.car.app.CarAppService"/>
           <category android:name="androidx.car.app.category.NAVIGATION"/>
       </intent-filter>
+      <intent-filter>
+        <action android:name="androidx.car.app.action.NAVIGATE" />
+        <category android:name="android.intent.category.DEFAULT"/>
+        <data android:scheme="geo" />
+      </intent-filter>
     </service>
 
     <service
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppPermissionActivity.java b/car/app/app/src/main/java/androidx/car/app/CarAppPermissionActivity.java
index aa165cf..664f64a 100644
--- a/car/app/app/src/main/java/androidx/car/app/CarAppPermissionActivity.java
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppPermissionActivity.java
@@ -137,8 +137,8 @@
                                 listener.onRequestPermissionsResult(granted.toArray(new String[0]),
                                         rejected.toArray(new String[0]));
                             } catch (RemoteException e) {
-                                // This is impossible since it is running in the same process.
-                                throw new IllegalStateException(e);
+                                Log.e(LogTags.TAG, "CarAppService dead when accepting/rejecting "
+                                        + "permissions", e);
                             }
 
                             finish();
diff --git a/collection2/collection2/src/commonMain/kotlin/androidx/collection/ArraySet.kt b/collection2/collection2/src/commonMain/kotlin/androidx/collection/ArraySet.kt
index cada5c3..d17909c 100644
--- a/collection2/collection2/src/commonMain/kotlin/androidx/collection/ArraySet.kt
+++ b/collection2/collection2/src/commonMain/kotlin/androidx/collection/ArraySet.kt
@@ -18,16 +18,46 @@
 
 import kotlin.jvm.JvmOverloads
 
+/**
+ * ArraySet is a generic set data structure that is designed to be more memory efficient than a
+ * traditional [HashSet].  The design is very similar to `ArrayMap`, with all of the caveats
+ * described there.  This implementation is separate from `ArrayMap`, however, so the array
+ * contains only one item for each entry in the set (instead of a pair for a mapping).
+ *
+ * Note that this implementation is not intended to be appropriate for data structures
+ * that may contain large numbers of items.  It is generally slower than a traditional
+ * [HashSet], since lookups require a binary search and adds and removes require inserting
+ * and deleting entries in the array.  For containers holding up to hundreds of items,
+ * the performance difference is not significant, less than 50%.
+ *
+ * Because this container is intended to better balance memory use, unlike most other
+ * standard Java containers it will shrink its array as items are removed from it.  Currently
+ * you have no control over this shrinking -- if you set a capacity and then remove an
+ * item, it may reduce the capacity to better match the current size.  In the future an
+ * explicit call to set the capacity should turn off this aggressive shrinking behavior.
+ *
+ * This structure is *NOT* thread-safe.
+ *
+ * @param capacity initial capacity of the set.  The default capacity of an array set is 0, and it
+ * will grow once items are added to it.
+ */
 class ArraySet<E>
 @JvmOverloads constructor(
     capacity: Int = 0
 ) : MutableCollection<E>, MutableSet<E> {
+
+    /**
+     * Create a new ArraySet with the elements from the given ArraySet.
+     */
     constructor(set: ArraySet<out E>?) : this(0) {
         if (set != null) {
             addAll(set)
         }
     }
 
+    /**
+     * Create a new ArraySet with the elements from the given [Collection].
+     */
     constructor(set: Collection<E>?) : this(0) {
         if (set != null) {
             addAll(set)
@@ -50,12 +80,20 @@
 
     private var _size: Int = 0
 
+    /**
+     * The number of items in this set.
+     */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
     open override val size: Int get() = _size
 
+    /**
+     * Return `true` if the set contains no items.
+     */
     override fun isEmpty(): Boolean = _size == 0
 
     /**
+     * Ensure the set can hold at least [minimumCapacity] items.
+     *
      * @throws ConcurrentModificationException if the set has been concurrently modified.
      */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
@@ -70,6 +108,12 @@
         }
     }
 
+    /**
+     * Returns the index of [element] in the set.
+     *
+     * @param element The value to search for.
+     * @return the index of [element] if it exists, else a negative integer.
+     */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
     open fun indexOf(element: E): Int {
         return if (element == null) {
@@ -132,10 +176,21 @@
         return end.inv()
     }
 
+    /**
+     * Return the value at the given index in the array.
+     *
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return the value stored at [index].
+     */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
     open fun valueAt(index: Int): E? = values[index]
 
     /**
+     * Adds the specified [element] to this set. The set is not modified if it
+     * already contains [element].
+     *
+     * @param element the object to add.
+     * @return `true` if this set is modified, `false` otherwise.
      * @throws ConcurrentModificationException if the set has been concurrently modified.
      */
     override fun add(element: E): Boolean {
@@ -194,6 +249,10 @@
         return true
     }
 
+    /**
+     * [add] all values in [elements]
+     * @param elements The collection whose contents are to be added.
+     */
     override fun addAll(elements: Collection<E>): Boolean {
         ensureCapacity(_size + elements.size)
         var added = false
@@ -203,6 +262,10 @@
         return added
     }
 
+    /**
+     * [add] all values in [elements]
+     * @param elements The array whose contents are to be added.
+     */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
     open fun addAll(elements: ArraySet<E>) {
         val arraySize = elements._size
@@ -219,6 +282,12 @@
         }
     }
 
+    /**
+     * Removes the specified [element] from this set.
+     *
+     * @param element the object to remove.
+     * @return `true` if this set is modified, `false` otherwise.
+     */
     override fun remove(element: E): Boolean {
         val index = indexOf(element)
         if (index >= 0) {
@@ -229,6 +298,10 @@
     }
 
     /**
+     * Remove the element at the given [index].
+     * @param index The desired index, must be between 0 and [size]-1.
+     * @return Returns the value that was stored at this [index].
+     *
      * @throws ConcurrentModificationException if the set has been concurrently modified.
      */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
@@ -304,6 +377,10 @@
         return value
     }
 
+    /**
+     * [remove] all values in [elements]
+     * @return `true` if any values were removed from the array set, else `false`.
+     */
     override fun removeAll(elements: Collection<E>): Boolean {
         var removed = false
         for (element in elements) {
@@ -312,6 +389,10 @@
         return removed
     }
 
+    /**
+     * [remove] all values in [elements]
+     * @return `true` if any values were removed from the array set, else `false`.
+     */
     @Suppress("NON_FINAL_MEMBER_IN_FINAL_CLASS") // For japicmp.
     open fun removeAll(elements: ArraySet<out E>): Boolean {
         // TODO: If array is sufficiently large, a marking approach might be beneficial. In a first
@@ -327,6 +408,9 @@
         return originalSize != _size
     }
 
+    /**
+     * Make the set empty.  All storage is released.
+     */
     override fun clear() {
         hashes = EMPTY_INTS
         @Suppress("UNCHECKED_CAST") // Empty array.
@@ -334,6 +418,12 @@
         _size = 0
     }
 
+    /**
+     * Remove all values in the array set that do *not* exist in the given [elements].
+     * @param elements The collection whose contents are to be used to determine which
+     * values to keep.
+     * @return `true` if any values were removed from the array set, else `false`.
+     */
     override fun retainAll(elements: Collection<E>): Boolean {
         var removed = false
         for (i in 0 until _size) {
@@ -345,12 +435,31 @@
         return removed
     }
 
+    /**
+     * Check whether a value exists in the set.
+     *
+     * @param element The value to search for.
+     * @return whether [element] exists in the set.
+     */
     override operator fun contains(element: E): Boolean = indexOf(element) >= 0
 
+    /**
+     * Determine if the array set contains all of the values in the given collection.
+     *
+     * @param elements The collection whose contents are to be checked against.
+     * @return `true` if this array set contains a value for every entry
+     * in [elements], else `false`.
+     */
     override fun containsAll(elements: Collection<E>): Boolean {
         return elements.all { it in this }
     }
 
+    /**
+     * Return an [MutableIterator] over all values in the set.
+     *
+     * *Note:* this is a less efficient way to access the array contents compared to
+     * looping from 0 until [size] and calling [valueAt].
+     */
     override fun iterator(): MutableIterator<E> {
         return Iterator(_size)
     }
@@ -365,6 +474,10 @@
     }
 
     private companion object {
+        /**
+         * The minimum amount by which the capacity of a [ArraySet] will increase.
+         * This is tuned to be relatively space-efficient.
+         */
         private const val BASE_SIZE = 4
         private const val BASE_SIZE_2X = BASE_SIZE * 2
     }
diff --git a/compose/animation/animation-graphics/api/1.1.0-beta04.txt b/compose/animation/animation-graphics/api/1.1.0-beta04.txt
index 5522e93..5f573e31 100644
--- a/compose/animation/animation-graphics/api/1.1.0-beta04.txt
+++ b/compose/animation/animation-graphics/api/1.1.0-beta04.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+  }
+
   public final class AnimatedVectorResources_androidKt {
   }
 
diff --git a/compose/animation/animation-graphics/api/current.txt b/compose/animation/animation-graphics/api/current.txt
index 5522e93..5f573e31 100644
--- a/compose/animation/animation-graphics/api/current.txt
+++ b/compose/animation/animation-graphics/api/current.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+  }
+
   public final class AnimatedVectorResources_androidKt {
   }
 
diff --git a/compose/animation/animation-graphics/api/public_plus_experimental_1.1.0-beta04.txt b/compose/animation/animation-graphics/api/public_plus_experimental_1.1.0-beta04.txt
index 7062c06..91d3cf3 100644
--- a/compose/animation/animation-graphics/api/public_plus_experimental_1.1.0-beta04.txt
+++ b/compose/animation/animation-graphics/api/public_plus_experimental_1.1.0-beta04.txt
@@ -8,8 +8,12 @@
 
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.painter.Painter rememberAnimatedVectorPainter(androidx.compose.animation.graphics.vector.AnimatedImageVector animatedImageVector, boolean atEnd);
+  }
+
   public final class AnimatedVectorResources_androidKt {
-    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.animation.graphics.vector.AnimatedImageVector animatedVectorResource(@DrawableRes int id);
+    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.animation.graphics.vector.AnimatedImageVector animatedVectorResource(androidx.compose.animation.graphics.vector.AnimatedImageVector.Companion, @DrawableRes int id);
   }
 
   public final class AnimatorResources_androidKt {
@@ -22,9 +26,12 @@
   @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Immutable public final class AnimatedImageVector {
     method public androidx.compose.ui.graphics.vector.ImageVector getImageVector();
     method public int getTotalDuration();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterFor(boolean atEnd);
     property public final androidx.compose.ui.graphics.vector.ImageVector imageVector;
     property public final int totalDuration;
+    field public static final androidx.compose.animation.graphics.vector.AnimatedImageVector.Companion Companion;
+  }
+
+  public static final class AnimatedImageVector.Companion {
   }
 
   public final class AnimatorKt {
diff --git a/compose/animation/animation-graphics/api/public_plus_experimental_current.txt b/compose/animation/animation-graphics/api/public_plus_experimental_current.txt
index 7062c06..91d3cf3 100644
--- a/compose/animation/animation-graphics/api/public_plus_experimental_current.txt
+++ b/compose/animation/animation-graphics/api/public_plus_experimental_current.txt
@@ -8,8 +8,12 @@
 
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.ui.graphics.painter.Painter rememberAnimatedVectorPainter(androidx.compose.animation.graphics.vector.AnimatedImageVector animatedImageVector, boolean atEnd);
+  }
+
   public final class AnimatedVectorResources_androidKt {
-    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.animation.graphics.vector.AnimatedImageVector animatedVectorResource(@DrawableRes int id);
+    method @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Composable public static androidx.compose.animation.graphics.vector.AnimatedImageVector animatedVectorResource(androidx.compose.animation.graphics.vector.AnimatedImageVector.Companion, @DrawableRes int id);
   }
 
   public final class AnimatorResources_androidKt {
@@ -22,9 +26,12 @@
   @androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi @androidx.compose.runtime.Immutable public final class AnimatedImageVector {
     method public androidx.compose.ui.graphics.vector.ImageVector getImageVector();
     method public int getTotalDuration();
-    method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.painter.Painter painterFor(boolean atEnd);
     property public final androidx.compose.ui.graphics.vector.ImageVector imageVector;
     property public final int totalDuration;
+    field public static final androidx.compose.animation.graphics.vector.AnimatedImageVector.Companion Companion;
+  }
+
+  public static final class AnimatedImageVector.Companion {
   }
 
   public final class AnimatorKt {
diff --git a/compose/animation/animation-graphics/api/restricted_1.1.0-beta04.txt b/compose/animation/animation-graphics/api/restricted_1.1.0-beta04.txt
index 5522e93..5f573e31 100644
--- a/compose/animation/animation-graphics/api/restricted_1.1.0-beta04.txt
+++ b/compose/animation/animation-graphics/api/restricted_1.1.0-beta04.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+  }
+
   public final class AnimatedVectorResources_androidKt {
   }
 
diff --git a/compose/animation/animation-graphics/api/restricted_current.txt b/compose/animation/animation-graphics/api/restricted_current.txt
index 5522e93..5f573e31 100644
--- a/compose/animation/animation-graphics/api/restricted_current.txt
+++ b/compose/animation/animation-graphics/api/restricted_current.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.compose.animation.graphics.res {
 
+  public final class AnimatedVectorPainterResources_androidKt {
+  }
+
   public final class AnimatedVectorResources_androidKt {
   }
 
diff --git a/compose/animation/animation-graphics/samples/src/main/java/androidx/compose/animation/graphics/samples/AnimatedVectorSample.kt b/compose/animation/animation-graphics/samples/src/main/java/androidx/compose/animation/graphics/samples/AnimatedVectorSample.kt
index e660d5b..722c4b2 100644
--- a/compose/animation/animation-graphics/samples/src/main/java/androidx/compose/animation/graphics/samples/AnimatedVectorSample.kt
+++ b/compose/animation/animation-graphics/samples/src/main/java/androidx/compose/animation/graphics/samples/AnimatedVectorSample.kt
@@ -20,6 +20,8 @@
 import androidx.annotation.Sampled
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
 import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.size
@@ -38,10 +40,10 @@
     @OptIn(ExperimentalAnimationGraphicsApi::class)
     @Composable
     fun AnimatedVector(@DrawableRes drawableId: Int) {
-        val image = animatedVectorResource(drawableId)
+        val image = AnimatedImageVector.animatedVectorResource(drawableId)
         var atEnd by remember { mutableStateOf(false) }
         Image(
-            painter = image.painterFor(atEnd),
+            painter = rememberAnimatedVectorPainter(image, atEnd),
             contentDescription = "Your content description",
             modifier = Modifier.size(64.dp).clickable {
                 atEnd = !atEnd
diff --git a/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorPainterResources.android.kt b/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorPainterResources.android.kt
new file mode 100644
index 0000000..68c3d6c
--- /dev/null
+++ b/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorPainterResources.android.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.animation.graphics.res
+
+import androidx.compose.animation.core.updateTransition
+import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.RenderVectorGroup
+import androidx.compose.ui.graphics.vector.VectorConfig
+import androidx.compose.ui.graphics.vector.VectorGroup
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+
+/**
+ * Creates and remembers a [Painter] to render an [AnimatedImageVector]. It renders the image
+ * either at the start or the end of all the animations depending on the [atEnd]. Changes to
+ * [atEnd] are animated.
+ *
+ * @param atEnd Whether the animated vector should be rendered at the end of all its animations.
+ *
+ * @sample androidx.compose.animation.graphics.samples.AnimatedVectorSample
+ */
+@ExperimentalAnimationGraphicsApi
+@Composable
+fun rememberAnimatedVectorPainter(
+    animatedImageVector: AnimatedImageVector,
+    atEnd: Boolean
+): Painter {
+    return rememberAnimatedVectorPainter(animatedImageVector, atEnd) { group, overrides ->
+        RenderVectorGroup(group, overrides)
+    }
+}
+
+@ExperimentalAnimationGraphicsApi
+@Composable
+private fun rememberAnimatedVectorPainter(
+    animatedImageVector: AnimatedImageVector,
+    atEnd: Boolean,
+    render: @Composable (VectorGroup, Map<String, VectorConfig>) -> Unit
+): Painter {
+    return rememberVectorPainter(
+        defaultWidth = animatedImageVector.imageVector.defaultWidth,
+        defaultHeight = animatedImageVector.imageVector.defaultHeight,
+        viewportWidth = animatedImageVector.imageVector.viewportWidth,
+        viewportHeight = animatedImageVector.imageVector.viewportHeight,
+        name = animatedImageVector.imageVector.name,
+        tintColor = animatedImageVector.imageVector.tintColor,
+        tintBlendMode = animatedImageVector.imageVector.tintBlendMode,
+    ) { _, _ ->
+        val transition = updateTransition(atEnd, label = animatedImageVector.imageVector.name)
+        render(
+            animatedImageVector.imageVector.root,
+            animatedImageVector.targets.associate { target ->
+                target.name to target.animator.createVectorConfig(
+                    transition,
+                    animatedImageVector.totalDuration
+                )
+            }
+        )
+    }
+}
diff --git a/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorResources.android.kt b/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorResources.android.kt
index b7f979c..64f61c3 100644
--- a/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorResources.android.kt
+++ b/compose/animation/animation-graphics/src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorResources.android.kt
@@ -20,19 +20,17 @@
 import android.util.Xml
 import androidx.annotation.DrawableRes
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
 import androidx.compose.animation.graphics.vector.AnimatedImageVector
 import androidx.compose.animation.graphics.vector.compat.parseAnimatedImageVector
 import androidx.compose.animation.graphics.vector.compat.seekToStartTag
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.platform.LocalContext
 import org.xmlpull.v1.XmlPullParserException
 
 /**
  * Load an [AnimatedImageVector] from an Android resource id.
  *
- * Note: This API is transient and will be likely removed for encouraging async resource loading.
- *
  * @param id the resource identifier
  * @return an animated vector drawable resource.
  *
@@ -40,7 +38,9 @@
  */
 @ExperimentalAnimationGraphicsApi
 @Composable
-fun animatedVectorResource(@DrawableRes id: Int): AnimatedImageVector {
+fun AnimatedImageVector.Companion.animatedVectorResource(
+    @DrawableRes id: Int
+): AnimatedImageVector {
     val context = LocalContext.current
     val res = context.resources
     val theme = context.theme
diff --git a/compose/animation/animation-graphics/src/commonMain/kotlin/androidx/compose/animation/graphics/vector/AnimatedImageVector.kt b/compose/animation/animation-graphics/src/commonMain/kotlin/androidx/compose/animation/graphics/vector/AnimatedImageVector.kt
index 57d7abdd..4567ab8 100644
--- a/compose/animation/animation-graphics/src/commonMain/kotlin/androidx/compose/animation/graphics/vector/AnimatedImageVector.kt
+++ b/compose/animation/animation-graphics/src/commonMain/kotlin/androidx/compose/animation/graphics/vector/AnimatedImageVector.kt
@@ -16,22 +16,15 @@
 
 package androidx.compose.animation.graphics.vector
 
-import androidx.compose.animation.core.updateTransition
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
-import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
-import androidx.compose.ui.graphics.painter.Painter
 import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.graphics.vector.RenderVectorGroup
-import androidx.compose.ui.graphics.vector.VectorGroup
-import androidx.compose.ui.graphics.vector.VectorConfig
-import androidx.compose.ui.graphics.vector.rememberVectorPainter
 import androidx.compose.ui.util.fastMaxBy
 
 /**
  * Animated vector graphics object that is generated as a result of
  * [androidx.compose.animation.graphics.res.loadAnimatedVectorResource].
- * It can be composed and rendered by [painterFor].
+ * It can be composed and rendered by `rememberAnimatedVectorPainter`.
  *
  * @param imageVector The [ImageVector] to be animated. This is represented with the
  * `android:drawable` parameter of an `<animated-vector>` element.
@@ -54,44 +47,9 @@
     }?.animator?.totalDuration ?: 0
 
     /**
-     * Creates and remembers a [Painter] to render this [AnimatedImageVector]. It renders the image
-     * either at the start or the end of all the animations depending on the [atEnd]. Changes to
-     * [atEnd] are animated.
-     *
-     * @param atEnd Whether the animated vector should be rendered at the end of all its animations.
-     *
-     * @sample androidx.compose.animation.graphics.samples.AnimatedVectorSample
+     * Provide an empty companion object to hang platform-specific companion extensions onto.
      */
-    @Composable
-    fun painterFor(atEnd: Boolean): Painter {
-        return painterFor(atEnd) { group, overrides ->
-            RenderVectorGroup(group, overrides)
-        }
-    }
-
-    @Composable
-    internal fun painterFor(
-        atEnd: Boolean,
-        render: @Composable (VectorGroup, Map<String, VectorConfig>) -> Unit
-    ): Painter {
-        return rememberVectorPainter(
-            defaultWidth = imageVector.defaultWidth,
-            defaultHeight = imageVector.defaultHeight,
-            viewportWidth = imageVector.viewportWidth,
-            viewportHeight = imageVector.viewportHeight,
-            name = imageVector.name,
-            tintColor = imageVector.tintColor,
-            tintBlendMode = imageVector.tintBlendMode,
-        ) { _, _ ->
-            val transition = updateTransition(atEnd, label = imageVector.name)
-            render(
-                imageVector.root,
-                targets.associate { target ->
-                    target.name to target.animator.createVectorConfig(transition, totalDuration)
-                }
-            )
-        }
-    }
+    companion object {} // ktlint-disable no-empty-class-body
 }
 
 /**
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVectorGraphicsDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVectorGraphicsDemo.kt
index 854a5d7..46dfdfc 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVectorGraphicsDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimatedVectorGraphicsDemo.kt
@@ -25,6 +25,8 @@
 import androidx.compose.animation.core.updateTransition
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
 import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
@@ -56,10 +58,10 @@
         verticalArrangement = Arrangement.SpaceEvenly,
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
-        val image = animatedVectorResource(R.drawable.ic_hourglass_animated)
+        val image = AnimatedImageVector.animatedVectorResource(R.drawable.ic_hourglass_animated)
         var atEnd by remember { mutableStateOf(false) }
         Image(
-            painter = image.painterFor(atEnd),
+            painter = rememberAnimatedVectorPainter(image, atEnd),
             contentDescription = "AnimatedImageVector",
             modifier = Modifier.size(200.dp).clickable {
                 atEnd = !atEnd
diff --git a/compose/benchmark-utils/OWNERS b/compose/benchmark-utils/OWNERS
index 305021a..b2c0d56 100644
--- a/compose/benchmark-utils/OWNERS
+++ b/compose/benchmark-utils/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 jellefresen@google.com
diff --git a/compose/foundation/foundation/api/1.1.0-beta04.txt b/compose/foundation/foundation/api/1.1.0-beta04.txt
index d5185f0..d890160 100644
--- a/compose/foundation/foundation/api/1.1.0-beta04.txt
+++ b/compose/foundation/foundation/api/1.1.0-beta04.txt
@@ -372,9 +372,6 @@
 
 package androidx.compose.foundation.lazy {
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -396,9 +393,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -410,15 +404,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -430,17 +415,11 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -472,9 +451,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -499,6 +475,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   public final class BringIntoViewRequesterKt {
diff --git a/compose/foundation/foundation/api/current.ignore b/compose/foundation/foundation/api/current.ignore
index a3cabae..1de8dc2 100644
--- a/compose/foundation/foundation/api/current.ignore
+++ b/compose/foundation/foundation/api/current.ignore
@@ -1,11 +1,17 @@
 // Baseline format: 1.0
-InvalidNullConversion: androidx.compose.foundation.ImageKt#Image(androidx.compose.ui.graphics.ImageBitmap, String, androidx.compose.ui.Modifier, androidx.compose.ui.Alignment, androidx.compose.ui.layout.ContentScale, float, androidx.compose.ui.graphics.ColorFilter) parameter #1:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter contentDescription in androidx.compose.foundation.ImageKt.Image(androidx.compose.ui.graphics.ImageBitmap bitmap, String contentDescription, androidx.compose.ui.Modifier modifier, androidx.compose.ui.Alignment alignment, androidx.compose.ui.layout.ContentScale contentScale, float alpha, androidx.compose.ui.graphics.ColorFilter colorFilter)
-
-
-RemovedClass: androidx.compose.foundation.gestures.RelativeVelocityTrackerKt:
-    Removed class androidx.compose.foundation.gestures.RelativeVelocityTrackerKt
-RemovedClass: androidx.compose.foundation.lazy.LazyListItemContentFactoryKt:
-    Removed class androidx.compose.foundation.lazy.LazyListItemContentFactoryKt
-RemovedClass: androidx.compose.foundation.lazy.LazyListPrefetcher_androidKt:
-    Removed class androidx.compose.foundation.lazy.LazyListPrefetcher_androidKt
+RemovedClass: androidx.compose.foundation.lazy.IntervalListKt:
+    Removed class androidx.compose.foundation.lazy.IntervalListKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListHeadersKt:
+    Removed class androidx.compose.foundation.lazy.LazyListHeadersKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListItemPlacementAnimatorKt:
+    Removed class androidx.compose.foundation.lazy.LazyListItemPlacementAnimatorKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListItemsProviderImplKt:
+    Removed class androidx.compose.foundation.lazy.LazyListItemsProviderImplKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListKt:
+    Removed class androidx.compose.foundation.lazy.LazyListKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListMeasureKt:
+    Removed class androidx.compose.foundation.lazy.LazyListMeasureKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListScrollingKt:
+    Removed class androidx.compose.foundation.lazy.LazyListScrollingKt
+RemovedClass: androidx.compose.foundation.lazy.LazySemanticsKt:
+    Removed class androidx.compose.foundation.lazy.LazySemanticsKt
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index d5185f0..d890160 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -372,9 +372,6 @@
 
 package androidx.compose.foundation.lazy {
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -396,9 +393,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -410,15 +404,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -430,17 +415,11 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -472,9 +451,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -499,6 +475,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   public final class BringIntoViewRequesterKt {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_1.1.0-beta04.txt b/compose/foundation/foundation/api/public_plus_experimental_1.1.0-beta04.txt
index 1e015d0..b9cf081 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_1.1.0-beta04.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_1.1.0-beta04.txt
@@ -427,9 +427,6 @@
     ctor public GridItemSpan();
   }
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -472,9 +469,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -486,15 +480,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -506,18 +491,12 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
     method @androidx.compose.foundation.ExperimentalFoundationApi public void stickyHeader(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -549,9 +528,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -576,6 +552,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   @androidx.compose.foundation.ExperimentalFoundationApi public sealed interface BringIntoViewRequester {
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 1e015d0..b9cf081 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -427,9 +427,6 @@
     ctor public GridItemSpan();
   }
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -472,9 +469,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -486,15 +480,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -506,18 +491,12 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
     method @androidx.compose.foundation.ExperimentalFoundationApi public void stickyHeader(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -549,9 +528,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -576,6 +552,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   @androidx.compose.foundation.ExperimentalFoundationApi public sealed interface BringIntoViewRequester {
diff --git a/compose/foundation/foundation/api/restricted_1.1.0-beta04.txt b/compose/foundation/foundation/api/restricted_1.1.0-beta04.txt
index d5185f0..d890160 100644
--- a/compose/foundation/foundation/api/restricted_1.1.0-beta04.txt
+++ b/compose/foundation/foundation/api/restricted_1.1.0-beta04.txt
@@ -372,9 +372,6 @@
 
 package androidx.compose.foundation.lazy {
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -396,9 +393,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -410,15 +404,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -430,17 +415,11 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -472,9 +451,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -499,6 +475,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   public final class BringIntoViewRequesterKt {
diff --git a/compose/foundation/foundation/api/restricted_current.ignore b/compose/foundation/foundation/api/restricted_current.ignore
index a3cabae..1de8dc2 100644
--- a/compose/foundation/foundation/api/restricted_current.ignore
+++ b/compose/foundation/foundation/api/restricted_current.ignore
@@ -1,11 +1,17 @@
 // Baseline format: 1.0
-InvalidNullConversion: androidx.compose.foundation.ImageKt#Image(androidx.compose.ui.graphics.ImageBitmap, String, androidx.compose.ui.Modifier, androidx.compose.ui.Alignment, androidx.compose.ui.layout.ContentScale, float, androidx.compose.ui.graphics.ColorFilter) parameter #1:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter contentDescription in androidx.compose.foundation.ImageKt.Image(androidx.compose.ui.graphics.ImageBitmap bitmap, String contentDescription, androidx.compose.ui.Modifier modifier, androidx.compose.ui.Alignment alignment, androidx.compose.ui.layout.ContentScale contentScale, float alpha, androidx.compose.ui.graphics.ColorFilter colorFilter)
-
-
-RemovedClass: androidx.compose.foundation.gestures.RelativeVelocityTrackerKt:
-    Removed class androidx.compose.foundation.gestures.RelativeVelocityTrackerKt
-RemovedClass: androidx.compose.foundation.lazy.LazyListItemContentFactoryKt:
-    Removed class androidx.compose.foundation.lazy.LazyListItemContentFactoryKt
-RemovedClass: androidx.compose.foundation.lazy.LazyListPrefetcher_androidKt:
-    Removed class androidx.compose.foundation.lazy.LazyListPrefetcher_androidKt
+RemovedClass: androidx.compose.foundation.lazy.IntervalListKt:
+    Removed class androidx.compose.foundation.lazy.IntervalListKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListHeadersKt:
+    Removed class androidx.compose.foundation.lazy.LazyListHeadersKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListItemPlacementAnimatorKt:
+    Removed class androidx.compose.foundation.lazy.LazyListItemPlacementAnimatorKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListItemsProviderImplKt:
+    Removed class androidx.compose.foundation.lazy.LazyListItemsProviderImplKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListKt:
+    Removed class androidx.compose.foundation.lazy.LazyListKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListMeasureKt:
+    Removed class androidx.compose.foundation.lazy.LazyListMeasureKt
+RemovedClass: androidx.compose.foundation.lazy.LazyListScrollingKt:
+    Removed class androidx.compose.foundation.lazy.LazyListScrollingKt
+RemovedClass: androidx.compose.foundation.lazy.LazySemanticsKt:
+    Removed class androidx.compose.foundation.lazy.LazySemanticsKt
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index d5185f0..d890160 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -372,9 +372,6 @@
 
 package androidx.compose.foundation.lazy {
 
-  public final class IntervalListKt {
-  }
-
   public final class LazyDslKt {
     method @androidx.compose.runtime.Composable public static void LazyColumn(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LazyRow(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.lazy.LazyListState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior flingBehavior, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit> content);
@@ -396,9 +393,6 @@
     method public androidx.compose.ui.Modifier fillParentMaxWidth(androidx.compose.ui.Modifier, optional float fraction);
   }
 
-  public final class LazyListHeadersKt {
-  }
-
   public interface LazyListItemInfo {
     method public int getIndex();
     method public Object getKey();
@@ -410,15 +404,6 @@
     property public abstract int size;
   }
 
-  public final class LazyListItemPlacementAnimatorKt {
-  }
-
-  public final class LazyListItemsProviderImplKt {
-  }
-
-  public final class LazyListKt {
-  }
-
   public interface LazyListLayoutInfo {
     method public int getTotalItemsCount();
     method public int getViewportEndOffset();
@@ -430,17 +415,11 @@
     property public abstract java.util.List<androidx.compose.foundation.lazy.LazyListItemInfo> visibleItemsInfo;
   }
 
-  public final class LazyListMeasureKt {
-  }
-
   @androidx.compose.foundation.lazy.LazyScopeMarker public interface LazyListScope {
     method public void item(optional Object? key, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit> content);
     method public void items(int count, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.lazy.LazyItemScope,? super java.lang.Integer,kotlin.Unit> itemContent);
   }
 
-  public final class LazyListScrollingKt {
-  }
-
   @androidx.compose.runtime.Stable public final class LazyListState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public LazyListState(optional int firstVisibleItemIndex, optional int firstVisibleItemScrollOffset);
     method public suspend Object? animateScrollToItem(int index, optional int scrollOffset, optional kotlin.coroutines.Continuation<? super kotlin.Unit> p);
@@ -472,9 +451,6 @@
   @kotlin.DslMarker public @interface LazyScopeMarker {
   }
 
-  public final class LazySemanticsKt {
-  }
-
   public final class Lazy_androidKt {
   }
 
@@ -499,6 +475,34 @@
 
 }
 
+package androidx.compose.foundation.lazy.list {
+
+  public final class IntervalListKt {
+  }
+
+  public final class LazyListHeadersKt {
+  }
+
+  public final class LazyListItemPlacementAnimatorKt {
+  }
+
+  public final class LazyListItemsProviderImplKt {
+  }
+
+  public final class LazyListKt {
+  }
+
+  public final class LazyListMeasureKt {
+  }
+
+  public final class LazyListScrollingKt {
+  }
+
+  public final class LazySemanticsKt {
+  }
+
+}
+
 package androidx.compose.foundation.relocation {
 
   public final class BringIntoViewRequesterKt {
diff --git a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/lazy/LazyListScrollingBenchmark.kt b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/lazy/LazyListScrollingBenchmark.kt
index 036d159..20133f1 100644
--- a/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/lazy/LazyListScrollingBenchmark.kt
+++ b/compose/foundation/foundation/benchmark/src/androidTest/java/androidx/compose/foundation/benchmark/lazy/LazyListScrollingBenchmark.kt
@@ -20,6 +20,8 @@
 import android.view.MotionEvent
 import android.view.View
 import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.FlingBehavior
+import androidx.compose.foundation.gestures.ScrollScope
 import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxHeight
@@ -165,7 +167,11 @@
     "LazyColumn",
     isVertical = true
 ) { state ->
-    LazyColumn(state = state, modifier = Modifier.requiredHeight(400.dp).fillMaxWidth()) {
+    LazyColumn(
+        state = state,
+        modifier = Modifier.requiredHeight(400.dp).fillMaxWidth(),
+        flingBehavior = NoFlingBehavior
+    ) {
         item {
             FirstLargeItem()
         }
@@ -179,7 +185,11 @@
     "LazyRow",
     isVertical = false
 ) { state ->
-    LazyRow(state = state, modifier = Modifier.requiredWidth(400.dp).fillMaxHeight()) {
+    LazyRow(
+        state = state,
+        modifier = Modifier.requiredWidth(400.dp).fillMaxHeight(),
+        flingBehavior = NoFlingBehavior
+    ) {
         item {
             FirstLargeItem()
         }
@@ -189,6 +199,12 @@
     }
 }
 
+private object NoFlingBehavior : FlingBehavior {
+    override suspend fun ScrollScope.performFling(initialVelocity: Float): Float {
+        return 0f
+    }
+}
+
 // TODO(b/169852102 use existing public constructs instead)
 private fun ComposeBenchmarkRule.toggleStateBenchmark(
     caseFactory: () -> ListRemeasureTestCase
@@ -205,6 +221,7 @@
             runWithTimingDisabled {
                 assertNoPendingChanges()
                 getTestCase().afterToggle()
+                assertNoPendingChanges()
             }
         }
     }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollAccessibilityTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollAccessibilityTest.kt
index 57511e1..4804278 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollAccessibilityTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollAccessibilityTest.kt
@@ -93,7 +93,7 @@
         }.let { composeView ->
             ViewCompat
                 .getAccessibilityDelegate(composeView)!!
-                .getAccessibilityNodeProvider(composeView)
+                .getAccessibilityNodeProvider(composeView)!!
                 .provider as AccessibilityNodeProvider
         }
 
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TransformableTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TransformableTest.kt
index 073fad1..3fb977b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TransformableTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/TransformableTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation
 
+import androidx.compose.animation.core.tween
 import androidx.compose.foundation.gestures.TransformableState
 import androidx.compose.foundation.gestures.rememberTransformableState
 import androidx.compose.foundation.gestures.animatePanBy
@@ -29,7 +30,9 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.InspectableValue
@@ -37,6 +40,7 @@
 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performTouchInput
@@ -47,6 +51,9 @@
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import org.junit.After
 import org.junit.Before
@@ -66,6 +73,8 @@
     @get:Rule
     val rule = createComposeRule()
 
+    private lateinit var scope: CoroutineScope
+
     @Before
     fun before() {
         isDebugInspectorInfoEnabled = true
@@ -76,6 +85,14 @@
         isDebugInspectorInfoEnabled = false
     }
 
+    private fun ComposeContentTestRule.setContentAndGetScope(content: @Composable () -> Unit) {
+        setContent {
+            val actualScope = rememberCoroutineScope()
+            SideEffect { scope = actualScope }
+            content()
+        }
+    }
+
     @Test
     fun transformable_zoomIn() {
         var cumulativeScale = 1.0f
@@ -564,6 +581,36 @@
     }
 
     @Test
+    fun transformable_animateCancelledUpdatesIsTransformInProgress() {
+        rule.mainClock.autoAdvance = false
+        val state = TransformableState { _, _, _ -> }
+        setTransformableContent {
+            Modifier.transformable(state)
+        }
+
+        lateinit var animateJob: Job
+
+        rule.runOnIdle {
+            assertThat(state.isTransformInProgress).isFalse()
+            animateJob = scope.launch {
+                state.animateZoomBy(4f, tween(1000))
+            }
+        }
+
+        rule.mainClock.advanceTimeBy(500)
+
+        rule.runOnIdle {
+            assertThat(state.isTransformInProgress).isTrue()
+        }
+
+        animateJob.cancel()
+
+        rule.runOnIdle {
+            assertThat(state.isTransformInProgress).isFalse()
+        }
+    }
+
+    @Test
     fun testInspectorValue() {
         rule.setContent {
             val state = rememberTransformableState { _, _, _ -> }
@@ -579,7 +626,7 @@
     }
 
     private fun setTransformableContent(getModifier: @Composable () -> Modifier) {
-        rule.setContent {
+        rule.setContentAndGetScope {
             Box(Modifier.size(600.dp).testTag(TEST_TAG).then(getModifier()))
         }
     }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyGridTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyGridTest.kt
index 439759c0d..92e395d 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyGridTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyGridTest.kt
@@ -29,6 +29,8 @@
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.list.scrollBy
+import androidx.compose.foundation.lazy.list.setContentWithTestViewConfiguration
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyArrangementsTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyArrangementsTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyArrangementsTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyArrangementsTest.kt
index c22018e..48bb5d9 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyArrangementsTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyArrangementsTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.layout.Arrangement
@@ -22,6 +22,10 @@
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyColumnTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyColumnTest.kt
index 4673083..563d2bd 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyColumnTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import android.os.Build
 import androidx.compose.foundation.AutoTestFrameClock
@@ -28,6 +28,10 @@
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyCustomKeysTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyCustomKeysTest.kt
similarity index 96%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyCustomKeysTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyCustomKeysTest.kt
index cfec1ba..fcb0408 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyCustomKeysTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyCustomKeysTest.kt
@@ -14,12 +14,18 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.itemsIndexed
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyItemStateRestoration.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyItemStateRestoration.kt
similarity index 96%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyItemStateRestoration.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyItemStateRestoration.kt
index 8604782..4178d65 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyItemStateRestoration.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyItemStateRestoration.kt
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListAnimateItemPlacementTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListAnimateItemPlacementTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
index dd77069..8ea615e 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListAnimateItemPlacementTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListAnimateItemPlacementTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.animation.core.FiniteAnimationSpec
 import androidx.compose.animation.core.LinearEasing
@@ -29,6 +29,13 @@
 import androidx.compose.foundation.layout.requiredHeightIn
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.requiredWidthIn
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListHeadersTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
similarity index 97%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListHeadersTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
index b45ea16..13b1f6d 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListHeadersTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListHeadersTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.layout.PaddingValues
@@ -22,6 +22,11 @@
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertIsDisplayed
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt
similarity index 96%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt
index d081014..143a455 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListLayoutInfoTest.kt
@@ -14,12 +14,17 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListLayoutInfo
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.getValue
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcherTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
similarity index 97%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcherTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
index 6c8a3e4..763ee14 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcherTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.AutoTestFrameClock
 import androidx.compose.foundation.ExperimentalFoundationApi
@@ -22,6 +22,9 @@
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Remeasurement
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListSlotsReuseTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt
similarity index 97%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListSlotsReuseTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt
index 8f626d0..f9d6f61 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListSlotsReuseTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListSlotsReuseTest.kt
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
index e48ffbb..2b161b6 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import android.os.Build
 import androidx.compose.animation.core.snap
@@ -39,6 +39,14 @@
 import androidx.compose.foundation.layout.requiredWidth
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.itemsIndexed
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt
index 9be61a2..5d0eea5 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsContentPaddingTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.animation.core.snap
 import androidx.compose.foundation.AutoTestFrameClock
@@ -25,6 +25,11 @@
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertHeightIsEqualTo
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsIndexedTest.kt
similarity index 95%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsIndexedTest.kt
index 78ad549..f104ca7 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsIndexedTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsIndexedTest.kt
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.itemsIndexed
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsReverseLayoutTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt
similarity index 97%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsReverseLayoutTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt
index 8ad1b08..3a47a97 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsReverseLayoutTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListsReverseLayoutTest.kt
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyNestedScrollingTest.kt
similarity index 98%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyNestedScrollingTest.kt
index 3670335..78a5fdc 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyNestedScrollingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyNestedScrollingTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.gestures.ScrollableState
 import androidx.compose.foundation.gestures.scrollable
@@ -24,6 +24,9 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyRowTest.kt
similarity index 94%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyRowTest.kt
index d6b11c6..69f89a5 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyRowTest.kt
@@ -14,13 +14,17 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollAccessibilityTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt
similarity index 96%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollAccessibilityTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt
index 7f03801..4cdc602 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollAccessibilityTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollAccessibilityTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import android.view.View
 import android.view.accessibility.AccessibilityNodeProvider
@@ -23,6 +23,10 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Alignment
@@ -90,7 +94,7 @@
         }.let { composeView ->
             ViewCompat
                 .getAccessibilityDelegate(composeView)!!
-                .getAccessibilityNodeProvider(composeView)
+                .getAccessibilityNodeProvider(composeView)!!
                 .provider as AccessibilityNodeProvider
         }
 
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
similarity index 93%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
index 689da8c..78d7333 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyScrollTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.AutoTestFrameClock
 import androidx.compose.foundation.ExperimentalFoundationApi
@@ -25,6 +25,11 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.MediumTest
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazySemanticsTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazySemanticsTest.kt
similarity index 96%
rename from compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazySemanticsTest.kt
rename to compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazySemanticsTest.kt
index a0b1bf3..e7fc7c84 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazySemanticsTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazySemanticsTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxHeight
@@ -22,6 +22,9 @@
 import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.requiredWidth
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.testTag
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/TempListUtils.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/TempListUtils.kt
index 0d55ea2..34d6bae 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/TempListUtils.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/TempListUtils.kt
@@ -25,6 +25,10 @@
 
 /**
  * Returns a list containing only elements matching the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastFilter(predicate: (T) -> Boolean): List<T> {
@@ -42,6 +46,10 @@
  *
  * Returns the specified [initial] value if the collection is empty.
  *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
+ *
  * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value.
  */
 @OptIn(ExperimentalContracts::class)
@@ -57,6 +65,10 @@
 /**
  * Returns a list containing the results of applying the given [transform] function
  * to each element in the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastMapIndexedNotNull(
@@ -73,6 +85,10 @@
 /**
  * Returns the largest value among all values produced by selector function applied to each element
  * in the collection or null if there are no elements.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R : Comparable<R>> List<T>.fastMaxOfOrNull(selector: (T) -> R): R? {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TransformableState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TransformableState.kt
index 5298664..1e5d2b7 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TransformableState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TransformableState.kt
@@ -245,8 +245,11 @@
     ): Unit = coroutineScope {
         transformMutex.mutateWith(transformScope, transformPriority) {
             isTransformingState.value = true
-            block()
-            isTransformingState.value = false
+            try {
+                block()
+            } finally {
+                isTransformingState.value = false
+            }
         }
     }
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
index b1af308..b78cfa9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyDsl.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.gestures.ScrollableDefaults
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.lazy.list.LazyList
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -259,3 +260,11 @@
         content = content
     )
 }
+
+/**
+ * This should create an object meeting following requirements:
+ * 1) objects created for the same index are equals and never equals for different indexes
+ * 2) this class is saveable via a default SaveableStateRegistry on the platform
+ * 3) this objects can't be equals to any object which could be provided by a user as a custom key
+ */
+internal expect fun getDefaultLazyKeyFor(index: Int): Any
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
index 5ba59cd..505a344 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyGrid.kt
@@ -23,6 +23,9 @@
 import androidx.compose.foundation.layout.BoxWithConstraints
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.lazy.list.IntervalHolder
+import androidx.compose.foundation.lazy.list.MutableIntervalList
+import androidx.compose.foundation.lazy.list.intervalForIndex
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Layout
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScope.kt
index f26ebe8..fc68dfe 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyItemScope.kt
@@ -21,18 +21,9 @@
 import androidx.compose.animation.core.VisibilityThreshold
 import androidx.compose.animation.core.spring
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Stable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.ParentDataModifier
-import androidx.compose.ui.platform.InspectorInfo
-import androidx.compose.ui.platform.InspectorValueInfo
-import androidx.compose.ui.platform.debugInspectorInfo
 import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
 
 /**
@@ -106,46 +97,3 @@
         )
     ): Modifier
 }
-
-internal data class LazyItemScopeImpl(
-    val density: Density,
-    val constraints: Constraints
-) : LazyItemScope {
-    private val maxWidth: Dp = with(density) { constraints.maxWidth.toDp() }
-    private val maxHeight: Dp = with(density) { constraints.maxHeight.toDp() }
-
-    override fun Modifier.fillParentMaxSize(fraction: Float) = size(
-        maxWidth * fraction,
-        maxHeight * fraction
-    )
-
-    override fun Modifier.fillParentMaxWidth(fraction: Float) =
-        width(maxWidth * fraction)
-
-    override fun Modifier.fillParentMaxHeight(fraction: Float) =
-        height(maxHeight * fraction)
-
-    @ExperimentalFoundationApi
-    override fun Modifier.animateItemPlacement(animationSpec: FiniteAnimationSpec<IntOffset>) =
-        this.then(AnimateItemPlacementModifier(animationSpec, debugInspectorInfo {
-            name = "animateItemPlacement"
-            value = animationSpec
-        }))
-}
-
-private class AnimateItemPlacementModifier(
-    val animationSpec: FiniteAnimationSpec<IntOffset>,
-    inspectorInfo: InspectorInfo.() -> Unit,
-) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
-    override fun Density.modifyParentData(parentData: Any?): Any = animationSpec
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other !is AnimateItemPlacementModifier) return false
-        return animationSpec != other.animationSpec
-    }
-
-    override fun hashCode(): Int {
-        return animationSpec.hashCode()
-    }
-}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
index 04c44c0..92e6f17 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
@@ -24,6 +24,12 @@
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchPolicy
 import androidx.compose.foundation.lazy.layout.LazyLayoutState
+import androidx.compose.foundation.lazy.list.DataIndex
+import androidx.compose.foundation.lazy.list.LazyListItemPlacementAnimator
+import androidx.compose.foundation.lazy.list.LazyListItemsProvider
+import androidx.compose.foundation.lazy.list.LazyListMeasureResult
+import androidx.compose.foundation.lazy.list.LazyListScrollPosition
+import androidx.compose.foundation.lazy.list.doSmoothScrollToItem
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.getValue
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/DataIndex.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/DataIndex.kt
similarity index 96%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/DataIndex.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/DataIndex.kt
index aa3c299..49dc44f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/DataIndex.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/DataIndex.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 /**
  * Represents an index in the list of items of lazy layout.
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/IntervalList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/IntervalList.kt
similarity index 97%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/IntervalList.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/IntervalList.kt
index 8e2f14d..2fd5787 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/IntervalList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/IntervalList.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 internal class IntervalHolder<T>(
     val startIndex: Int,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyItemScopeImpl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyItemScopeImpl.kt
new file mode 100644
index 0000000..f7262c5
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyItemScopeImpl.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.lazy.list
+
+import androidx.compose.animation.core.FiniteAnimationSpec
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ParentDataModifier
+import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.InspectorValueInfo
+import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+
+internal data class LazyItemScopeImpl(
+    val density: Density,
+    val constraints: Constraints
+) : LazyItemScope {
+    private val maxWidth: Dp = with(density) { constraints.maxWidth.toDp() }
+    private val maxHeight: Dp = with(density) { constraints.maxHeight.toDp() }
+
+    override fun Modifier.fillParentMaxSize(fraction: Float) = size(
+        maxWidth * fraction,
+        maxHeight * fraction
+    )
+
+    override fun Modifier.fillParentMaxWidth(fraction: Float) =
+        width(maxWidth * fraction)
+
+    override fun Modifier.fillParentMaxHeight(fraction: Float) =
+        height(maxHeight * fraction)
+
+    @ExperimentalFoundationApi
+    override fun Modifier.animateItemPlacement(animationSpec: FiniteAnimationSpec<IntOffset>) =
+        this.then(AnimateItemPlacementModifier(animationSpec, debugInspectorInfo {
+            name = "animateItemPlacement"
+            value = animationSpec
+        }))
+}
+
+private class AnimateItemPlacementModifier(
+    val animationSpec: FiniteAnimationSpec<IntOffset>,
+    inspectorInfo: InspectorInfo.() -> Unit,
+) : ParentDataModifier, InspectorValueInfo(inspectorInfo) {
+    override fun Density.modifyParentData(parentData: Any?): Any = animationSpec
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is AnimateItemPlacementModifier) return false
+        return animationSpec != other.animationSpec
+    }
+
+    override fun hashCode(): Int {
+        return animationSpec.hashCode()
+    }
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyList.kt
similarity index 98%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyList.kt
index 635c4af..46f14c3 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyList.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.assertNotNestingScrollableContainers
 import androidx.compose.foundation.clipScrollableContainer
@@ -28,6 +28,8 @@
 import androidx.compose.foundation.layout.calculateEndPadding
 import androidx.compose.foundation.layout.calculateStartPadding
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.foundation.lazy.layout.LazyLayout
 import androidx.compose.foundation.lazy.layout.LazyMeasurePolicy
 import androidx.compose.foundation.lazy.layout.rememberLazyLayoutPrefetchPolicy
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListHeaders.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListHeaders.kt
similarity index 98%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListHeaders.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListHeaders.kt
index 9816176..7355e96 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListHeaders.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListHeaders.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.ui.util.fastForEachIndexed
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimator.kt
similarity index 99%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimator.kt
index 11f4c1a..7243fbe 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemPlacementAnimator.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemPlacementAnimator.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.Spring
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProvider.kt
similarity index 94%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProvider.kt
index d721bff..1d03253 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProvider.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemsProvider
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProviderImpl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProviderImpl.kt
similarity index 91%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProviderImpl.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProviderImpl.kt
index e704e24..6eda8b9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProviderImpl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListItemsProviderImpl.kt
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.getDefaultLazyKeyFor
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.State
@@ -83,19 +86,11 @@
 }
 
 /**
- * This should create an object meeting following requirements:
- * 1) objects created for the same index are equals and never equals for different indexes
- * 2) this class is saveable via a default SaveableStateRegistry on the platform
- * 3) this objects can't be equals to any object which could be provided by a user as a custom key
- */
-internal expect fun getDefaultLazyKeyFor(index: Int): Any
-
-/**
  * Traverses the interval [list] in order to create a mapping from the key to the index for all
  * the indexes in the passed [range].
  * The returned map will not contain the values for intervals with no key mapping provided.
  */
-private fun generateKeyToIndexMap(
+internal fun generateKeyToIndexMap(
     range: IntRange,
     list: IntervalList<LazyListIntervalContent>
 ): Map<Any, Int> {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasure.kt
similarity index 99%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasure.kt
index 11e9300..ef95dd9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasure.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.ui.layout.MeasureResult
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasureResult.kt
similarity index 93%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasureResult.kt
index a1c3315..4f5d0003 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListMeasureResult.kt
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
+import androidx.compose.foundation.lazy.LazyListItemInfo
+import androidx.compose.foundation.lazy.LazyListLayoutInfo
 import androidx.compose.foundation.lazy.layout.LazyLayoutItemInfo
 import androidx.compose.foundation.lazy.layout.LazyLayoutMeasureResult
 import androidx.compose.ui.layout.MeasureResult
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScopeImpl.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScopeImpl.kt
similarity index 93%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScopeImpl.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScopeImpl.kt
index 4e9771e..8feb771 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScopeImpl.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScopeImpl.kt
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.foundation.lazy.LazyListScope
 import androidx.compose.runtime.Composable
 
 internal class LazyListScopeImpl : LazyListScope {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrollPosition.kt
similarity index 98%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrollPosition.kt
index 858a091..b51e2ee 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrollPosition.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.runtime.mutableStateOf
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrolling.kt
similarity index 98%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrolling.kt
index 1ddc32e..552a51e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyListScrolling.kt
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.AnimationState
 import androidx.compose.animation.core.animateTo
 import androidx.compose.animation.core.spring
+import androidx.compose.foundation.lazy.LazyListItemInfo
+import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.fastFirstOrNull
 import kotlin.coroutines.cancellation.CancellationException
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItem.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItem.kt
similarity index 98%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItem.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItem.kt
index 917f1cd..e35218f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItem.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItem.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.animation.core.FiniteAnimationSpec
+import androidx.compose.foundation.lazy.LazyListItemInfo
 import androidx.compose.foundation.lazy.layout.LazyLayoutPlaceable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.layout.Placeable
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItemProvider.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItemProvider.kt
similarity index 97%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItemProvider.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItemProvider.kt
index eda6892..030b5fb 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyMeasuredItemProvider.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazyMeasuredItemProvider.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.lazy.layout.LazyLayoutPlaceable
 import androidx.compose.foundation.lazy.layout.LazyLayoutPlaceablesProvider
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazySemantics.kt
similarity index 97%
rename from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt
rename to compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazySemantics.kt
index 8f949991..7ecbf46 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazySemantics.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/list/LazySemantics.kt
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.compose.foundation.lazy.list
 
 import androidx.compose.foundation.gestures.ScrollableState
 import androidx.compose.foundation.gestures.animateScrollBy
+import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.runtime.State
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.CollectionInfo
diff --git a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
index 2a9e88f..3ecc5c7 100644
--- a/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
+++ b/compose/foundation/foundation/src/desktopTest/kotlin/androidx/compose/foundation/ScrollbarTest.kt
@@ -33,13 +33,11 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.input.mouse.MouseScrollOrientation
-import androidx.compose.ui.input.mouse.MouseScrollUnit
-import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.ExperimentalTestApi
 import androidx.compose.ui.test.InternalTestApi
@@ -432,10 +430,10 @@
 
     @OptIn(InternalTestApi::class, ExperimentalComposeUiApi::class)
     private fun ComposeTestRule.performMouseScroll(x: Int, y: Int, delta: Float) {
-        (this as DesktopComposeTestRule).scene.sendPointerScrollEvent(
+        (this as DesktopComposeTestRule).scene.sendPointerEvent(
+            PointerEventType.Move,
             Offset(x.toFloat(), y.toFloat()),
-            MouseScrollUnit.Line(delta),
-            MouseScrollOrientation.Vertical
+            scrollDelta = Offset(x = 0f, y = delta)
         )
     }
 
diff --git a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/TapGestureDetectorTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/TapGestureDetectorTest.kt
index 844d010..c225449 100644
--- a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/TapGestureDetectorTest.kt
+++ b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/TapGestureDetectorTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.foundation.gestures
 
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.input.pointer.consumeDownChange
 import androidx.compose.ui.input.pointer.consumePositionChange
 import kotlinx.coroutines.delay
@@ -108,10 +109,12 @@
     /**
      * Clicking in the region should result in the callback being invoked.
      */
+    @OptIn(ExperimentalComposeUiApi::class)
     @Test
     fun normalTap() = util.executeInComposition {
         val down = down(5f, 5f)
         assertTrue(down.consumed.downChange)
+        assertTrue(down.isConsumed)
 
         assertTrue(pressed)
         assertFalse(tapped)
@@ -119,6 +122,7 @@
 
         val up = down.up(50)
         assertTrue(up.consumed.downChange)
+        assertTrue(up.isConsumed)
 
         assertTrue(tapped)
         assertTrue(released)
@@ -224,6 +228,7 @@
      * Pressing in the region, sliding out and then lifting should result in
      * the callback not being invoked
      */
+    @OptIn(ExperimentalComposeUiApi::class)
     @Test
     fun tapMiss() = util.executeInComposition {
         val up = down(5f, 5f)
@@ -235,6 +240,7 @@
         assertFalse(released)
         assertFalse(tapped)
         assertFalse(up.consumed.downChange)
+        assertFalse(up.isConsumed)
     }
 
     /**
@@ -467,9 +473,46 @@
         assertTrue(canceled)
     }
 
+    @OptIn(ExperimentalComposeUiApi::class)
+    @Test
+    fun consumedChange_MotionTap() = util.executeInComposition {
+        down(5f, 5f)
+            .moveTo(6f, 2f) {
+                consume()
+            }
+            .up(50)
+
+        assertFalse(tapped)
+        assertTrue(pressed)
+        assertFalse(released)
+        assertTrue(canceled)
+    }
+
+    /**
+     * Clicking in the region with the up already consumed should result in the callback not
+     * being invoked.
+     */
+    @OptIn(ExperimentalComposeUiApi::class)
+    @Test
+    fun consumedChange_upTap() = util.executeInComposition {
+        val down = down(5f, 5f)
+
+        assertFalse(tapped)
+        assertTrue(pressed)
+
+        down.up {
+            consume()
+        }
+
+        assertFalse(tapped)
+        assertFalse(released)
+        assertTrue(canceled)
+    }
+
     /**
      * Ensure that two-finger taps work.
      */
+    @OptIn(ExperimentalComposeUiApi::class)
     @Test
     fun twoFingerTap() = util.executeInComposition {
         val down = down(1f, 1f)
@@ -480,16 +523,19 @@
 
         val down2 = down(9f, 5f)
         assertFalse(down2.consumed.downChange)
+        assertFalse(down2.isConsumed)
 
         assertFalse(pressed)
 
         val up = down.up()
         assertFalse(up.consumed.downChange)
+        assertFalse(up.isConsumed)
         assertFalse(tapped)
         assertFalse(released)
 
         val up2 = down2.up()
         assertTrue(up2.consumed.downChange)
+        assertTrue(up2.isConsumed)
 
         assertTrue(tapped)
         assertTrue(released)
diff --git a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/lazy/MutableIntervalListTest.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/lazy/MutableIntervalListTest.kt
index d909f6a..e4aff73 100644
--- a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/lazy/MutableIntervalListTest.kt
+++ b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/lazy/MutableIntervalListTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.foundation.lazy.list.MutableIntervalList
+import androidx.compose.foundation.lazy.list.intervalForIndex
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/compose/integration-tests/demos/OWNERS b/compose/integration-tests/demos/OWNERS
index 49be039..cb0413de 100644
--- a/compose/integration-tests/demos/OWNERS
+++ b/compose/integration-tests/demos/OWNERS
@@ -1,4 +1,3 @@
-pavlis@google.com
 adamp@google.com
 mount@google.com
 popam@google.com
diff --git a/compose/integration-tests/demos/build.gradle b/compose/integration-tests/demos/build.gradle
index 00e53eb..cec8a8f 100644
--- a/compose/integration-tests/demos/build.gradle
+++ b/compose/integration-tests/demos/build.gradle
@@ -22,6 +22,7 @@
     implementation(project(":compose:foundation:foundation-layout"))
     implementation(project(":compose:integration-tests:demos:common"))
     implementation(project(":compose:material:material"))
+    implementation(project(":compose:material3:material3"))
     implementation(project(":compose:runtime:runtime"))
     implementation(project(":compose:ui:ui"))
 
diff --git a/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt b/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
index 6d4f247..0684a01 100644
--- a/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
+++ b/compose/integration-tests/demos/src/androidTest/java/androidx/compose/integration/demos/test/DemoTest.kt
@@ -41,6 +41,7 @@
 import androidx.test.filters.LargeTest
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -107,6 +108,8 @@
         navigateThroughAllDemos(SplitDemoCategories[2])
     }
 
+    // Broken: b/206811195
+    @Ignore
     @Test
     fun navigateThroughAllDemos_4() {
         navigateThroughAllDemos(SplitDemoCategories[3])
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoActivity.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoActivity.kt
index b438f13..0fa2230 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoActivity.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoActivity.kt
@@ -17,22 +17,23 @@
 package androidx.compose.integration.demos
 
 import android.app.Activity
-import android.content.Context
 import android.content.Intent
-import android.content.SharedPreferences
 import android.os.Bundle
 import android.view.View
 import android.view.Window
 import androidx.activity.OnBackPressedCallback
 import androidx.activity.OnBackPressedDispatcher
+import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.integration.demos.common.ActivityDemo
 import androidx.compose.integration.demos.common.Demo
 import androidx.compose.integration.demos.common.DemoCategory
-import androidx.compose.material.Colors
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.darkColors
-import androidx.compose.material.lightColors
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -45,12 +46,12 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalView
 import androidx.fragment.app.FragmentActivity
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleEventObserver
-import androidx.preference.PreferenceManager
 
 /**
  * Main [Activity] containing all Compose related demos.
@@ -75,18 +76,19 @@
             ) {
                 Navigator(AllDemosCategory, onBackPressedDispatcher, activityStarter)
             }
-            val demoColors = remember {
-                DemoColors().also {
-                    lifecycle.addObserver(
-                        LifecycleEventObserver { _, event ->
-                            if (event == Lifecycle.Event.ON_RESUME) {
-                                it.loadColorsFromSharedPreferences(this)
-                            }
-                        }
-                    )
+            val isDynamicThemeOn = remember { mutableStateOf(IsDynamicThemingAvailable) }
+            DisposableEffect(lifecycle) {
+                val obs = LifecycleEventObserver { _, event ->
+                    if (event == Lifecycle.Event.ON_RESUME) {
+                        isDynamicThemeOn.value = isDynamicThemeSettingOn(applicationContext)
+                    }
+                }
+                lifecycle.addObserver(obs)
+                onDispose {
+                    lifecycle.removeObserver(obs)
                 }
             }
-            DemoTheme(demoColors, window) {
+            DemoTheme(isDynamicThemeOn.value, window) {
                 val filteringMode = rememberSaveable(
                     saver = FilterMode.Saver(onBackPressedDispatcher)
                 ) {
@@ -122,19 +124,26 @@
 
 @Composable
 private fun DemoTheme(
-    demoColors: DemoColors,
+    isDynamicThemeOn: Boolean,
     window: Window,
     content: @Composable () -> Unit
 ) {
-    MaterialTheme(demoColors.colors) {
-        val statusBarColor = with(MaterialTheme.colors) {
-            (if (isLight) primaryVariant else Color.Black).toArgb()
+    val isDarkMode = isSystemInDarkTheme()
+
+    @Suppress("NewApi")
+    val colorScheme =
+        if (isDynamicThemeOn) {
+            val context = LocalContext.current
+            if (isDarkMode) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+        } else {
+            if (isDarkMode) darkColorScheme() else lightColorScheme()
         }
-        SideEffect {
-            window.statusBarColor = statusBarColor
-        }
-        content()
+
+    SideEffect {
+        window.statusBarColor =
+            (if (isDarkMode) Color.Black else colorScheme.inversePrimary).toArgb()
     }
+    MaterialTheme(colorScheme = colorScheme, content = content)
 }
 
 private class Navigator private constructor(
@@ -254,95 +263,3 @@
         )
     }
 }
-
-/**
- * Returns a [DemoColors] from the values saved to [SharedPreferences]. If a given color is
- * not present in the [SharedPreferences], its default value as defined in [Colors]
- * will be returned.
- */
-fun DemoColors.loadColorsFromSharedPreferences(context: Context) {
-    val sharedPreferences =
-        PreferenceManager.getDefaultSharedPreferences(context)
-
-    fun getColorsFromSharedPreferences(isLightTheme: Boolean): Colors {
-        val function = if (isLightTheme) ::reflectLightColors else ::reflectDarkColors
-        val parametersToSet = function.parameters.mapNotNull { parameter ->
-            val savedValue = sharedPreferences.getString(parameter.name + isLightTheme, "")
-            if (savedValue.isNullOrBlank()) {
-                null
-            } else {
-                // TODO: should be a Color(savedValue.toLong(16)) when b/154329050 is fixed
-                val parsedColor = savedValue.toLong(16)
-                parameter to parsedColor
-            }
-        }.toMap()
-        return function.callBy(parametersToSet)
-    }
-
-    light = getColorsFromSharedPreferences(true)
-    dark = getColorsFromSharedPreferences(false)
-}
-
-/**
- * TODO: remove after b/154329050 is fixed
- * Inline classes don't play well with reflection, so we want boxed classes for our
- * call to [lightColors].
- */
-internal fun reflectLightColors(
-    primary: Long = 0xFF6200EE,
-    primaryVariant: Long = 0xFF3700B3,
-    secondary: Long = 0xFF03DAC6,
-    secondaryVariant: Long = 0xFF018786,
-    background: Long = 0xFFFFFFFF,
-    surface: Long = 0xFFFFFFFF,
-    error: Long = 0xFFB00020,
-    onPrimary: Long = 0xFFFFFFFF,
-    onSecondary: Long = 0xFF000000,
-    onBackground: Long = 0xFF000000,
-    onSurface: Long = 0xFF000000,
-    onError: Long = 0xFFFFFFFF
-) = lightColors(
-    primary = Color(primary),
-    primaryVariant = Color(primaryVariant),
-    secondary = Color(secondary),
-    secondaryVariant = Color(secondaryVariant),
-    background = Color(background),
-    surface = Color(surface),
-    error = Color(error),
-    onPrimary = Color(onPrimary),
-    onSecondary = Color(onSecondary),
-    onBackground = Color(onBackground),
-    onSurface = Color(onSurface),
-    onError = Color(onError)
-)
-
-/**
- * TODO: remove after b/154329050 is fixed
- * Inline classes don't play well with reflection, so we want boxed classes for our
- * call to [darkColors].
- */
-internal fun reflectDarkColors(
-    primary: Long = 0xFFBB86FC,
-    primaryVariant: Long = 0xFF3700B3,
-    secondary: Long = 0xFF03DAC6,
-    background: Long = 0xFF121212,
-    surface: Long = 0xFF121212,
-    error: Long = 0xFFCF6679,
-    onPrimary: Long = 0xFF000000,
-    onSecondary: Long = 0xFF000000,
-    onBackground: Long = 0xFFFFFFFF,
-    onSurface: Long = 0xFFFFFFFF,
-    onError: Long = 0xFF000000
-) = darkColors(
-    primary = Color(primary),
-    primaryVariant = Color(primaryVariant),
-    secondary = Color(secondary),
-    background = Color(background),
-    surface = Color(surface),
-    error = Color(error),
-    onPrimary = Color(onPrimary),
-    onSecondary = Color(onSecondary),
-    onBackground = Color(onBackground),
-    onSurface = Color(onSurface),
-    onError = Color(onError)
-)
\ No newline at end of file
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
index 858fa8d..902fe64 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoApp.kt
@@ -18,10 +18,15 @@
 
 import androidx.compose.animation.Crossfade
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
@@ -31,28 +36,31 @@
 import androidx.compose.integration.demos.common.DemoCategory
 import androidx.compose.integration.demos.common.FragmentDemo
 import androidx.compose.integration.demos.common.allLaunchableDemos
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.Icon
-import androidx.compose.material.IconButton
-import androidx.compose.material.ListItem
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Scaffold
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.ArrowBack
 import androidx.compose.material.icons.filled.ArrowForward
 import androidx.compose.material.icons.filled.Search
 import androidx.compose.material.icons.filled.Settings
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SmallTopAppBar
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.unit.LayoutDirection
@@ -61,6 +69,7 @@
 import androidx.fragment.app.FragmentActivity
 import androidx.fragment.app.FragmentContainerView
 
+@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun DemoApp(
     currentDemo: Demo,
@@ -77,11 +86,14 @@
 
     var filterText by rememberSaveable { mutableStateOf("") }
 
+    val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() }
+
     Scaffold(
         topBar = {
             DemoAppBar(
                 title = backStackTitle,
-                navigationIcon = navigationIcon,
+                scrollBehavior = scrollBehavior,
+                navigationIcon = navigationIcon ?: {},
                 launchSettings = launchSettings,
                 isFiltering = isFiltering,
                 filterText = filterText,
@@ -89,7 +101,8 @@
                 onStartFiltering = onStartFiltering,
                 onEndFiltering = onEndFiltering
             )
-        }
+        },
+        modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
     ) { innerPadding ->
         val modifier = Modifier.padding(innerPadding)
         DemoContent(modifier, currentDemo, isFiltering, filterText, onNavigateToDemo, onNavigateUp)
@@ -106,7 +119,7 @@
     onNavigateUp: () -> Unit
 ) {
     Crossfade(isFiltering to currentDemo) { (filtering, demo) ->
-        Surface(modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
+        Surface(modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
             if (filtering) {
                 DemoFilter(
                     launchableDemos = AllDemosCategory.allLaunchableDemos(),
@@ -121,12 +134,26 @@
 }
 
 @Composable
+fun Material2LegacyTheme(content: @Composable () -> Unit) {
+    val material2Colors =
+        if (isSystemInDarkTheme()) {
+            androidx.compose.material.darkColors()
+        } else {
+            androidx.compose.material.lightColors()
+        }
+    androidx.compose.material.MaterialTheme(colors = material2Colors, content = content)
+}
+
+@Composable
 private fun DisplayDemo(demo: Demo, onNavigate: (Demo) -> Unit, onNavigateUp: () -> Unit) {
     when (demo) {
         is ActivityDemo<*> -> {
             /* should never get here as activity demos are not added to the backstack*/
         }
-        is ComposableDemo -> demo.content(onNavigateUp)
+        is ComposableDemo ->
+            // provide material 2 as well for interop, find a way to
+            // remove it when all demos migrated to m3
+            Material2LegacyTheme { demo.content(onNavigateUp) }
         is DemoCategory -> DisplayDemoCategory(demo, onNavigate)
         is FragmentDemo<*> -> {
             lateinit var view: FragmentContainerView
@@ -156,21 +183,16 @@
 }
 
 @Composable
-@OptIn(ExperimentalMaterialApi::class)
 private fun DisplayDemoCategory(category: DemoCategory, onNavigate: (Demo) -> Unit) {
-    // TODO: migrate to LazyColumn after b/175671850
+    // TODO: migrate to LazyColumn after DemoTests are rewritten to accommodate laziness
     Column(Modifier.verticalScroll(rememberScrollState())) {
         category.demos.forEach { demo ->
-            ListItem(
-                text = {
-                    Text(
-                        modifier = Modifier.height(56.dp)
-                            .wrapContentSize(Alignment.Center),
-                        text = demo.title
-                    )
-                },
-                modifier = Modifier.clickable { onNavigate(demo) }
-            )
+            ListItem(onClick = { onNavigate(demo) }) {
+                Text(
+                    modifier = Modifier.height(56.dp).wrapContentSize(Alignment.Center),
+                    text = demo.title
+                )
+            }
         }
     }
 }
@@ -179,7 +201,8 @@
 @Composable
 private fun DemoAppBar(
     title: String,
-    navigationIcon: @Composable (() -> Unit)?,
+    scrollBehavior: TopAppBarScrollBehavior,
+    navigationIcon: @Composable () -> Unit,
     isFiltering: Boolean,
     filterText: String,
     onFilter: (String) -> Unit,
@@ -191,13 +214,15 @@
         FilterAppBar(
             filterText = filterText,
             onFilter = onFilter,
-            onClose = onEndFiltering
+            onClose = onEndFiltering,
+            scrollBehavior = scrollBehavior
         )
     } else {
-        TopAppBar(
+        SmallTopAppBar(
             title = {
                 Text(title, Modifier.testTag(Tags.AppBarTitle))
             },
+            scrollBehavior = scrollBehavior,
             navigationIcon = navigationIcon,
             actions = {
                 AppBarIcons.Filter(onClick = onStartFiltering)
@@ -233,3 +258,20 @@
         }
     }
 }
+
+@Composable
+internal fun ListItem(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    content: @Composable (() -> Unit)
+) {
+    Box(
+        modifier
+            .heightIn(min = 48.dp)
+            .fillMaxWidth()
+            .clickable(onClick = onClick)
+            .padding(horizontal = 16.dp)
+            .wrapContentHeight(Alignment.CenterVertically),
+        contentAlignment = Alignment.CenterStart
+    ) { content() }
+}
\ No newline at end of file
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoColors.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoColors.kt
deleted file mode 100644
index 5bb3529..0000000
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoColors.kt
+++ /dev/null
@@ -1,41 +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.integration.demos
-
-import android.content.SharedPreferences
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material.Colors
-import androidx.compose.material.darkColors
-import androidx.compose.material.lightColors
-
-/**
- * Wrapper class that contains a light and dark [Colors], to allow saving and
- * restoring the entire light / dark theme to and from [SharedPreferences].
- */
-@Stable
-class DemoColors {
-    var light: Colors by mutableStateOf(lightColors())
-    var dark: Colors by mutableStateOf(darkColors())
-
-    val colors
-        @Composable get() = if (isSystemInDarkTheme()) dark else light
-}
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
index 957232c..62a05db 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoFilter.kt
@@ -17,7 +17,6 @@
 package androidx.compose.integration.demos
 
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
@@ -26,17 +25,16 @@
 import androidx.compose.foundation.text.BasicTextField
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.integration.demos.common.Demo
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.Icon
-import androidx.compose.material.IconButton
-import androidx.compose.material.ListItem
-import androidx.compose.material.LocalContentColor
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.material.TopAppBar
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.SmallTopAppBar
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.key
@@ -46,7 +44,6 @@
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.graphics.SolidColor
-import androidx.compose.ui.graphics.compositeOver
 import androidx.compose.ui.text.SpanStyle
 import androidx.compose.ui.text.buildAnnotatedString
 import androidx.compose.ui.text.withStyle
@@ -73,33 +70,30 @@
 }
 
 /**
- * [TopAppBar] with a text field allowing filtering all the demos.
+ * [SmallTopAppBar] with a text field allowing filtering all the demos.
  */
 @Composable
 fun FilterAppBar(
     filterText: String,
     onFilter: (String) -> Unit,
-    onClose: () -> Unit
+    onClose: () -> Unit,
+    scrollBehavior: TopAppBarScrollBehavior
 ) {
-    with(MaterialTheme.colors) {
-        val appBarColor = if (isLight) {
-            surface
-        } else {
-            // Blending primary over surface according to Material design guidance for brand
-            // surfaces in dark theme
-            primary.copy(alpha = 0.08f).compositeOver(surface)
-        }
-        TopAppBar(backgroundColor = appBarColor, contentColor = onSurface) {
-            IconButton(modifier = Modifier.align(Alignment.CenterVertically), onClick = onClose) {
+    SmallTopAppBar(
+        navigationIcon = {
+            IconButton(onClick = onClose) {
                 Icon(Icons.Filled.Close, null)
             }
+        },
+        title = {
             FilterField(
                 filterText,
                 onFilter,
-                Modifier.fillMaxWidth().align(Alignment.CenterVertically)
+                Modifier.fillMaxWidth()
             )
-        }
-    }
+        },
+        scrollBehavior = scrollBehavior
+    )
 }
 
 /**
@@ -131,13 +125,12 @@
  * [ListItem] that displays a [demo] and highlights any matches for [filterText] inside [Demo.title]
  */
 @Composable
-@OptIn(ExperimentalMaterialApi::class)
 private fun FilteredDemoListItem(
     demo: Demo,
     filterText: String,
     onNavigate: (Demo) -> Unit
 ) {
-    val primary = MaterialTheme.colors.primary
+    val primary = MaterialTheme.colorScheme.primary
     val annotatedString = buildAnnotatedString {
         val title = demo.title
         var currentIndex = 0
@@ -159,13 +152,11 @@
     }
     key(demo.title) {
         ListItem(
-            text = {
-                Text(
-                    modifier = Modifier.height(56.dp).wrapContentSize(Alignment.Center),
-                    text = annotatedString
-                )
-            },
-            modifier = Modifier.clickable { onNavigate(demo) }
-        )
+            onClick = { onNavigate(demo) }) {
+            Text(
+                modifier = Modifier.height(56.dp).wrapContentSize(Alignment.Center),
+                text = annotatedString
+            )
+        }
     }
 }
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoSettingsActivity.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoSettingsActivity.kt
index 3f0f540..e41e89c 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoSettingsActivity.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/DemoSettingsActivity.kt
@@ -17,21 +17,15 @@
 package androidx.compose.integration.demos
 
 import android.content.Context
-import android.content.SharedPreferences
+import android.os.Build
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
-import androidx.preference.EditTextPreference
-import androidx.preference.Preference
+import androidx.compose.integration.demos.DemoSettingsActivity.SettingsFragment
+import androidx.preference.CheckBoxPreference
 import androidx.preference.PreferenceCategory
 import androidx.preference.PreferenceFragmentCompat
 import androidx.preference.PreferenceManager
 import androidx.preference.plusAssign
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toArgb
-import androidx.compose.material.Colors
-import androidx.compose.material.darkColors
-import androidx.compose.material.lightColors
-import kotlin.reflect.full.memberProperties
 
 /**
  * Shell [AppCompatActivity] around [SettingsFragment], as we need a FragmentActivity subclass
@@ -56,371 +50,22 @@
                 screen += this
             }
 
-            general += Preference(context).apply {
-                title = "Shuffle all colors"
-                onPreferenceClickListener = Preference.OnPreferenceClickListener {
-                    generateRandomPalette().saveColors(context)
-                    requireActivity().finish()
-                    true
-                }
-            }
-
-            general += Preference(context).apply {
-                title = "Reset colors to default"
-                onPreferenceClickListener = Preference.OnPreferenceClickListener {
-                    val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
-                    sharedPreferences.edit().clear().apply()
-                    requireActivity().finish()
-                    true
-                }
-            }
-
-            val light = PreferenceCategory(context).apply {
-                title = "Light colors"
-                screen += this
-            }
-            // Create new Colors to resolve defaults
-            lightColors().forEachColorProperty { name, color ->
-                light += EditTextPreference(context).apply {
-                    key = name + true
-                    title = name
-                    // set the default value to be the default for Colors
-                    setDefaultValue(Integer.toHexString(color.toArgb()))
-                    summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()
-                }
-            }
-
-            val dark = PreferenceCategory(context).apply {
-                title = "Dark colors"
-                screen += this
-            }
-
-            darkColors().forEachColorProperty { name, color ->
-                dark += EditTextPreference(context).apply {
-                    key = name + false
-                    title = name
-                    // set the default value to be the default for Colors
-                    setDefaultValue(Integer.toHexString(color.toArgb()))
-                    summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()
-                }
+            general += CheckBoxPreference(context).apply {
+                title = "Dynamic theming (android S+)"
+                isEnabled = IsDynamicThemingAvailable
+                key = IsDynamicThemeOnKey
+                setDefaultValue(isDynamicThemeSettingOn(context))
             }
             preferenceScreen = screen
         }
     }
 }
 
-/**
- * Iterates over each color present in a given [Colors].
- *
- * @param action the action to take on each property, where name is the name of the property,
- * such as 'primary' for [Colors.primary], and color is the resolved [Color] of the
- * property.
- */
-private fun Colors.forEachColorProperty(action: (name: String, color: Color) -> Unit) {
-    Colors::class.memberProperties.forEach { property ->
-        val name = property.name
-        val color = property.get(this) as? Color ?: return@forEach
-        action(name, color)
-    }
+internal fun isDynamicThemeSettingOn(context: Context): Boolean {
+    return PreferenceManager
+        .getDefaultSharedPreferences(context)
+        .getBoolean(IsDynamicThemeOnKey, IsDynamicThemingAvailable)
 }
 
-/**
- * Persists the current [DemoColors] to [SharedPreferences].
- */
-private fun DemoColors.saveColors(context: Context) {
-    light.forEachColorProperty { name, color ->
-        PreferenceManager.getDefaultSharedPreferences(context)
-            .edit()
-            .putString(name + true, Integer.toHexString(color.toArgb()))
-            .apply()
-    }
-    dark.forEachColorProperty { name, color ->
-        PreferenceManager.getDefaultSharedPreferences(context)
-            .edit()
-            .putString(name + false, Integer.toHexString(color.toArgb()))
-            .apply()
-    }
-}
-
-/**
- * Generates a [DemoColors] with random [Colors.primary], [Colors.onPrimary],
- * [Colors.secondary] and [Colors.onSecondary] as random dark-on-light or light-on-dark
- * pairs. Other colors are kept from the baseline.
- */
-private fun generateRandomPalette(): DemoColors {
-    return DemoColors().apply {
-        val (lightPrimary, lightOnPrimary) = generateColorPair(true)
-        val (lightSecondary, lightOnSecondary) = generateColorPair(true)
-        light = lightColors(
-            primary = lightPrimary,
-            secondary = lightSecondary,
-            onPrimary = lightOnPrimary,
-            onSecondary = lightOnSecondary
-        )
-        val (darkPrimary, darkOnPrimary) = generateColorPair(false)
-        val (darkSecondary, darkOnSecondary) = generateColorPair(false)
-        dark = darkColors(
-            primary = darkPrimary,
-            secondary = darkSecondary,
-            onPrimary = darkOnPrimary,
-            onSecondary = darkOnSecondary
-        )
-    }
-}
-
-/**
- * Generate a random dark and light color from the palette, and returns either a dark-on-light
- * or light-on-dark color pair.
- */
-private fun generateColorPair(isLightTheme: Boolean): Pair<Color, Color> {
-    val darkColor = Color(DarkPaletteColors.random())
-    val lightColor = Color(LightPaletteColors.random())
-    return if (isLightTheme) {
-        darkColor to lightColor
-    } else {
-        lightColor to darkColor
-    }
-}
-
-// Colors taken from https://material.io/design/color -> 2014 Material Design color palettes
-val LightPaletteColors = listOf(
-    0xFFEF5350,
-    0xFFF44336,
-    0xFFE53935,
-    0xFFD32F2F,
-    0xFFC62828,
-    0xFFB71C1C,
-    0xFFFF5252,
-    0xFFFF1744,
-    0xFFD50000,
-    0xFFEC407A,
-    0xFFE91E63,
-    0xFFD81B60,
-    0xFFC2185B,
-    0xFFAD1457,
-    0xFF880E4F,
-    0xFFFF4081,
-    0xFFF50057,
-    0xFFC51162,
-    0xFFBA68C8,
-    0xFFAB47BC,
-    0xFF9C27B0,
-    0xFF8E24AA,
-    0xFF7B1FA2,
-    0xFF6A1B9A,
-    0xFF4A148C,
-    0xFFE040FB,
-    0xFFD500F9,
-    0xFFAA00FF,
-    0xFF9575CD,
-    0xFF7E57C2,
-    0xFF673AB7,
-    0xFF5E35B1,
-    0xFF512DA8,
-    0xFF4527A0,
-    0xFF311B92,
-    0xFF7C4DFF,
-    0xFF651FFF,
-    0xFF6200EA,
-    0xFF7986CB,
-    0xFF5C6BC0,
-    0xFF3F51B5,
-    0xFF3949AB,
-    0xFF303F9F,
-    0xFF283593,
-    0xFF1A237E,
-    0xFF536DFE,
-    0xFF3D5AFE,
-    0xFF304FFE,
-    0xFF1E88E5,
-    0xFF1976D2,
-    0xFF1565C0,
-    0xFF0D47A1,
-    0xFF448AFF,
-    0xFF2979FF,
-    0xFF2962FF,
-    0xFF0288D1,
-    0xFF0277BD,
-    0xFF01579B,
-    0xFF0091EA,
-    0xFF0097A7,
-    0xFF00838F,
-    0xFF006064,
-    0xFF009688,
-    0xFF00897B,
-    0xFF00796B,
-    0xFF00695C,
-    0xFF004D40,
-    0xFF43A047,
-    0xFF388E3C,
-    0xFF2E7D32,
-    0xFF1B5E20,
-    0xFF558B2F,
-    0xFF33691E,
-    0xFF827717,
-    0xFFE65100,
-    0xFFF4511E,
-    0xFFE64A19,
-    0xFFD84315,
-    0xFFBF360C,
-    0xFFFF3D00,
-    0xFFDD2C00,
-    0xFFA1887F,
-    0xFF8D6E63,
-    0xFF795548,
-    0xFF6D4C41,
-    0xFF5D4037,
-    0xFF4E342E,
-    0xFF3E2723,
-    0xFF757575,
-    0xFF616161,
-    0xFF424242,
-    0xFF212121,
-    0xFF78909C,
-    0xFF607D8B,
-    0xFF546E7A,
-    0xFF455A64,
-    0xFF37474F,
-    0xFF263238
-)
-
-val DarkPaletteColors = listOf(
-    0xFFFFCDD2,
-    0xFFEF9A9A,
-    0xFFE57373,
-    0xFFFF8A80,
-    0xFFF8BBD0,
-    0xFFF48FB1,
-    0xFFF06292,
-    0xFFFF80AB,
-    0xFFE1BEE7,
-    0xFFCE93D8,
-    0xFFEA80FC,
-    0xFFD1C4E9,
-    0xFFB39DDB,
-    0xFFB388FF,
-    0xFFC5CAE9,
-    0xFF9FA8DA,
-    0xFF8C9EFF,
-    0xFFBBDEFB,
-    0xFF90CAF9,
-    0xFF64B5F6,
-    0xFF42A5F5,
-    0xFF2196F3,
-    0xFF82B1FF,
-    0xFFB3E5FC,
-    0xFF81D4FA,
-    0xFF4FC3F7,
-    0xFF29B6F6,
-    0xFF03A9F4,
-    0xFF039BE5,
-    0xFF80D8FF,
-    0xFF40C4FF,
-    0xFF00B0FF,
-    0xFFB2EBF2,
-    0xFF80DEEA,
-    0xFF4DD0E1,
-    0xFF26C6DA,
-    0xFF00BCD4,
-    0xFF00ACC1,
-    0xFF84FFFF,
-    0xFF18FFFF,
-    0xFF00E5FF,
-    0xFF00B8D4,
-    0xFFB2DFDB,
-    0xFF80CBC4,
-    0xFF4DB6AC,
-    0xFF26A69A,
-    0xFFA7FFEB,
-    0xFF64FFDA,
-    0xFF1DE9B6,
-    0xFF00BFA5,
-    0xFFC8E6C9,
-    0xFFA5D6A7,
-    0xFF81C784,
-    0xFF66BB6A,
-    0xFF4CAF50,
-    0xFFB9F6CA,
-    0xFF69F0AE,
-    0xFF00E676,
-    0xFF00C853,
-    0xFFDCEDC8,
-    0xFFC5E1A5,
-    0xFFAED581,
-    0xFF9CCC65,
-    0xFF8BC34A,
-    0xFF7CB342,
-    0xFF689F38,
-    0xFFCCFF90,
-    0xFFB2FF59,
-    0xFF76FF03,
-    0xFF64DD17,
-    0xFFF0F4C3,
-    0xFFE6EE9C,
-    0xFFDCE775,
-    0xFFD4E157,
-    0xFFCDDC39,
-    0xFFC0CA33,
-    0xFFAFB42B,
-    0xFF9E9D24,
-    0xFFF4FF81,
-    0xFFEEFF41,
-    0xFFC6FF00,
-    0xFFAEEA00,
-    0xFFFFF9C4,
-    0xFFFFF59D,
-    0xFFFFF176,
-    0xFFFFEE58,
-    0xFFFFEB3B,
-    0xFFFDD835,
-    0xFFFBC02D,
-    0xFFF9A825,
-    0xFFF57F17,
-    0xFFFFFF8D,
-    0xFFFFFF00,
-    0xFFFFEA00,
-    0xFFFFD600,
-    0xFFFFECB3,
-    0xFFFFE082,
-    0xFFFFD54F,
-    0xFFFFCA28,
-    0xFFFFC107,
-    0xFFFFB300,
-    0xFFFFA000,
-    0xFFFF8F00,
-    0xFFFF6F00,
-    0xFFFFE57F,
-    0xFFFFD740,
-    0xFFFFC400,
-    0xFFFFAB00,
-    0xFFFFE0B2,
-    0xFFFFCC80,
-    0xFFFFB74D,
-    0xFFFFA726,
-    0xFFFF9800,
-    0xFFFB8C00,
-    0xFFF57C00,
-    0xFFEF6C00,
-    0xFFFFD180,
-    0xFFFFAB40,
-    0xFFFF9100,
-    0xFFFF6D00,
-    0xFFFFCCBC,
-    0xFFFFAB91,
-    0xFFFF8A65,
-    0xFFFF7043,
-    0xFFFF5722,
-    0xFFFF9E80,
-    0xFFFF6E40,
-    0xFFD7CCC8,
-    0xFFBCAAA4,
-    0xFFF5F5F5,
-    0xFFEEEEEE,
-    0xFFE0E0E0,
-    0xFFBDBDBD,
-    0xFF9E9E9E,
-    0xFFCFD8DC,
-    0xFFB0BEC5,
-    0xFF90A4AE,
-    0xFFFFFFFF
-)
\ No newline at end of file
+private const val IsDynamicThemeOnKey = "material3_isDynamicThemeOn"
+internal val IsDynamicThemingAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
\ No newline at end of file
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropUi.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropUi.kt
index 960a3c3..1ef5eae 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropUi.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/InteropUi.kt
@@ -34,6 +34,7 @@
 import androidx.appcompat.app.AppCompatActivity
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.Button
 import androidx.compose.material.ButtonDefaults
@@ -43,6 +44,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -181,7 +183,27 @@
     }
 }
 
-private object InteropUiSnippet6 {
+@Composable
+fun InteropUiSnippet6(showCautionIcon: Boolean) {
+    if (showCautionIcon) {
+        CautionIcon(/* ... */)
+    }
+}
+
+@Composable
+fun InteropUiSnippet7() {
+    var isEnabled by rememberSaveable { mutableStateOf(false) }
+
+    Column {
+        ImageWithEnabledOverlay(isEnabled)
+        ControlPanelWithToggle(
+            isEnabled = isEnabled,
+            onEnabledChanged = { isEnabled = it }
+        )
+    }
+}
+
+private object InteropUiSnippet8 {
     @Composable
     fun MyComposable() {
         BoxWithConstraints {
@@ -196,7 +218,7 @@
     }
 }
 
-private object InteropUiSnippet7 {
+private object InteropUiSnippet9 {
     // import androidx.compose.ui.platform.ComposeView
 
     class MyComposeAdapter : RecyclerView.Adapter<MyComposeViewHolder>() {
@@ -233,7 +255,7 @@
     }
 }
 
-private object InteropUiSnippet8 {
+private object InteropUiSnippet10 {
     // import androidx.compose.ui.platform.ViewCompositionStrategy
 
     class MyComposeViewHolder(
@@ -295,6 +317,21 @@
 private fun Icon() {
 }
 
+@Composable
+private fun CautionIcon() {
+}
+
+@Composable
+private fun ImageWithEnabledOverlay(isEnabled: Boolean) {
+}
+
+@Composable
+private fun ControlPanelWithToggle(
+    isEnabled: Boolean,
+    onEnabledChanged: (Boolean) -> Unit
+) {
+}
+
 private class WindowCompat {
     companion object {
         fun setDecorFitsSystemWindows(window: Any, bool: Boolean) {}
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
index 82f2c4a..ac91305 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/interoperability/Interoperability.kt
@@ -35,8 +35,8 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.LinearLayout
+import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
-import androidx.appcompat.app.AppCompatActivity
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.integration.docs.databinding.ExampleLayoutBinding
@@ -53,6 +53,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.ComposeView
 import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.compose.ui.viewinterop.AndroidViewBinding
 import androidx.lifecycle.MutableLiveData
@@ -66,7 +67,7 @@
  */
 
 private object InteropSnippet1 {
-    class ExampleActivity : AppCompatActivity() {
+    class ExampleActivity : ComponentActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
 
@@ -87,22 +88,34 @@
 private object InteropSnippet2 {
     class ExampleFragment : Fragment() {
 
+        private var _binding: FragmentExampleBinding? = null
+        // This property is only valid between onCreateView and onDestroyView.
+        private val binding get() = _binding!!
+
         override fun onCreateView(
             inflater: LayoutInflater,
             container: ViewGroup?,
             savedInstanceState: Bundle?
         ): View {
-            // Inflate the layout for this fragment
-            return inflater.inflate(
-                R.layout.fragment_example, container, false
-            ).apply {
-                findViewById<ComposeView>(R.id.compose_view).setContent {
+            _binding = FragmentExampleBinding.inflate(inflater, container, false)
+            val view = binding.root
+            binding.composeView.apply {
+                // Dispose of the Composition when the view's LifecycleOwner
+                // is destroyed
+                setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
+                setContent {
                     // In Compose world
                     MaterialTheme {
                         Text("Hello Compose!")
                     }
                 }
             }
+            return view
+        }
+
+        override fun onDestroyView() {
+            super.onDestroyView()
+            _binding = null
         }
     }
 }
@@ -116,6 +129,9 @@
             savedInstanceState: Bundle?
         ): View {
             return ComposeView(requireContext()).apply {
+                // Dispose of the Composition when the view's LifecycleOwner
+                // is destroyed
+                setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
                 setContent {
                     MaterialTheme {
                         // In Compose world
@@ -206,7 +222,7 @@
 
 /* ktlint-disable indent */
 private object InteropSnippet8 {
-    class ExampleActivity : AppCompatActivity() {
+    class ExampleActivity : ComponentActivity() {
         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             // get data from savedInstanceState
@@ -228,7 +244,7 @@
     }
 }
 
-private object InteropSnippet19 {
+private object InteropSnippet9 {
     @Composable
     fun SystemBroadcastReceiver(
         systemAction: String,
@@ -347,4 +363,18 @@
     }
 
     fun requireContext(): Context = TODO()
+
+    open fun onDestroyView() { }
+}
+
+private class FragmentExampleBinding {
+    val root: View = TODO()
+    var composeView: ComposeView
+    companion object {
+        fun inflate(
+            li: LayoutInflater,
+            container: ViewGroup?,
+            boolean: Boolean
+        ): FragmentExampleBinding { TODO() }
+    }
 }
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/resources/Resources.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/resources/Resources.kt
index c66d0c3..d317818 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/resources/Resources.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/resources/Resources.kt
@@ -25,6 +25,8 @@
 
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
 import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.Divider
 import androidx.compose.material.Icon
@@ -136,10 +138,10 @@
     // - res/drawable/animated_vector.xml
 
     // In your Compose code
-    val image = animatedVectorResource(id = R.drawable.animated_vector)
+    val image = AnimatedImageVector.animatedVectorResource(id = R.drawable.animated_vector)
     val atEnd by remember { mutableStateOf(false) }
     Icon(
-        painter = image.painterFor(atEnd = atEnd),
+        painter = rememberAnimatedVectorPainter(image, atEnd),
         contentDescription = null // decorative element
     )
 }
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
index d5a5c46..5c703e0 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/sideeffects/SideEffects.kt
@@ -238,7 +238,7 @@
 
         // Calculate high priority tasks only when the todoTasks or highPriorityKeywords
         // change, not on every recomposition
-        val highPriorityTasks by remember(todoTasks, highPriorityKeywords) {
+        val highPriorityTasks by remember {
             derivedStateOf { todoTasks.filter { it.containsWord(highPriorityKeywords) } }
         }
 
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
index 9e17c64..a8ed7dec2 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/state/State.kt
@@ -221,7 +221,7 @@
 
         // Logic to decide when to show the bottom bar
         val shouldShowBottomBar: Boolean
-            @Composable get() = /* ... */
+            get() = /* ... */
                 // DO NOT COPY IN DAC
                 false
 
diff --git a/compose/lint/internal-lint-checks/build.gradle b/compose/lint/internal-lint-checks/build.gradle
index 412cfb9..3039214 100644
--- a/compose/lint/internal-lint-checks/build.gradle
+++ b/compose/lint/internal-lint-checks/build.gradle
@@ -25,7 +25,6 @@
 dependencies {
     compileOnly(libs.androidLintApi)
     compileOnly(libs.kotlinStdlib)
-    api(project(":lint-checks"))
     implementation(project(":compose:lint:common"))
 
     testImplementation(project(":compose:lint:common-test"))
diff --git a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
index 89745e0..3bce32a 100644
--- a/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
+++ b/compose/lint/internal-lint-checks/src/main/java/androidx/compose/lint/ComposeIssueRegistry.kt
@@ -18,7 +18,6 @@
 
 package androidx.compose.lint
 
-import androidx.build.lint.AndroidXIssueRegistry
 import com.android.tools.lint.client.api.IssueRegistry
 import com.android.tools.lint.client.api.Vendor
 import com.android.tools.lint.detector.api.CURRENT_API
@@ -32,7 +31,7 @@
             ListIteratorDetector.ISSUE,
             ModifierInspectorInfoDetector.ISSUE,
             UnnecessaryLambdaCreationDetector.ISSUE,
-        ) + AndroidXIssueRegistry.Issues
+        )
     }
     override val vendor = Vendor(
         vendorName = "Jetpack Compose",
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SliderScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SliderScreenshotTest.kt
index dfbdacc..b282d58 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SliderScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/SliderScreenshotTest.kt
@@ -223,4 +223,27 @@
         }
         assertSliderAgainstGolden("rangeSlider_fullRange")
     }
+
+    @Test
+    @ExperimentalMaterialApi
+    fun rangeSliderTest_steps_customColors() {
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                var position by remember { mutableStateOf(30f..70f) }
+                RangeSlider(
+                    values = position,
+                    valueRange = 0f..100f,
+                    onValueChange = { position = it }, steps = 9,
+                    colors = SliderDefaults.colors(
+                        thumbColor = Color.Blue,
+                        activeTrackColor = Color.Red,
+                        inactiveTrackColor = Color.Yellow,
+                        activeTickColor = Color.Magenta,
+                        inactiveTickColor = Color.Cyan
+                    )
+                )
+            }
+        }
+        assertSliderAgainstGolden("rangeSlider_steps_customColors")
+    }
 }
\ No newline at end of file
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
index 49995ca..e0d0a92 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Checkbox.kt
@@ -54,6 +54,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
 import kotlin.math.floor
+import kotlin.math.max
 
 /**
  * <a href="https://material.io/components/checkboxes" class="external" target="_blank">Material Design checkbox</a>.
@@ -318,20 +319,29 @@
     val halfStrokeWidth = strokeWidth / 2.0f
     val stroke = Stroke(strokeWidth)
     val checkboxSize = size.width
-    drawRoundRect(
-        boxColor,
-        topLeft = Offset(strokeWidth, strokeWidth),
-        size = Size(checkboxSize - strokeWidth * 2, checkboxSize - strokeWidth * 2),
-        cornerRadius = CornerRadius(radius / 2),
-        style = Fill
-    )
-    drawRoundRect(
-        borderColor,
-        topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
-        size = Size(checkboxSize - strokeWidth, checkboxSize - strokeWidth),
-        cornerRadius = CornerRadius(radius),
-        style = stroke
-    )
+    if (boxColor == borderColor) {
+        drawRoundRect(
+            boxColor,
+            size = Size(checkboxSize, checkboxSize),
+            cornerRadius = CornerRadius(radius),
+            style = Fill
+        )
+    } else {
+        drawRoundRect(
+            boxColor,
+            topLeft = Offset(strokeWidth, strokeWidth),
+            size = Size(checkboxSize - strokeWidth * 2, checkboxSize - strokeWidth * 2),
+            cornerRadius = CornerRadius(max(0f, radius - strokeWidth)),
+            style = Fill
+        )
+        drawRoundRect(
+            borderColor,
+            topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
+            size = Size(checkboxSize - strokeWidth, checkboxSize - strokeWidth),
+            cornerRadius = CornerRadius(radius - halfStrokeWidth),
+            style = stroke
+        )
+    }
 }
 
 private fun DrawScope.drawCheck(
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Slider.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Slider.kt
index d7ad38c..4b99271 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Slider.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Slider.kt
@@ -678,17 +678,18 @@
             trackStrokeWidth,
             StrokeCap.Round
         )
-        tickFractions.groupBy { it > positionFractionEnd }.forEach { (afterFraction, list) ->
-            drawPoints(
-                list.map {
-                    Offset(lerp(sliderStart, sliderEnd, it).x, center.y)
-                },
-                PointMode.Points,
-                (if (afterFraction) inactiveTickColor else activeTickColor).value,
-                trackStrokeWidth,
-                StrokeCap.Round
-            )
-        }
+        tickFractions.groupBy { it > positionFractionEnd || it < positionFractionStart }
+            .forEach { (outsideFraction, list) ->
+                drawPoints(
+                    list.map {
+                        Offset(lerp(sliderStart, sliderEnd, it).x, center.y)
+                    },
+                    PointMode.Points,
+                    (if (outsideFraction) inactiveTickColor else activeTickColor).value,
+                    trackStrokeWidth,
+                    StrokeCap.Round
+                )
+            }
     }
 }
 
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index ce0c80e..5c90c17 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -305,14 +305,7 @@
   }
 
   public final class ScaffoldKt {
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.ScaffoldState scaffoldState, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? drawerContent, optional boolean drawerGesturesEnabled, optional androidx.compose.ui.graphics.Shape drawerShape, optional float drawerTonalElevation, optional long drawerContainerColor, optional long drawerContentColor, optional long drawerScrimColor, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
-    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.ScaffoldState rememberScaffoldState(optional androidx.compose.material3.DrawerState drawerState);
-  }
-
-  @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class ScaffoldState {
-    ctor public ScaffoldState(androidx.compose.material3.DrawerState drawerState);
-    method public androidx.compose.material3.DrawerState getDrawerState();
-    property public final androidx.compose.material3.DrawerState drawerState;
+    method @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void Scaffold(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> topBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> bottomBar, optional kotlin.jvm.functions.Function0<kotlin.Unit> floatingActionButton, optional int floatingActionButtonPosition, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.PaddingValues,kotlin.Unit> content);
   }
 
   public final class Strings_androidKt {
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt
new file mode 100644
index 0000000..e0eb904
--- /dev/null
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt
@@ -0,0 +1,85 @@
+/*
+ * 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.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Menu
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExtendedFloatingActionButton
+import androidx.compose.material3.FabPosition
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SmallTopAppBar
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Sampled
+@Composable
+fun SimpleScaffoldWithTopBar() {
+    val colors = listOf(
+        Color(0xFFffd7d7.toInt()),
+        Color(0xFFffe9d6.toInt()),
+        Color(0xFFfffbd0.toInt()),
+        Color(0xFFe3ffd9.toInt()),
+        Color(0xFFd0fff8.toInt())
+    )
+
+    Scaffold(
+        topBar = {
+            SmallTopAppBar(
+                title = { Text("Simple Scaffold Screen") },
+                navigationIcon = {
+                    IconButton(
+                        onClick = { /* "Open nav drawer" */ }
+                    ) {
+                        Icon(Icons.Filled.Menu, contentDescription = "Localized description")
+                    }
+                }
+            )
+        },
+        floatingActionButtonPosition = FabPosition.End,
+        floatingActionButton = {
+            ExtendedFloatingActionButton(
+                text = { Text("Inc") },
+                onClick = { /* fab click handler */ }
+            )
+        },
+        content = { innerPadding ->
+            LazyColumn(contentPadding = innerPadding) {
+                items(count = 100) {
+                    Box(
+                        Modifier
+                            .fillMaxWidth()
+                            .height(50.dp)
+                            .background(colors[it % colors.size])
+                    )
+                }
+            }
+        }
+    )
+}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/IconButtonScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/IconButtonScreenshotTest.kt
new file mode 100644
index 0000000..67f6d1e
--- /dev/null
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/IconButtonScreenshotTest.kt
@@ -0,0 +1,177 @@
+/*
+ * 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.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusProperties
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.hasClickAction
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performMouseInput
+import androidx.compose.ui.test.performTouchInput
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@OptIn(ExperimentalTestApi::class)
+class IconButtonScreenshotTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    @get:Rule
+    val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_MATERIAL3)
+
+    private val wrap = Modifier.wrapContentSize(Alignment.TopStart)
+    private val wrapperTestTag = "iconButtonWrapper"
+
+    @Test
+    fun iconButton_lightTheme() {
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                IconButton(onClick = { /* doSomething() */ }) {
+                    Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
+                }
+            }
+        }
+        assertAgainstGolden("iconButton_lightTheme")
+    }
+
+    @Test
+    fun iconButton_darkTheme() {
+        rule.setContent {
+            MaterialTheme(darkColorScheme()) {
+                Surface(modifier = Modifier.fillMaxSize()) {
+                    Box(wrap.testTag(wrapperTestTag)) {
+                        IconButton(onClick = { /* doSomething() */ }) {
+                            Icon(
+                                Icons.Filled.Favorite,
+                                contentDescription = "Localized description"
+                            )
+                        }
+                    }
+                }
+            }
+        }
+        assertAgainstGolden("iconButton_darkTheme")
+    }
+
+    @Test
+    fun iconButton_lightTheme_disabled() {
+
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                IconButton(onClick = { /* doSomething() */ }, enabled = false) {
+                    Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
+                }
+            }
+        }
+        assertAgainstGolden("iconButton_lightTheme_disabled")
+    }
+
+    @Test
+    fun iconButton_lightTheme_pressed() {
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                IconButton(onClick = { /* doSomething() */ }) {
+                    Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
+                }
+            }
+        }
+
+        rule.mainClock.autoAdvance = false
+        rule.onNode(hasClickAction())
+            .performTouchInput { down(center) }
+
+        rule.mainClock.advanceTimeByFrame()
+        rule.waitForIdle() // Wait for measure
+        rule.mainClock.advanceTimeBy(milliseconds = 200)
+
+        // Ripples are drawn on the RenderThread, not the main (UI) thread, so we can't wait for
+        // synchronization. Instead just wait until after the ripples are finished animating.
+        Thread.sleep(300)
+
+        assertAgainstGolden("iconButton_lightTheme_pressed")
+    }
+
+    @Test
+    fun iconButton_lightTheme_hovered() {
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                IconButton(onClick = { /* doSomething() */ }) {
+                    Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
+                }
+            }
+        }
+        rule.onNodeWithTag(wrapperTestTag).performMouseInput {
+            enter(center)
+        }
+
+        assertAgainstGolden("iconButton_lightTheme_hovered")
+    }
+
+    @Test
+    fun iconButton_lightTheme_focused() {
+        val focusRequester = FocusRequester()
+
+        rule.setMaterialContent {
+            Box(wrap.testTag(wrapperTestTag)) {
+                IconButton(onClick = { /* doSomething() */ },
+                    modifier = Modifier
+                        // Normally this is only focusable in non-touch mode, so let's force it to
+                        // always be focusable so we can test how it appears
+                        .focusProperties { canFocus = true }
+                        .focusRequester(focusRequester)
+                ) {
+                    Icon(Icons.Filled.Favorite, contentDescription = "Localized description")
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            focusRequester.requestFocus()
+        }
+
+        assertAgainstGolden("iconButton_lightTheme_focused")
+    }
+
+    private fun assertAgainstGolden(goldenName: String) {
+        rule.onNodeWithTag(wrapperTestTag)
+            .captureToImage()
+            .assertAgainstGolden(screenshotRule, goldenName)
+    }
+}
\ No newline at end of file
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
index ed666cb..1aee644 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Checkbox.kt
@@ -55,6 +55,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.util.lerp
 import kotlin.math.floor
+import kotlin.math.max
 
 /**
  * Material Design checkbox.
@@ -337,20 +338,29 @@
     val halfStrokeWidth = strokeWidth / 2.0f
     val stroke = Stroke(strokeWidth)
     val checkboxSize = size.width
-    drawRoundRect(
-        boxColor,
-        topLeft = Offset(strokeWidth, strokeWidth),
-        size = Size(checkboxSize - strokeWidth * 2, checkboxSize - strokeWidth * 2),
-        cornerRadius = CornerRadius(radius / 2),
-        style = Fill
-    )
-    drawRoundRect(
-        borderColor,
-        topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
-        size = Size(checkboxSize - strokeWidth, checkboxSize - strokeWidth),
-        cornerRadius = CornerRadius(radius),
-        style = stroke
-    )
+    if (boxColor == borderColor) {
+        drawRoundRect(
+            boxColor,
+            size = Size(checkboxSize, checkboxSize),
+            cornerRadius = CornerRadius(radius),
+            style = Fill
+        )
+    } else {
+        drawRoundRect(
+            boxColor,
+            topLeft = Offset(strokeWidth, strokeWidth),
+            size = Size(checkboxSize - strokeWidth * 2, checkboxSize - strokeWidth * 2),
+            cornerRadius = CornerRadius(max(0f, radius - strokeWidth)),
+            style = Fill
+        )
+        drawRoundRect(
+            borderColor,
+            topLeft = Offset(halfStrokeWidth, halfStrokeWidth),
+            size = Size(checkboxSize - strokeWidth, checkboxSize - strokeWidth),
+            cornerRadius = CornerRadius(radius - halfStrokeWidth),
+            style = stroke
+        )
+    }
 }
 
 private fun DrawScope.drawCheck(
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
index ba9daf7..cafed40 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
@@ -70,7 +70,10 @@
                     enabled = enabled,
                     role = Role.Button,
                     interactionSource = interactionSource,
-                    indication = rememberRipple(bounded = false, radius = RippleRadius)
+                    indication = rememberRipple(
+                        bounded = false,
+                        radius = IconButton.StateLayerSize / 2
+                    )
                 ),
         contentAlignment = Alignment.Center
     ) {
@@ -121,7 +124,10 @@
                     enabled = enabled,
                     role = Role.Checkbox,
                     interactionSource = interactionSource,
-                    indication = rememberRipple(bounded = false, radius = RippleRadius)
+                    indication = rememberRipple(
+                        bounded = false,
+                        radius = IconButton.StateLayerSize / 2
+                    )
                 ),
         contentAlignment = Alignment.Center
     ) {
@@ -134,6 +140,3 @@
         CompositionLocalProvider(LocalContentColor provides contentColor, content = content)
     }
 }
-
-// Default radius of an unbounded ripple in an IconButton
-private val RippleRadius = IconButton.StateLayerSize
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt
index 8609e2f..8c618ca 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt
@@ -16,21 +16,14 @@
 
 package androidx.compose.material3
 
-import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.tokens.NavigationDrawer
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.remember
 import androidx.compose.runtime.staticCompositionLocalOf
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.layout.SubcomposeLayout
-import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 
@@ -43,26 +36,17 @@
  * screen, by ensuring proper layout strategy for them and collecting necessary data so these
  * components will work together correctly.
  *
+ * Simple example of a Scaffold with [SmallTopAppBar], [FloatingActionButton]:
+ *
+ * @sample androidx.compose.material3.samples.SimpleScaffoldWithTopBar
+ *
  * @param modifier optional Modifier for the root of the [Scaffold]
- * @param scaffoldState state of this scaffold widget. It contains the state of the screen, e.g.
- * variables to provide manual control over the drawer behavior, sizes of components, etc
  * @param topBar top app bar of the screen. Consider using [SmallTopAppBar].
  * @param bottomBar bottom bar of the screen. Consider using [NavigationBar].
  * @param floatingActionButton Main action button of your screen. Consider using
  * [FloatingActionButton] for this slot.
  * @param floatingActionButtonPosition position of the FAB on the screen. See [FabPosition] for
  * possible options available.
- * @param drawerContent content of the Drawer sheet that can be pulled from the left side (right
- * for RTL).
- * @param drawerGesturesEnabled whether or not drawer (if set) can be interacted with via gestures
- * @param drawerShape shape of the drawer sheet (if set)
- * @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
- * 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 drawerScrimColor color of the scrim that obscures content when the drawer is open
  * @param containerColor background of the scaffold body
  * @param contentColor color of the content in scaffold body. Defaults to either the matching
  * content color for [containerColor], or, if it is not a color from the theme, this will keep
@@ -72,56 +56,27 @@
  * you're using Modifier.VerticalScroll, apply this modifier to the child of the scroll, and not on
  * the scroll itself.
  */
-// TODO(b/198144133): Add Simple example of a Scaffold with [SmallTopAppBar], [FloatingActionButton]
-//  and [Navigation drawer].
 @ExperimentalMaterial3Api
 @Composable
 fun Scaffold(
     modifier: Modifier = Modifier,
-    scaffoldState: ScaffoldState = rememberScaffoldState(),
     topBar: @Composable () -> Unit = {},
     bottomBar: @Composable () -> Unit = {},
     floatingActionButton: @Composable () -> Unit = {},
     floatingActionButtonPosition: FabPosition = FabPosition.End,
-    drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
-    drawerGesturesEnabled: Boolean = true,
-    drawerShape: Shape = RoundedCornerShape(16.dp),
-    drawerTonalElevation: Dp = DrawerDefaults.Elevation,
-    drawerContainerColor: Color =
-        MaterialTheme.colorScheme.fromToken(NavigationDrawer.ContainerColor),
-    drawerContentColor: Color = contentColorFor(drawerContainerColor),
-    drawerScrimColor: Color = DrawerDefaults.scrimColor,
     containerColor: Color = MaterialTheme.colorScheme.background,
     contentColor: Color = contentColorFor(containerColor),
     content: @Composable (PaddingValues) -> Unit
 ) {
-    val child = @Composable { childModifier: Modifier ->
-        Surface(modifier = childModifier, color = containerColor, contentColor = contentColor) {
-            ScaffoldLayout(
-                fabPosition = floatingActionButtonPosition,
-                topBar = topBar,
-                bottomBar = bottomBar,
-                content = content,
-                fab = floatingActionButton
-            )
-        }
-    }
 
-    if (drawerContent != null) {
-        NavigationDrawer(
-            modifier = modifier,
-            drawerState = scaffoldState.drawerState,
-            gesturesEnabled = drawerGesturesEnabled,
-            drawerContent = drawerContent,
-            drawerShape = drawerShape,
-            drawerTonalElevation = drawerTonalElevation,
-            drawerContainerColor = drawerContainerColor,
-            drawerContentColor = drawerContentColor,
-            scrimColor = drawerScrimColor,
-            content = { child(Modifier) }
+    Surface(modifier = modifier, color = containerColor, contentColor = contentColor) {
+        ScaffoldLayout(
+            fabPosition = floatingActionButtonPosition,
+            topBar = topBar,
+            bottomBar = bottomBar,
+            content = content,
+            fab = floatingActionButton
         )
-    } else {
-        child(modifier)
     }
 }
 
@@ -234,33 +189,6 @@
 }
 
 /**
- * State for [Scaffold] composable component.
- *
- * Contains basic screen state, e.g. Drawer configuration, as well as sizes of components after
- * layout has happened
- *
- * @param drawerState the drawer state
- */
-@Stable
-@ExperimentalMaterial3Api
-class ScaffoldState(
-    val drawerState: DrawerState,
-)
-
-/**
- * Creates a [ScaffoldState] with the default animation clock and memoizes it.
- *
- * @param drawerState the drawer state
- */
-@ExperimentalMaterial3Api
-@Composable
-fun rememberScaffoldState(
-    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
-): ScaffoldState = remember {
-    ScaffoldState(drawerState)
-}
-
-/**
  * The possible positions for a [FloatingActionButton] attached to a [Scaffold].
  */
 // TODO(b/200553810): Mark as experimental
diff --git a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetector.kt b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetector.kt
new file mode 100644
index 0000000..896c7bf
--- /dev/null
+++ b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetector.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.compose.runtime.lint
+
+import androidx.compose.lint.Names
+import androidx.compose.lint.isInPackageName
+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.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.kotlin.descriptors.containingPackage
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.typeUtil.supertypes
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.kotlin.KotlinUastResolveProviderService
+import java.util.EnumSet
+
+/**
+ * [Detector] that checks `mutableStateOf` calls to warn if the type is a mutable collection, as
+ * mutations to the mutable collection inside the state won't cause invalidations. Instead, it is
+ * recommended to use mutableStateListOf / mutableStateMapOf for observable mutable collections, or
+ * mutableStateOf with a read-only collection inside, and assigning a new instance when the data
+ * changes.
+ */
+class MutableCollectionMutableStateDetector : Detector(), SourceCodeScanner {
+    override fun getApplicableMethodNames(): List<String> = listOf(
+        Names.Runtime.MutableStateOf.shortName
+    )
+
+    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+        if (!method.isInPackageName(Names.Runtime.PackageName)) return
+
+        val expression = node.sourcePsi as? KtExpression ?: return
+
+        // PsiType will return the underlying JVM type for kotlin collections, so instead we need to
+        // use the KotlinType to preserve the actual Kotlin type declared in source - that way we
+        // can disambiguate between MutableList and the underlying java.util.List that it will be
+        // converted to.
+        val service = expression.project.getService(KotlinUastResolveProviderService::class.java)
+        val bindingContext = service.getBindingContext(expression)
+        val expressionType = bindingContext.getType(expression)
+
+        // expressionType will be MutableState<Foo>, so unwrap the argument to get the type we care
+        // about. We do this instead of looking at the inner expression type, to account for cases
+        // such as mutableStateOf<List<Int>>(mutableListOf(1)) or
+        // val foo: MutableState<List<Int>> = mutableStateOf(mutableListOf(1)) - the inner
+        // expression type is mutable but because the type of the mutableStateOf expression is not,
+        // we don't want to report a warning.
+        val type = expressionType?.arguments?.firstOrNull()?.type ?: return
+
+        if (type.isMutableCollection()) {
+            context.report(
+                MutableCollectionMutableState,
+                node,
+                context.getNameLocation(node),
+                "Creating a MutableState object with a mutable collection type"
+            )
+        }
+    }
+
+    companion object {
+        val MutableCollectionMutableState = Issue.create(
+            "MutableCollectionMutableState",
+            "Creating a MutableState object with a mutable collection type",
+            "Writes to mutable collections inside a MutableState will not cause a " +
+                "recomposition - only writes to the MutableState itself will. In most cases you " +
+                "should either use a read-only collection (such as List or Map) and assign a new " +
+                "instance to the MutableState when your data changes, or you can use " +
+                "an snapshot-backed collection such as SnapshotStateList or SnapshotStateMap " +
+                "which will correctly cause a recomposition when their contents are modified.",
+            Category.CORRECTNESS, 3, Severity.WARNING,
+            Implementation(
+                MutableCollectionMutableStateDetector::class.java,
+                EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
+            )
+        )
+    }
+}
+
+/**
+ * Returns whether this type can be considered a mutable collection.
+ * Returns true if this is, or this is a subclass of:
+ *
+ * - [kotlin.collections.MutableCollection]
+ * - [kotlin.collections.MutableMap]
+ *
+ * If not, returns false if this is, or this is a subclass of:
+ *
+ * - [kotlin.collections.Collection]
+ * - [kotlin.collections.Map]
+ *
+ * If not, returns true if this is, or this is a subclass of:
+ * - [java.util.Collection]
+ * - [java.util.Map]
+ */
+private fun KotlinType.isMutableCollection(): Boolean {
+    // MutableCollection::class.qualifiedName == Collection::class.qualifiedName, so using hardcoded
+    // strings instead
+    val kotlinImmutableTypes = listOf(
+        "kotlin.collections.Collection",
+        "kotlin.collections.Map",
+    )
+
+    val kotlinMutableTypes = listOf(
+        "kotlin.collections.MutableCollection",
+        "kotlin.collections.MutableMap"
+    )
+
+    val javaMutableTypes = listOf(
+        "java.util.Collection",
+        "java.util.Map"
+    )
+
+    // Check `this`
+    if (kotlinMutableTypes.any { it == fqn }) return true
+    if (kotlinImmutableTypes.any { it == fqn }) return false
+    if (javaMutableTypes.any { it == fqn }) return true
+
+    // Check supertypes
+    val supertypes = supertypes()
+    if (supertypes.any { type -> kotlinMutableTypes.any { it == type.fqn } }) return true
+    if (supertypes.any { type -> kotlinImmutableTypes.any { it == type.fqn } }) return false
+    if (supertypes.any { type -> javaMutableTypes.any { it == type.fqn } }) return true
+
+    return false
+}
+
+private val KotlinType.fqn: String? get() {
+    val descriptor = constructor.declarationDescriptor ?: return null
+    val packageName = descriptor.containingPackage()?.asString() ?: return null
+    return packageName + "." + descriptor.name.asString()
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
index 5473733..d59b1b8 100644
--- a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
+++ b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/RuntimeIssueRegistry.kt
@@ -37,6 +37,7 @@
         ComposableNamingDetector.ComposableNaming,
         ComposableStateFlowValueDetector.StateFlowValueCalledInComposition,
         CompositionLocalNamingDetector.CompositionLocalNaming,
+        MutableCollectionMutableStateDetector.MutableCollectionMutableState,
         ProduceStateDetector.ProduceStateDoesNotAssignValue,
         RememberDetector.RememberReturnType,
         UnrememberedMutableStateDetector.UnrememberedMutableState
diff --git a/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetectorTest.kt b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetectorTest.kt
new file mode 100644
index 0000000..9d57ef0
--- /dev/null
+++ b/compose/runtime/runtime-lint/src/test/java/androidx/compose/runtime/lint/MutableCollectionMutableStateDetectorTest.kt
@@ -0,0 +1,1586 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.compose.runtime.lint
+
+import androidx.compose.lint.test.Stubs
+import androidx.compose.lint.test.kotlinAndCompiledStub
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestMode
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/* ktlint-disable max-line-length */
+@RunWith(JUnit4::class)
+
+/**
+ * Test for [MutableCollectionMutableStateDetector].
+ */
+class MutableCollectionMutableStateDetectorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = MutableCollectionMutableStateDetector()
+
+    override fun getIssues(): MutableList<Issue> =
+        mutableListOf(MutableCollectionMutableStateDetector.MutableCollectionMutableState)
+
+    /**
+     * Extensions / subclasses around Kotlin mutable collections, both in source and compiled form.
+     */
+    private val KotlinMutableCollectionExtensions = kotlinAndCompiledStub(
+        filename = "MutableCollectionExtensions.kt",
+        filepath = "stubs",
+        checksum = 0x90938fc8,
+        """
+            package stubs
+
+            fun mutableList(): MutableList<Int> = mutableListOf()
+            val MutableList: MutableList<Int> = mutableListOf()
+            object MutableListObject : MutableList<Int> by mutableListOf()
+            class MutableListSubclass : MutableList<Int> by mutableListOf()
+
+            fun mutableSet(): MutableSet<Int> = mutableSetOf()
+            val MutableSet: MutableSet<Int> = mutableSetOf()
+            object MutableSetObject : MutableSet<Int> by mutableSetOf()
+            class MutableSetSubclass : MutableSet<Int> by mutableSetOf()
+
+            fun mutableMap(): MutableMap<Int, Int> = mutableMapOf()
+            val MutableMap: MutableMap<Int, Int> = mutableMapOf()
+            object MutableMapObject : MutableMap<Int, Int> by mutableMapOf()
+            class MutableMapSubclass : MutableMap<Int, Int> by mutableMapOf()
+
+            fun mutableCollection(): MutableCollection<Int> = mutableListOf()
+            val MutableCollection: MutableCollection<Int> = mutableListOf()
+            object MutableCollectionObject : MutableCollection<Int> by mutableListOf()
+            class MutableCollectionSubclass : MutableCollection<Int> by mutableListOf()
+        """,
+"""
+        META-INF/main.kotlin_module:
+        H4sIAAAAAAAAAGNgYGBmYGBgBGJWKM3Apc0lkZiXUpSfmVKhl5yfW5BfnKpX
+        VJpXkpmbKsQfnJdYUJyRXxJckliS6l3CpcbFWlxSmlQsJOtbWpKYlJPqnJ+T
+        k5pckpmf51pRkppXDGQUA9XxcbGUpBaXCLGFAEnvEiUGLQYASQTUpX0AAAA=
+        """,
+        """
+        stubs/MutableCollectionExtensionsKt.class:
+        H4sIAAAAAAAAAJ2Wa2/bVBjH/yc3O26aOEkva7q1LL2v7ZyNXSgNZaVsLCzp
+        YEWTUF85rRXcJg7KOanGu34WPgHQF0ggoYiXfAW+C+Kxa9nOWYI2pNjnnOfy
+        P7/H56L89c9vfwB4gFcMS1z0m9xo9IXZbFsH3XbbOhF213n6RlgOpw5/IRQw
+        Bv3MvDCNtum0jJfNMwpSEGeY6Fwn1m0uGArrG3UvrC/stuHadhnW3jJW66FW
+        zRFWy+rt7lHkUr3baxlnlmj2TNvhhuk4XWG6NNw47IrDfrtNUcVQbL/XM39w
+        FRWkGVJV27HFHkN8feN1BhPIaNAwyZAdnl5BjmwtSzSi7BNDI12uI4MCimnE
+        MMWg+UUfWRSZHyqPTIS4KtvGVTwbncU5t06fm/w7ilcwp6Hksk8O6Si4SaYQ
+        3SPQooOcBJPBIj5wuW+H3A3ze5mbTISzI9tGcb9PKSShYFXDmlSKZ98YKsWD
+        0qKDnMSXwRa23VLuEn1H3rAMN4boQw/BbY9xjVuXqVHBCj4kT0gcnTs/wjYz
+        miaDR3jslvERg1o9afubduUdD8nyu+2sx/97ITff60vl6+ddQTUYDUuYp6Yw
+        yRbrXMTpfmHuK8nAzt1OjOxvbLdXod7pPYa/B5er2uBSi+mL9KhaTI1Te9tv
+        V/x2idpUKaPnS2ohUYhVYhVGo0IwSpUKerGUvR75No0ipoKIbHlWH1yG6X/+
+        mFJp3lJCjesJ8iVDrdCl6Gr5lp6WhcOACT1DuZPhLKErp+tuifcZfQMs/MfV
+        evecTmz6yG45puj3LIb5V31H2B2r5lzY3Kas/fAKZEgcdE8t91zYjnXY7zSt
+        3jeuMh2bo26/d2I9s93BnK/x+i0F3KNdl6AVSNDdQtcZjeruymAXDWpTRKtS
+        W3KvjMBXlXx0BgPfJ5KPNnbg2xvypTGHJI3iOKTRBvnp42Ayvvs7tG9/RXYA
+        /Sd3y+AlvTVyu5AZeq7FlCGxOeQDqZueEEX/gulQIeVZk2OyZzA7CqREIPMD
+        3JJB0gSS9qVuSFILgVQEpCyDaGOyl7A8CmSNQNYHuCODZAkk60utSFKbgVQE
+        xJBBcmOyK7Q1rrO3fBA9ujQDPJBZiqRV9NXuS2oPA7UIy47MMjUyW8XHVCXz
+        soXP8iTKcoXp6GJdoRz9ZFcwJPAr7PwczFz25kjSDEni1zBPzwL17tCzTURV
+        emL4yuN6ga+pPaPMTyn6yTHiNezX8Bm9cVDD53hawzN8cQzG8Ry1Y0xzPOL4
+        0vs9pMPGUfD6eY4Ux5bX3+RY5lj0+gscsxwVjiSnv2GY+RfzLRDjlwkAAA==
+        """,
+        """
+        stubs/MutableCollectionObject.class:
+        H4sIAAAAAAAAAKVWW1cTVxT+zoSQIRlhEg03r62oIWkJalU0FEWKJQpBAalC
+        WzuEMQ4kEzszoWpv9Gbvtxcf+thnH+pqi1rX6qL2rT+qq/vMDBMIg9LlWsm5
+        7H32t69nn/nn3z/+BPASfmTYaVqVGTM9UrGUmaI6UC4W1byllfXRmTlahMAY
+        SsNzyoKSLip6Ie2QMw6lYmnFdFWkd9W5rG6pBdXI9GWG58tWUdPTcwultEZU
+        Q1eK6ZJizKuGmT63Tm+GQa5VF0IdwzY/lSHUM3T9Pw0hiAz1vZquWX0MgUTn
+        pIQwImEEITFsrarpNwzl5rBmkv7GMJo4t7HKdRhRBqmjY1YtqgXFUq90k/XD
+        a89kJGzFtgYIiDPUWdc0k2H38BOjTjEIKLOzdDyR7ZxiiK6LawjbGUILSrGi
+        jl5laKZzPsGXsBO7wtiB3QzxxPosdk5JaMNzEcTwPMGREyVVtxhYlgJEBvQX
+        iwxtCd9kZ7hhaX9eb8q3ErjE3uGyUUjPqdaMoWi6mVZ0vWwpXMhM58pWrlIs
+        kveia4opIsmwyy+/BGsQgJY3Q3iB3MtfU/PzLsJ5xVBKKh1kOODj9irKOAcp
+        ZHgJdCEdxovolrAfB3hIDlFc/V1nCOaLqmJIOIIIP3qUTM6XdYu7JKHHCelx
+        hsgK0Y5k1yai5ZrYZ+cm4xjyMuVGMwdL162bdr0S5yROcU4/6dXIT8UqG7wK
+        OlcpyLp0sjbly/C/rhIG8ArHPkM1YKil8oLKkX3O8nR2PCmdlAle3QQ55ETk
+        HF0vHyCGBkcRRUlCznF61Kby4NnUCw51jEJRUK1x7ZZqh4IKtc6kjYRJXOQH
+        XlvTPnKV0gy/LJd5nHRrkt8XCdO4GMYUXufF3x6mi/kmQ2x9DngibbbCHcjy
+        VV7CBBcWQOpDVtnuEAyJxLTP5fKhMezpnTjhk+7E9MQESdBAtaVwVBFzDPv8
+        Kr9aOROOASFQcfVtcE03aZmEAvQwSihTjnwtjyf8PUpt1B820GJyLdRkxN58
+        0e7BPJzUWsVsbnyiPzcwKOEGWnm/pMjuq2mm/jVLHXLllRmhkplVLIVoQmkh
+        QK8c40OQmto8kW5ofEddWpg9yNix5cWusNAqhAV5N/3FsCAGaY7QHKB5V3h5
+        kSZii3U0d/JZ/Pu20Lq8eEiM1cWEbqGbnQ6JwuOf6wU5cDYqh9qFbvFQvdxA
+        szD0+A472yKHbZokR9pXZCSb0yBvIU6jvY7KTTWSAZKUN5SMco69bpJjHner
+        Ldcsb6u1wrYvTojNGyC2yC3+nLGYXMdRLj2+EySU+vY6MSjX8/BRdwS15nUv
+        2OANS6W2TA2ga56yvH2soltaSc3qC5qp0cn+aoegGz6uFXTFqhh0neoGyrM0
+        NQ1ruurc2wmOzK9mOa8UJxVD43uX2FGL6/X8NQq2jFtKfn5Eue6KhcfLFSOv
+        ntH4ps3FmFxnGQ5S+QXpHwIvxDZekeTtF1Q79TR3AnKMv+q0/pJoAt6lncC/
+        IojyFVEGEKA9EE/ex5ZkoPcRmi7fh7yM2O9ovmeLfE1j2DmEKP2/oZVE4nzf
+        Qup4eKk/uYBH6SQ/25j8Dc3bH2DPQ+wVcNc+xSWbHa4ryVcd2Ec8xl8zMoZj
+        HHcxoqlY6gEOcqTUQxxeDxP1YKJI0mfiipcJfEtziDkhoPGI53DC1kUecdSH
+        OMZwzwN1vAp7XvU8yasTm/Mq8xSv+jbvVW+tV/S4+nt1mq0CrfWKnk3Xohqp
+        Vxl+2UDKMWBwdWHRSI8NUTnSYde3iOvV8HqvIp5XEQrOCPE8b87aR3NPidT5
+        Z4jUhadgjz8DNj20/lm4tGEW5H7+OetKnXItkpKpZUwt4Y0lXLnr3bx696ZV
+        DZM8wyQK5Fu2dz0e2piLFk/9hR0/IRi4W4Wd4bABfGePrGED/LiHH/fwhzz8
+        URc/tgZ/xxJmNwUe88BjHvikF8C0G8BgcglX/WPgxDHoVXMB19waPOZa1pSK
+        zfPMLiNEGb5eLWnHgibPgibM4W0vr5oNZriW7HctETnMA1RqL4booohY8FpL
+        i41P9f0IAjXRd37FrXs2IeCqCOB7e/4cP9Bskth75Mn70whk8UEWH9KIRT58
+        lMXH+GQazMSn+GwarSb/3bZ/EROTJiZMXDTRZlM6TOw3kbTXR+yxx0TGxEkT
+        A/Z2yETWRM7Ehf8A1Au5SlEPAAA=
+        """,
+        """
+        stubs/MutableCollectionSubclass.class:
+        H4sIAAAAAAAAAKVWW3PTVhD+ju+RBZYNzg3KpQRw7DZOoEDAaSCk0BicBJKQ
+        QtKWKo4wSmSZSnIK9Jbe6PWZhz72mYcy0wZoZzopj/1Rne6RFSWxZZIOM/Y5
+        0u7Z7+y3u2eP/vn3j78AvIGfGPabVnXOzI5WLXlOU4YrmqYULbWiT1bnipps
+        mmEwhnJhQV6Ss5qsl7Ljcwu0IleTVC1Vy64bDWxYl9ctpaQYucFcYbFiaaqe
+        XVgqZ1WSGrqsZcuysagYZvZyw845Bql+uzACDLu9tgwjxNDz/3YII8IQGlB1
+        1Rpk8Ke6p0UIiAoIQmTYtb7NkGHI9wqqSfvvFBDj2p3r2poiziB2dc0rmlKS
+        LeVmL3lf2LwmJ2IXdrfAhyRDwLqtmgwHC1vEnaLgl+fnySCV755hiDdENow9
+        DOElWasq47cYWmmdR/hFvIJ9AvZiP0My1ZjH7hkRHTgYRQKvEhzRKCu6xcDy
+        FCJyYEjTGDpSnunOccey3rqBjGctcItDhYpRyi4o1pwhq7qZlXW9YsncyMyO
+        VayxqqYR+4jjihlBmmGfV4YJ1iAAtUhV+hrRK95WiosOwhXZkMsKLWQ46kF7
+        g2SSg5RyvAh6kBXwOnpFHMFRHpJjFFdv6gzBoqbIhogTiPKlJ8nlYkW3OCUR
+        /bWQnmaIrgntSPZsI1qOi4N2bnI1R96k3KjmhfId655dsaQ5i3NcM0T7qsRT
+        tioGr4LuDRvkHTl5m/FUeB9YEcN4i2NfpBowlHJlSeHIHmt5OrtelE7KBK9v
+        ghypReQyHTAPIIaW2kYUJRFjNdLjtpQHz5ZerUknKBQlxZpU7yt2KKhQAya9
+        iJjGNb7gnU0NZKxanuOH5QaPk25N8/MiYhbXBMzgXV78nQIdzfcZEo054Im0
+        1TInkOdPRRFT3NgH2j5sVewewZBKzXocLg8Zw4GBqTMe6U7NTk2RBQ1UWzJH
+        jWCB4bBX5a9XzlTNgTCouAabHNNteiaiBF1AGRXKkafnyZQ3o0yz/tBkF5Pv
+        Qk3mcF2n9C5Han5rV8goVcO8bMkk85WX/HSJMT4EqV8tkuiuyt+oBfvm+xjr
+        W13uEXztPsEn7ad/RPBFgjRHafbTvE9YXaaJ1JEAzd18bl9dPhZJBBK+Xl8v
+        Ox98/kvIJ/kvxaVwp683ciwktdDsG3n+kF1qkwRbJkrRzjUL0da0SDtIs9N+
+        jkuxOks/WUpNLeNcYz/HpISr3WXbtUq7672w/UsSYmsTxDapzVszkZACHOX6
+        84ecZagzEAlKIR44anmgfttwMV24aynUa+lU9yxS6lom1ZIuW1WDTkFguDJP
+        U6yg6krtuE1xW36iKkVZm5YNlb87wq6Jqm6pZSWvL6mmSiK3VQ+tdw6GPfXL
+        Nml3TFpycXFUvuOACpOVqlFULqr8pcMxnW4wRB+d2yD9w2gBkxL8Yia2X1HV
+        +LBEvYPxDwEavybJMPwkBZLpJ9iR9g/8idiNJ5BWkfgdrY9tk29oFOxFrYjT
+        /wE9iWRORmhDO69P3mAcwJO0kq/dmf4NrXue4sAzHPLhkb3qgY1hax1L/tSF
+        w6Rj/DoiZzjGaQcjnklknqKPI2We4XgjTNyFiSNN33prLFP4luYwR+22TU64
+        hFP2XsSIoz7DKYbHLmiNleCy6n8RqzPbY5XbgtXg9lkN1LOi29Gb1Xm2AbSe
+        Fd17jkd1Vm8z/NrEqubABXxHc8jdn24LknKk4w63qMOq0Mgq6rKKUnBGSeey
+        uWQvHdsiUldeIlJXt8CefAlsuim9s3C9aRakIf496lidczwS05lVzKzgvRXc
+        fOSevJBt17rBMdF1TKRAfmCz63fRJhy0ZOZv7P0ZQf+jddg5DuvH9/bIWprg
+        J138pIs/4uKPO/iJTfh7VzC/LfCEC55wwafdAGadAAbTK7jlHYNaHINuNZdw
+        26nBU45nsUxikWd2FWHK8J31kq55EHM9iGEBH7p5VW0ww/HkiONJhMM8RbX+
+        YEQcFL9j7ccP9vwlfqTZpDUfkZN3Z+HP414e92nEx3z4JI9P8dksmInPsTyL
+        dpP/vrB/URPTJqZMXDPRYUu6TBwxkbafT9hjv4mcibMmhu3XERN5E2Mmrv4H
+        PrD+CPEOAAA=
+        """,
+        """
+        stubs/MutableListObject.class:
+        H4sIAAAAAAAAAKVYi38TxxH+7mRLsnTGZ4FtbBPzMkG2ADkkJQl2IIZAIjAm
+        YNcluG16lg5zth5Ud3JJ2iQmbZK+36UtfSZN37SFJjE4tKlD+kzbf6m/zuyt
+        z5J8MvqRH+ZutTvzzTezs7Mjvf+/t98B8AD+q6DDdkpTdvJEyTGmsuaIZTsn
+        p2bMtBOCosAYmTHmjGTWyE8n3elBd6bkWNkkCw+VSaTyjjltFgcPDI7MFpys
+        lU/OzOWSFs0W80Y2mTOKs2bRTh4vszWoQK82EUKDgnWVZkIIKojXixpCWEFw
+        yMpbzgEFgXjfhIYIohE0QlOwfgV6uFg0nnE11kXQwqtab2/GzJrThmM+PUDs
+        qvwd1NCKWBNUrFfQ4Jy3bAWdIzViSN4FjEyGBOOpvrMKWlfFKoROBaE5I1sy
+        T55T0E5yPgHV0I1NEXThHgVt8dV70ndWQwc2RxHCFoIj+jkz7yhQUgoa46lU
+        34SA9lGcYMUdrHgviVr5jHmRIkech7NZcixe5v3hQjZLOlYhP8i+JP3XhhK+
+        CcEa20cKxenkjOlMFQ0rbyeNfL7gGKxkJ0cLzmgpm6WAhSV7O4zdCnr8tpxg
+        iwRgpe0QkhSR9HkzPSsRnjSKRs4kQQU7fSJVNjPGINMiBPdhbwQDuF9DH/o5
+        GB+iePm7rqBrOZB+URmosVgzLGzyITa5n+KfzppGUcMQojzzCAUjXcg7HCwN
+        B939fVRBdHlS7NGeOvZBOu/aO+S6+Bjl5rTpcEJV5JyU1XAUj7PcE5RQIi84
+        PzmPUzVyMKXhGEZY5QSr2EdyF5xnxOkjoyfxJK+cIpcs2hzDKRQ5JfvKuKfk
+        PIU44bvgX2o0jGGcsSnHo1nDdlIuWQ1nXDZP0ZnO0pFMeXa7KuBHytYGOa9r
+        LdayP4mPsp2PK+j2QumHPFB7tTb0Jxh6is5k0cwV5kwOmo8sp17vWseLTgaX
+        JoLMuHk0TXXQB0hBk2uIckvDjJsqs7RrctZhAJEXeSHKeShEL7iin6QNtzmr
+        Orjs+BrY6VuI/DLQRokx5yid7NIUx0vBhhXclZqsoM9nulZQL+IZhv00OXCu
+        WMil3KIXcgrLIzoWY9azpshdyvYGmz5ouIR5Vnux4sYaLeWmuIp/jhM770xw
+        IdfwMuYjeAmvcHHdGKG74gsKYn4edqCXl7/Mx1sIfpXP3SYefZ2P03EefZNT
+        WYy+zdE3eXRZQ86V+x7fC6/wghD5AYfN4dGPNLzAPFT8RHgn7jq6ROOTPuH3
+        mVOwZWh8v08ViU+Oj5MGPahkGYwaxuu0M35lKIRfKNjhV8RXZMZdaiH8SsGB
+        GjdOnZw1vIrfRPBr/JbS29entri/r4laV10NK39gK9do14fSWdFncKCpfQin
+        RsfGh0cPH9HwJtq5T3iLAlBXZlJ/sNw3naCDlTEcg+bU3FyAejWFH410pdNh
+        VC9a/Im6EzVzn6Kmlub3RdSNakTVt9L/cEQNN9I7GlmapxdNhwP07qE3Lel9
+        9GbRBL0j4fdeVjcuze8Nxxpi6oA6oBwKhdXbrwVVPXCsVQ91qQPhvUG9id7q
+        E7cvK8c6xVyE5qI8V7G2WdekvLum6c1dy7jrhESHlFi90qS3MK4Yt+p6ld0A
+        abbW0GzXY5JJdFla8F9POBtWcWzS2xhHjFv0dg+rQ1hp1Teu0mjROz2pLulF
+        2UyZXebSXR0xwWUT6dxTk39PFX9F8u/QN9fQ6dG3lOuUR0robqW92ObpKLS+
+        Xcr1Lts4HdMbeHzm9uVG0gl2NYQb9SAn1F6Fkg09spddOQlHLjom9Vx0m+yZ
+        pTrcfbqUd6ycmcrPWbZFksMr1w0V1jFrOm84pSIV0YbDhQy9WkasvOmWy3FG
+        5opYSBvZCaNo8Wc52VuN6zV0FQaaxxwjPXvCuCDVImOFUjFtHrX4Q6fEmFjF
+        jDo9lb4EqFTH+Wh28hklb/9KpylI712AHuP+nsZ/ozkVN9BLT/ruQDN/p5nD
+        CNBnoK3/Bpr7A0O30PLUDehLCL2FDdeFyj/oGRFCQYIK4p800kidlOhfO59l
+        vhYk4D6SZNl1/W9iQ/dN9Cxiq4qrQoo1291VqcmjbdhOa4zRKzGGiRQXhBaB
+        sUmA7AzgugeyxV32QFoQFyA8YjiVxtT5khTDPSwptSZie27iAQZNLGLfalat
+        HmArduNBL2gJ/IveIcWNqMB+SGI/JqnGdnnY3bsWMRgoA3fZxjzwmMc2Jsyo
+        0szDwkyTKhRdQ0PeRsVFjGgn2MQi6GvgSjjc3Yh4u3Fwrd0Yrm83Dt0hfEfq
+        D9/h6vBRR0DTq/ktIqViCV3X1uDnhq4swelJfUVtf0fr85caev9In1bK9Ksj
+        Ta26jFKV1kcUXKuh5Qblw1U+nFnLh7P1+UCNuz+bp+/E5mNVbKhPl0j3SzZR
+        uUNpFdXbE/WoROX2uKBGFSi1enLbK0Apmc6v9q8cdBssWvOS6JwQnblDgmY/
+        QILmaiZo4a4S9MIduBY/AFfqjiVXrxaVlc1PBSr5rlWL3MpZyZy+W0jmByS6
+        5qIv4jMBVONqHq6G5ySuhucFrkv/2Sp86uj9j91nax47fZh/G5Jaj8p4av2J
+        Jby0gM8v4ItXsXxtBYVesCys5Qy34UtQBNoOiXZc+tjc371rGe4r133hXIeb
+        PbhmL5DNAljFKf6JQwKfljTbEu+i6woaA1dX+H6N+QbwvngqTTWIt3mW2jzi
+        R/G4xN8v8YP93Qv4xrU1AhD0cIKS8Sn+maMGT7WM57fujifhn6kL/zt3jZ/x
+        4nxS4scq4ty1gO/WBV5+LlbAlwvzIxK8iYP8/QVcWSvRmjyoJjfOtF8Zb78q
+        oH5IJ3WtLfODslFaI2d/7A9XT85e8g5kUh7Ixv4F/NTfVfdcNnrX4at4Tdai
+        B6WDLYnYz7nOLeGXiZu4Wl04y1u41/E7r8r9TID9XjK5VzIJM8xNXK++y8IS
+        JYw/ev1Sh8Cn2+MWVOpo33gDC9fFRECaCODf4v0e/kPvK6R2kzxZnEQghbdT
+        uEVP/Ikff07hHfxlEopNpfTdSeyw0W7jtviL2rhk4wUb8zY6xMw28Yzb6LOx
+        W4yHbBy0ccjGURubbByzcdLGmFg6Y2NSDDI2TBszNnI2LtiwqajbuGjjORvP
+        /x8chhqA3RgAAA==
+        """,
+        """
+        stubs/MutableListSubclass.class:
+        H4sIAAAAAAAAAKVYi1sU1xX/zSzsc5BhFRAw+MK4sOoSk5pGiAaNJquoUSg1
+        0jYddkcc2AfdmaWaNgm2TdMmfT9sa59J07dttU1QkjYl9vn1j+rXc+5cht1l
+        FvczHzBz995zfud3Hvfcy/73f++8B+AR/EdBl+2Up+zUqbJjTOXMUct2xspT
+        mZxh2yEoCozRGWPeSOWMwnTqzNSMmXGG3JmyY+VSLD5cIZEuOOa0WRo6NDQ6
+        W3RyViE1M59PWTRbKhi5VN4ozZolO3WywtqQAr3WRAhNCjZUmwkhqCDRKGoI
+        YQXBYatgOYcUBBL9ExqiiEXRDE3BxlXokVLJuOJqbIiilVe1vr6smTOnDcd8
+        bpDY1fg7pKEN8QhUbFTQ5FyybAU9o3WjSP4FjGyWRBPp/gsK2tZEK4QuBaF5
+        I1c2z1xU0EFyPiHV0IMtUXTjAQXtibVZ6b+goRNbYwhhG8GRA3mz4ChQ0gqa
+        E+l0/4SA9lGcYMVdrPggiVqFrHmZYkecR3I5qo9Ehf9Hi7kc6VjFwhD7kvJf
+        G076lgRr7BwtlqZTM6YzVTKsgp0yCoWiY7CSnTpddE6XczkKWFiyt8PYq6DX
+        L+kEWyIAK0NlmqKIZC6ZmVmJ8IxRMvImCSrY7ROpipkxBpkWIXgI+6MYxMMa
+        +jHAwfgQxcvfdQXdK4H0i8pgncW6YWGTH2aTByn+mZxplDQMI8Yzj1MwMsWC
+        w8HScNjN7xMKYiuTIkf7GsiDdN61d8R18UmqzWnT4YKqqjkpq+E4nmK5p6mg
+        RF1wfXIdp+vUYFrDCYyyyilWsY/l55wrYv+R0TN4hlfOkksWJcdwiiUuyf4K
+        7mk5TyFO+i74NxsNYxhnbKrxGG06J+2S1XDeZfMs7eocbcq0Z7e7Cn60Ym2I
+        67reYj37k/gY2/kEtQIvlH7Ig/VX60N/kqGnaE+WzHxx3uSg+chy6fWtt71o
+        Z3BzIsisW0fT1Al9gBREXENUWxpm3FKZpazJWYcBRF0UhCjXoRCdc0U/RQm3
+        uao6ue34Gtjt24j8KtBGmTHnqZzs8hTHS8GmVdzVrqyg32e6XlAv4wrDfoYc
+        uFgq5tNu0ws5xZURbYsx63lT1C5Ve5NNHzRcxQKrfa7qzDpdzk9xF/8CF3bB
+        meBGruGLWIjiZbzCzXVzlE6LLyuI+3nYiT5e/gpvbyH4Nd53W3j0Dd5OJ3n0
+        LS5lMfoOR9/k0TUNeVfu+3wuvMILQuSHHDaHRz/W8BLzUPFT4Z047egYTUz6
+        hN9nTsG24fGDPl0kMTk+Thr0oJZlMGoYb1Jm/NpQCL9UsMuvia/KjLvUQvi1
+        gkN1TpwGOWt4Hb+N4jf4HZW3r0/tCX9fk/WOujpW/shWbpJvDRUdHf0rl6JT
+        tGeyhmPQnJqfD9BVTOFHM53WtM/UyxZ/oquHmn1IUY8uLxyIqpvVqKpvp79w
+        VA030zsWXV6gF02HA/TupTct6f30ZtEkvaOblxf2h+NNcXVQHVSONN99I6jq
+        gRNteqhbHQzvD+oReqtP372mnOgSc1Gai/Fc1dpWXZPy7pqmt3SvoG4QEp1S
+        Yu1KRG9lXDFu0/UauwHSbKuj2aHHJZPYirTgv5FwNq3hGNHbGUeMW/UOD6tT
+        WGnTN6/RaNW7PKlu6UXFTIVd5tJTGzHBZQvpPFCXf28Nf0Xy79S31tHp1bdV
+        6lRGSuhup1zs8HQUWt8p5fpWbJyL6008Pn/3Guc72N0UbtaDXEr7FSoz9Mor
+        6mp5H7vsmHSRoiNi3yw118iYNV0wnHKJel/T0WKWXq2jVsF0u9w463IjK2aM
+        3IRRsviznOw7Vy44Vt5MF+Yt26Ip7x42snoM0QFZK1a12jLmGJnZU8acBI2O
+        FculjHnc4g9dUnVijSJd31S626vUnCNQ9Dhf0cnbv9E+UvEn7KQxXf/puUwz
+        RxGgWaB94DZaBgLD76L12dvQlxF6G5tuCZX36RkVQiGCCuEujTRSJyX66eAd
+        y31dAh4gSZbdMPAWNvXcQe8Stqu4IaRYs8NdlZo82iEoMUafxBghUrztWwXG
+        FgGyO4BbHsg2d9kDaUVCgPCI4VQa09WVpBjuMUmpLRnfdwePMGhyCQfWsmrz
+        ANuwF496QUvi7+w9k9wjVOiOKrGflFTjezzsnj1LGApUgLts4x543GMbF2ZU
+        aeYxYSaiCkXX0LCXqISIEWWCTSyB/pNbDYebjaiXjcPrZWOksWwcuUf4jjUe
+        vqO14aMjnabX8ltCmqe7b67Dzw3dP2gc9PDoYlDf39ON+Us3cv9In1Mq9Gsj
+        TXdtGaUarY8quFlHyw3KR2p8OL+eDxca84Fu3v5snrsXm4/XsKGLtkR6WLKJ
+        yQxlVNSmJ+ZRicn0uKBGDSjd1WTaq0CpmC6t9a8SdAcsWvOK6KIQnblHgeY+
+        QIHm6xZo8b4KdO4eXEsfgCtdbyVXrxdVtM1PB6r5rteL3M5ZzZz+OZDMD0l0
+        zUVfwmcDqMXVPFwNL0hcDS8KXJf+8zX4dCX333afr7vt9BH+ckdqPSHjqQ0k
+        l/HyIr60iFdvYOXYCgq9UEVYKxnuwGt0PjLaLol2UvrYMtCzZwXuq7d84VyH
+        Wzy4Fi+QLQJYxVn+jkICn5M025Pvo/s6mgM3Vvl+nfkG8E/xVCJ1iLd7lto9
+        4sfxlMQ/KPGDAz2L+ObNdQIQ9HCCkvFZ/p6iDk+1gue3748n4Z9vCP+7942f
+        9eJ8RuLHq+LcvYjvNQReuS9WwVca8+MSPMJB/sEirq9XaBEPKuLGmfKV9fJV
+        BfUj2qnrpcwPykZ5nZr9iT9cIzV71duQKbkhmwcW8TN/V9192ewdh6/jDdmL
+        HpUOtibjv+A+t4xfJe/gRm3jrLzCvYnfe13u5wLsD5LJg5JJmGHu4FbtWRaW
+        KAGpHcC/xPs9/Jve10nmz0TyrUkE0ng7jUV64jY/7qSxhHcmodh4F3+ZxC4b
+        HTb+Kn5jNq7aeMnGgo1OMbNDPBM2+m3sFeNhG4dtHLFx3MYWGydsnLExJpbO
+        25gUg6wN08aMjbyNORs29Wsbl228YOPF/wOZ1FsqfRgAAA==
+        """,
+        """
+        stubs/MutableMapObject.class:
+        H4sIAAAAAAAAAJ1X63cT1xH/3dXT6wXW8hPxMAkmtqUkMpQkEBs3xnWMbGP8
+        ICbBeXQtL2atlUR0Vw7kSfNOkzbP0jYf+5kPcNqSkJyT49Jv/aN6MrO7liV5
+        cRyO0d65c2d+M3fuzNzL//7/w08AjuNbgQ7pVJZk5mzFMZZs86xx5dzSqplz
+        YhAC5alVY83I2EZxJeOxBz1OxbHsDMkO1Qhki465YpYHA1jDg1P5kmNbxczq
+        WiFjEbdcNOxMwSjnzbLMTG4aHxTQG23GEBbYVWc3hqhA7w4xY4gLRIesouUM
+        C4T6+hc0qGhWEYEm0LkJPGUV8+byGUNedrV2q9jDElpPz7JpmyuGY74yILCn
+        PgSDGlqQaIKCVoGwc9mSAl1TwUGl3UVytmmUNXSiuRkxdAk050pFx7CKctK8
+        Rgh92f6LAi1bghjDfoHYmmFXzHOX6NhILiDSGg6iW8UBHBJo79t6fP0XNSTx
+        MJs+TLHIs0mRpfBuOLHABjT0ejJ95LBrkmRXTEegZ6pUXsmsms5SmaUzRrFY
+        cgzHKhE9XbFt3i7t8pEg01tZGtJ4jO08Tluz5FjhinPNPSHycgBHeeUYza9U
+        yHJnXzZwxwInAozt0PxxPMlGnqL8ICMjti2Q6Gs43/4FgaEG5lA6wJMg3rCr
+        fni7qJUcDhztI3ypXCrEcUrgYFBmE2SZlK2cjOG3dLq5y2Yu72vPGGWjYJIg
+        VcX20ZhnkJVBroERnFbxDEY1nMTTHIYxCkPZLJTWKAHGvYM5I6DSwY+xbZMy
+        u6WvvyYS8yan9Ewjb6g+WD2sfW3HrWKYIOMmqxCUhrOYZEemKUPIEaoRyekV
+        bLEBibZDCe6izHko8x7KvPW66eYZZX5Y0kTDBSywwPMCTSTgVgEXcp2h0ZJt
+        Uzjp2Aj6sfss3dcVt46khpewyJZerut005XCEtf472nvdOJ+FS5hQYWBHNfs
+        PpVaDHmdCMrjXm/5cvDxBzeKNDcKBXmmVpkqcD08wVSJz99dfZUpd5U8n8Ak
+        UxUNMx71mobn2EUF1zRcxCJTb9AOhnK22215Tg00np2ePz8yPTqm4R10cKu8
+        LvDUA94klIMbl8lZ0zGWDccgnlJYC9GNJvgToZaWJ9ZVi2fUsZXlo0J8tX79
+        hKp0KaqiH6FfXFXiTB+mXy/RNNe7aQzRqKjr12lopqlKYw9N4//9UOlav35s
+        dyKcUAYU7zsgTsfiyr1/RBU9NNGkJ5LKQOuZezfERIveRnT7sajeQaPi8zp9
+        XleV16XvTYa7xIBSIxly8ZKEt4/lXblD+v56uVoUV/7ARLd+kO0fa9O7k3oi
+        Ghc1fh7yrT20xZqnnZzr0cPJtoSeqN9fdCDy/L0bEZKJJsPxmB6f69KbknF/
+        tXZNpbWE3syoNVxN30Uau6sae2rWdL2FT4b6O6gozY0GE867FX7Qvzo362rs
+        qmNS96OW+XieroN9c5WiYxXMbHHNkhZJjmz2VKrheWulaDiVMhVMeLS0bPK1
+        bRVNr8zOMzJXUiln2AtG2eK5z+xpxK221joDu+YdI5envPXV1PlSpZwzn7V4
+        stfHWNjiGY5S8kfoFwOXwV6uB9r+l5SnURqHAD3BzwmivyKegndJRuHXCnG+
+        Js4oQjQH2lPfYVcqNPQj9rzwHfR1xP6Nttuuyjf0VV0hnaB0/IUojdRJif46
+        uEr49eED9tHIa2rqX2i7i70Ct12JTS21qkVNyNd6kvDZwm7W2vc9HrqLHgU3
+        q5od3qqvydQRPOJa6t0Oo397jJSPQZ2L1hjjpI/RsomRUbCOA7caYFqqMC2+
+        Kxsxf9SVpNdGcEB+I2pcagwItUvfkXE6l5B7Lr4j+11nToTqnTnkCVWdafed
+        YYp3pzS4RRczadTtNJ0Y/h6/YzPpu3hWqTmurTs9VZNJg7hBY0x4aUbf8e2i
+        mH2gKNIF4bvbEMVzAptY9VH0vJuqrQH6ztwP6fwvIc02INEFFXyyL2x3snSZ
+        Bdt/5Zfsv1hnf5Zf2779OT/M7en/4MC3iIRuptLrMO5g+Q4usSsh/NX9iia3
+        iKMuul4T//rEWaH1WX6p7wDf+tX4KR+fHgf3wRe3NvHtWw/kvz7C/wPw8Z/2
+        8aOp9B0Ub2GjmW3FiVZxolUcesr7OLN+LbZuuPfohpdXgkG9qmytgrb6wWWK
+        w8BJNb6jMJQfOAzjwWFwflUYyE96LvtVnfETN5K6g7VgGC9/Iw2VOMuv5QCQ
+        qzsHmaW/C9XCqwV5/eYOQGb5kRzgwZs79+BFxPFW9ZbrdOMFNP8Ihe7Lt/+J
+        P9x2GSFfPIS/ueMX+DuNX5LaewT4PjWBLD7I4kP64iP+fJzFJ/jjIoTEp/hs
+        EQ9LdEj8yf3XLPHnDXpCYlLic4kZiQsSz0ksSLzkLl2UWJTodOmk+z0i0SuR
+        kkhLdEsMSByXeELipMQpV2D8Z8BtlfOyEQAA
+        """,
+        """
+        stubs/MutableMapSubclass.class:
+        H4sIAAAAAAAAAJ1WWXcTRxb+qrW63UBL3oRYTIKJbYlEhpAEYuMJMMTINuAl
+        MYvJ0pYb01ZLIqqWA1mZ7MlkliQzeZjHeeaBnDNDQnLOHA+P+VE5ube7LUty
+        23E4sqtuV9373Vt3q/r5lx//B+AY/imQkk5tQebO1xxjwTbPGzdnawsF25Ay
+        BiFQnVw2VoycbZSXchcXls2CM+yt1BzLzhH3SANDvuyYS2Z1OGBpdHiyWHFs
+        q5xbXinlLFqtlg07VzKqRbMqcxPr6ocF9FadMYQFdjTpjSEq0L9NzBjiAtER
+        q2w5owKhgcE5DSraVUSgCfSsA09a5aK5eM6QN1ypnSp2MYfW17do2uaS4Ziv
+        DQnsanbBsIYEkm1Q0CEQdm5YUiA9uZlb6XyRgm0aVQ09aG9HDCmB9kKl7BhW
+        WU6YtwljID94VSCxwY0x7BWIrRh2zbx4XaCb+AJ8rWE/elXswwGBroGNARy8
+        qiGNx1n1QfJGkVWKPDl4zYg5VqCh3+MZIINdlcS7ZDoCfZOV6lJu2XQWqsyd
+        M8rlimM4VoXoCzXb5gPTKZ8IUr1xSUMWT7Kep+holjxbuuncdmNEVg7hCO8c
+        pe+bNdLcM5APPLHA8QBl21R/DM+ykucoQ0jJKdsWSA60RHhwTmCkZXEkG2BJ
+        0NqoK35wK69VHHYcnSN8vVopxXFSYH9QbhNklYStAlXnHyi6hRtmoehLTxlV
+        o2QSI9XF1t6YZZClYa6CUzit4gWc0XACz7MbzpIbqmapskIJMOYF5pyASoE/
+        y7pNyu3EwGCDJ2ZNh+yeal0baXZWH0vf3nazGCXIuMkiBKXhPCbYkAuUIWQI
+        1Yjk9ArW2IJEx6EEd1FmPJRZD2XWest084wyPyzpQ8MlzDHDZYE2YnCrgBSl
+        mhSdqdg2uZPCRtBPbrK1qSluHUkNr2CeNb3a1Osu1EoLXOOv09kp4n4VLmBO
+        hYEC1+welZoMWZ0MyuN+b/tGcPiDG0WWG4WCIlPLTJW4Hp5hqsLxd3ffYMrd
+        JcvHMcFUTcOUR72p4WU2UcFtDVcxz9TbAs894jVB6bV2U5w3HWPRcAxaU0or
+        IbqwBA8R6lZFWrpl8Re1Y2XxiBBfrt45riopRVX0Q/QfV5U40wfpv59o+tZ7
+        aQ7RrKird2hqp0+V5j76TK3eObozGU4qQ4o3DonTkYf/jip6aLxNT6aVoY5z
+        D78V4wm9k+iuo1G9m2bFX+vx11L1tZS+Ox1OiSGlgTPk4qUJbw/zu3wH9L3N
+        fI0oLv++8V59P+s/2qn3pvVkNC4arDzga3tsgzZPOj3Tp4fTnUk92Xy66FDk
+        8sNv+YTRdDge0+MzKb0tHfd3G/dU2kvq7YzasKrpO0hiZ11iV8Oeric4JtS0
+        QZVmrnWNcNEt2/3+jbheLGdvOSa1NOqDTxWpx7fNWktlw6lVKc/DZyqLJt+3
+        Vtn0quMlluUCqBQMe86oWvztL+6ZqZUdq2TmyyuWtGjp1HqLpVurdbfeL5vY
+        dsw6RqFIGeuDqrOVWrVgvmjxx24fY24DPo5Q2kfoP4Y2CD3JLwI6/peUoQre
+        RYpoenDQ+BdaOYMQrQJdme+xIxMa+Qm7rnwPfRWx/6LzO1fkrzSqLlPC/f2N
+        KI3ESYh+3VwL/HzwAQdo5j018x90PsBuge9cjnUptS5FXcSXepbwWcNOltrz
+        Ax57gD4Fd+uS3d6uL8nUITzhaurfCmNwa4yMj0Gth/YY44SPkVjHyClYxb57
+        LTCJOkzCN+XvREdpPuxy0nMh2CFPiwaTWh1C/c43ZIziEnLj4huy1zXmeKjZ
+        mAMeU92YLt8Ypvh0SotZdLOSRNNJs8nRH/BHVpN9gBeVhnBtPOnJhkwaxlc0
+        x/hwI67I2FZezD+SF6nD++a2ePGiwDpWsxc96ybrSJ5xU5shvfRbSNMtSHTD
+        BEf2ylaRpdsoWP9rv6X/WpP+aX4u+/pnfDd3Zf+Pff9CJHQ3k12FcR+L93Gd
+        TQnha3cUbW4RR130RIP/mxNnifan+am9DXzrd+NnfHy63TfBF/fW8e17j2S/
+        foqf8D7+8z5+NJO9j/I9rDWzjTjROk60jkNvcR9n2q/FjjXzDq9ZeTMY1KvK
+        jjpoh+9cptgNnFRj23JD9ZHdMBbsBud3uYHspPeuX9U5P3EjmftYCYbx8jfS
+        UonT/NwNALm1fZBp+l2qF14jyFt3twEyza/cAAve2b4F1ygAHhXCN+78Z/yD
+        5q+I9z3ifZ/qO487efyJRnzAw4d5fISP5yEkPsGn83hcolviM/evXeLzNXpc
+        YkLiC4kpiUsSL0vMSbzibl2VmJfocem0Ox6S6JfISGQleiWGJI5JPCNxQuKk
+        yzD2KyjpAQxSEQAA
+        """,
+        """
+        stubs/MutableSetObject.class:
+        H4sIAAAAAAAAAKVXW1cTVxT+ziQhQzKYSbhjS62iBtISBItFkIoUNBpASUpV
+        2tohjDAkmdiZCVV7ozd7v7340Mc++1BXW8S6Vhe1b/1RXd1nMg4QBmUtF+Sc
+        mX35zv723uec5N///vwLwFH8xNBkWuU5MzlRtpS5gppRram5JTVnBcEYrqSX
+        lGUlWVD0hWRFPFiRlC2tkCTboU0GKd1SF1RjcHgwnS9ZBU1PLi0XkxpJDV0p
+        JIuKkVcNM3luY6VBBrl6gSD8DHVbFgmihuHwLjGDEBlqhjRds4YZfPHOGQkh
+        hEMIQGJo3gBOa3penT+jmIu2154QItxC6uiYVwvqgmKpV3oYIlv5DkqIIlYL
+        AfUMfmtRMxla0t4ZJHY+ZX6e7OKpzssM0W2pCqKVIbisFMrq1FWqBNl55FPC
+        XjwTQhueZWiMb69I52UJzXgujCD2ERwFX1R1i4GlKBEUwEihwNAa30RktFQo
+        kKdW0gd5YElv3VDCs7jc40C6ZCwkl1RrzlA03Uwqul6yFO5kJidL1mS5UCD2
+        ohOKKSLO0O5VQII1CEDLmUF0Eb3coprLOwjnFUMpqmRIxfegvUmS4SALg7zU
+        L+DFEBLoltCBgzwlVMMmb+oMgVxBVQwJfQhz06MUcq6kW5yShP5KSo8xhB8J
+        7Ux27yJbTojDdm0GKoHQekHNHCtes27YfUmaExjmmldoXY14KlbJ4F3QuWmB
+        lCMn74SnwnsHShjBKY79KvWAoRZLyypH9rDl5ex4XDmpErytCXK8khFqq3oP
+        IIbaykKUJQnpCukJW8qTZ0unKtLzlIoF1cpoN1U7FYToN+lFQhYZbvDaloNh
+        slyc45vldZ4n3Zrh+0XCJWRCuAi7+VtCtCPfYIhtrwEvpK2+wgmc5k+KhGnu
+        LCBHgVilEcNQqCbx+KzH5vKQMewbyh73KHd8NpslDxqotxSOKmKRocGrX4JY
+        YjjotSc2bLKV0IKgthveYQPvMmYJKvQQiihR9Tw5Nca9uSZ2Ojl2WMXkq9Dx
+        Iw7lCvYpzBNNB6uYmsxkRyZHxyRcRxM/Qm/wztvFdUJH56MbZYJ6aV6xFJIJ
+        xWUf3WGMDwE67fIkuq7xN9rywvwRxo6tr3SHhBYhJMgH6COGBDFAc5hmH83t
+        ofUVmkgt+mnu5LP4zy2hZX2lV4z5Y0KP0MNOBUXh4S81guw7G5WDbUKP2Fsj
+        19IsnHl4m51tlkO2TJLDbY98JFtTK9eRZo/9HJUjVZ4+8pR39Ixyjf0ckWOu
+        tt72a5IbqqOw42skxKYdEJvlZm/NdEz2c5SLD28HCKWmzS8G5Bqevl5GqUW7
+        c6dtlH3suqXSeU0nQ3eeirx3uqxbWlFN6cuaqZHlyMbRQVs/oy3oilU2aJv7
+        R0vzKr9PNV2tbOgsR+Z7tpRTCjOKofF3R9hRjeteBlsWqMtYSi4/oVxz3EKZ
+        UtnIqeMaf2l1MGa2RYYj1H0B+gTB+7CVNySx/ZJ6p4bmw4Ac4/c8PX9FMgHv
+        oZ5G+hpBkq9JMgofvQONXfdQ1+UbeoDIpXuQ1xH8Aw13bZdvaAzZRmGCCuNb
+        epLInZzor4l3Lj+4HMB+suS2e7p+R8PeNbTfx/MC7thW3LOponU8+dN+HCAd
+        49ccBcMxBhyMaCLWuYYkR0rcx5HtMFEXJoo4el2Wh/AdzUFWSQGNfS7huL0W
+        MeKo9/ESw10XtMIq5LLqfxyrl3fHauAJrIZ2z+p4NSu6db1ZnWSbQKtZ0X3q
+        RFTlNcbw6w5elQBGNzcWjXQLkZQj9Tncwg6rs9tZhV1WYUrOOdK5bM7Ypukn
+        ZGryKTI19QTsC0+BTTewdxVmdqyCPMK/5zpeJ52IpK7EOi6uYnYVb95xd16N
+        7RfeFJjkBiZRIt8i/QX+Fc9Bm3bQGhN/o+1nBHx3NmDf5rA+fG+PrHYH/EYX
+        v9HFH3fxpxz82Bb8tlXM7Qo85oLHXPCsm8Ckk8BA1yrmvXNQyWPA7WYVV50e
+        POZEFknENF7ZdeQTa7i20dKVCCJuBBEs4h23rgs2mOFEcsiJROQwayhXbwzR
+        QRGx7B4tzTY+BfoAAh2i7/6Gm3dtgc9Zwocf7PkL/EizSW7vE5MPZuFL4cMU
+        PqIRK3z4OIVP8OksmInP8PksWkz6cYtb9n/YRNbEtImMiWZbst9Eh4m4/dxn
+        j/0mBkycMDFiv46bOG0ibWLqfxuJKgUvDwAA
+        """,
+        """
+        stubs/MutableSetSubclass.class:
+        H4sIAAAAAAAAAKVXW1cTVxT+Tu5MBjOJ3MTWWkUNpCVcLBahVKSi0QBKUqrS
+        1g7JGIZMJnZmQtXe6P367EMf++xDXatFbNfqoj72R3V1n8k4QJgoa7kg58zs
+        y3f2t/c+5yT//vfn3wBO4meGLtOqLZnpmZolL2lKTrFytaWCJptmGIzhRnZF
+        XpXTmqyX0nNLK0rBGqtLapaqpcl6fJtBRreUkmKMTYxly1VLU/X0ymolrZLU
+        0GUtXZGNsmKY6Utba40xSI0LhBFgaN2xSBghhhN7xAwjwhAaV3XVmmDwJ3sX
+        RAiICghCZOjcAs6qelkpXpDNZdtrn4AYtxB7eoqKppRkS7kxwBDbyXdMRByJ
+        FviwnyFgLasmQ3e2WQ6Jn18uFskymem9zhDflawwDjCEV2WtpszdZOggO4+M
+        ijiIFwR040WG9uTumvReF9GJl6II4zDBUfgVRbcYWIZSQQFMahrDgeQ2KlNV
+        TSNPtaqP8cDS3rrxlGd5ucfRbNUopVcUa8mQVd1My7petWTuZKZnq9ZsTdOI
+        fcQJxYwgyXDIq4QEaxCAWqCO6yN6hWWlUHYQLsuGXFHIkMrvQXubJMdBSmO8
+        2K/gVQEp9IvowTGeEqpihzd1hmBBU2RDxDCi3PQkhVyo6hanJGKkntJTDNEn
+        QjuT/XvIlhPihF2b0XogtF5YNc9Vbll37M4kzRuY4Jo3aV2VeMpW1eBd0Ltt
+        gYwjJ++Up8J7D4qYxFmO/Rb1gKFUqqsKR/aw5eXseVo5qRK8sQlyup4Raqv9
+        HkAMLfWFKEsisnXSM7aUJ8+WztWllykVJdoo6l3FTgUhBkx6EZFHjhu8veNo
+        mK1VlvhmeYfnSbcW+H4RcQ05AVdhN3+XQHvyXYbE7hrwQtrqG5zAef4ki5jn
+        zj4UKBCrOmkYMtUkmVz02FweMobD4/nTHuVOLubz5EED9ZbMUSNYZmjz6pcw
+        VhiOee2JLZt8PbQwqO0mmmzgPcYsQoEuoIIqVc+TU3vSm2uq2cnRZBWTr2Lx
+        ptrDXUGn4pPrYobapChbMsl8lVU/XVGMD0E6yMokuq3yN9rNvuIgY4Oba/2C
+        r8sn+KSj9IkIvkiQ5ijNfpoPCZtrNJE6EqC5l89dm2tDkUQg4RvwDbCzwce/
+        hnyS/2JcCnf7BiJDIamFZt+Fx/fYxU5JsGWiFO1+4iHamhaplTT77Oe4FGvw
+        9JOn1NQzzjX2c0xKuNr9tl+H1NYYhR1fOyF2NEHslDq9NfMJKcBRrj6+x1mG
+        ugORoBTiiRtilFQccq6qrVqeu20pdAjTdu8vU+VacmpJl62aQbszMFUtKvwi
+        VHWlvg/z3JdvtWpB1hZkQ+XvjrBnvqZbakXJ6KuqqZLIPcMnt44UhoONZju0
+        rTlLLpRn5FsOqJCr1oyCMq3ylwOO68IuRwzShg7SJ4wWMCnBr2pi+xV1jQ+r
+        9jN9E6Dxa5JMwU9SoL3vIVr7/ON/IXbtIaRNhP9A2wPb5RsaBduI3/oivrWf
+        GHeivw7en/zkcQBHyJLb7uv7HW0HN3DoEV724b5txT076lrHkz8dwVHSMX5P
+        UTAcY9TBiKcSvRtIc6TUIwzuhom7MHEkMeSyPI7vaA5z1BO2y7BLOGmvRYw4
+        6iO8xvDABa2zElxWI09j9freWI0+g9X43lmdbmRF16Y3qzNsG2gjK7oQnYga
+        vM4x/NbEqx7AFL6nOeSuT9cISTnSsMMt6rC6uJtV1GUVpeRcIp3L5oJtmn1G
+        pmafI1Nzz8C+8hzYdIV6V2GhaRWkSf5F1fE640Qk9qU2cXUdi+t4776780K2
+        n7gtMNENTKREvk/6K/w7moM276C1p/5B9y8I+u9vwX7AYf34wR5ZSxP8dhe/
+        3cWfdvHnHPzEDvzudSztCTzhgidc8LybwLSTwGDfOoreOajnMeh2s4KbTg+e
+        ciKLpRIqr+wmyqkN3Npq6XoEMTeCGJbxoVvXkg1mOJEcdyKJcJgN1Bo3RsRB
+        8Tvefvxoz1/iJ5pNsvmIgry9CH8GdzK4SyM+5sMnGXyKzxbBTHyOtUX65YkO
+        E1/Y/1ETeRPzJnImOm3JERM9JpL287A9jpgYNfGGiUn7ddrEeRNZE3P/Axpj
+        kXLPDgAA
+        """
+    )
+
+    /**
+     * Extensions / subclasses around Kotlin immutable collections, both in source and compiled
+     * form.
+     */
+    private val KotlinImmutableCollectionExtensions = kotlinAndCompiledStub(
+        filename = "ImmutableCollectionExtensions.kt",
+        filepath = "stubs",
+        checksum = 0xf50711c2,
+        """
+            package stubs
+
+            fun list(): List<Int> = listOf()
+            val List: List<Int> = listOf()
+            object ListObject : List<Int> by listOf()
+            class ListSubclass : List<Int> by listOf()
+
+            fun set(): Set<Int> = setOf()
+            val Set: Set<Int> = setOf()
+            object SetObject : Set<Int> by setOf()
+            class SetSubclass : Set<Int> by setOf()
+
+            fun map(): Map<Int, Int> = mapOf()
+            val Map: Map<Int, Int> = mapOf()
+            object MapObject : Map<Int, Int> by mapOf()
+            class MapSubclass : Map<Int, Int> by mapOf()
+
+            fun collection(): Collection<Int> = listOf()
+            val Collection: Collection<Int> = listOf()
+            object CollectionObject : Collection<Int> by listOf()
+            class CollectionSubclass : Collection<Int> by listOf()
+        """,
+"""
+        META-INF/main.kotlin_module:
+        H4sIAAAAAAAAAC2KMQrCQBBFRzQWUyhsZSdYiYFcQiwkZbzAJhlwYXcnZP5C
+        ju8WFv+9V3wi2hPRrq75m7jli8/zqmHeuknToibdWjJCEncesl/sqxjgIT34
+        zo2hjOau75QK/BjlqTHKhKD5tUGy1bD6PPEBYnDHT2WPGz3oB8hyC49/AAAA
+        """,
+        """
+        stubs/CollectionObject.class:
+        H4sIAAAAAAAAAK1W21MTVxj/nQ1JlmWVEI0IXhoraiDFIFpvpFSkWINcVJCq
+        tLVLssLCZjfd3VDs1d7svX3zodOnPvtQp61inWmpfesf1el3dtdNhMVxHGfg
+        nLPfOd/v+323c/Lvf3/8CeAQfmDYYjvVGTs3aOq6WnQ00xifmadFHIxhbmRe
+        WVRyumLM5jxxnyepOppep5KvO1cwHHVWtfr6+0YWTEfXjNz8YjmnkdQyFD1X
+        VqwF1bJzZ0aVSkUtjbqffQyJ1ZbiaGDYHGYtjhhD5xODxyEyxPKaoTn9DJFM
+        55QMCU0SopAZ0j5OMYCvj4V9hnhsZGhUyxXn2ohmOwzJTGddELisT0YCLRKa
+        kWSQOzpKqq7OKo56pYf8Wnt2M1KNELCFocGZ02yGrSPhOaCwiEXTcBTNoFMN
+        mULnZYaWNaGOYztDfFHRq+r4VUoonQvJh4ydeE7CDqQZNj7KKY7nGVKZtcnu
+        vCyjHR1N2I09ZILcKqsGhYAVGJoeMhvQdYa2TGhh9HHG+8P38tm1Bvtdhd0j
+        pjWbm1edGYsbyCmGYTqKl5sx0xmr6joPjU/HFtHNsDOsHsh3iwC0oh1Hjlws
+        zqnFBR/hrGIpZZUOMuwLcb1OMsFBZvt43RxAr4QeHJTRiS4elhcp3uGeU7w0
+        e4iXjVt0FMmjOMZVjhN1jewqjmnxbNVXU8GXk3Y2dCO802Tk8RLHfpmszqrO
+        hPau6lqlPDXY9CFjECf5gVdIrJRK5HMN54JhVysV03LU0niFmyH6Q0tFteI1
+        26sMBwN5WrPTlIx0oJG+alppS1VK3aahX0vX2khEYVVR1cVRwhkJpzFCjUls
+        3ArKPUGV1DzmZRIt6qpCIYxZatlcJIeTa9NIrevtujZEb12gLtlVb+5q1XCN
+        5c5aakkrUuu6Bo48/ky+e11qQoVaf+fjLbjUeAe51Oruv7FqeYZ39WVeKIYz
+        xRtbxus4KWEab/CO3CbR/XFFxgCXCVBknPJkRcq/Yw5YlkJVl8lMh7R0iIxu
+        wfzk8ZBuzExPTpIGDRRthaOKmGPYE9ZrtZRNegTimGfoX+deeEJmMlToEhZQ
+        ZtgUyjyVCfcou96FtI6Vt7kVKiYxX9Tdp4KHk94HsTA2MTkwNjgkYxFt/N5+
+        hwKw6lIP70q6qx8+gaOU6JLiKCQTyosRensZH6J0lS6QaEnjX1QyQukAw08r
+        17dLwlZBEhI76V+UBDFKc5M/Z8R/bghbV673ismGpNAj9LCTcVF48HNMSESG
+        WxLxdqFH7I0lGmkWTj+4GRluTUiuTE40tQc6tMOGGxMy33HXzYkNwe5Grnc+
+        mWjgGBcf3IwSeqy9QYwmYpxjLyP+SBfK5aqjzOhqLbxDS45K9y1d1PsX6J3Y
+        dr5qOFpZLRiLmq3RyYHaTU7lP6HNGopTtah1GwbNEk3NI5qhevU/yZF5T5tF
+        RZ9SLI1/+8KO1bjBZf6IgQ0TjlJcoN8Cvpo0YVatonpK4x9tPsbUGmZ0ywv0
+        40BAHDzfbTzx5O8NSlGM5heARJI/4rT+gmQCrmETjfSbgiRfkiRPXwLNG7vu
+        YkNXJL+MTb+j9bZ79isaJXc3RXMKX9NKJj06ja1kh0eWGtxHOhwg/YbWbcvY
+        dQ97BdxyT3HNLd6ur8lX+5ChPcbfJ0RcjGM+Rks2uX8ZhzhS9h4Or4VpCWBa
+        0I0jgXtZfENznHm+00gPmc/Ps0UecdR7oPKugXpeSYFX9ET5jFZpnWD4ZR0t
+        j0B/fexppGsv3P7Q4+yfCqLaSzy4w9J9nL6UHL6L0b9WhUIKQiEFER2jiApP
+        oV8fynFanQ3qJEM4bB2c1ezPoeMp2Z932U88A/ZZWk3iwlPhvIaLAc4UrS49
+        Ez7n+M9TPy7n/TpPZf/Gjh8Rjdzqyq5g+g7evIO3eFlE8K07ska3C2NuhFN1
+        dlKBnZQft3P8d5OPn/NrLdp1BzO3gmauh/GSFvVgEgNUcg/JnfDJyTVOpXAM
+        j4ocUJGDFKq46ofsiI/WnE1qvKVXEM8uw6h1kQfSHIA0Yw5mELdZF6ziU9vr
+        +yVymGXYq3tR9FFEOEHltrr4QNN9CJfuovorlm67gohvIoLv3PlzfE8zT/27
+        FJf3phEp4P0CPqARH/LhowKu4+NpMBuf4NNpNNtos/GZ+9dkY9DGgI2TNtpd
+        yT4bnTa6bRy1kSfJ/3e4UsLJDgAA
+        """,
+        """
+        stubs/CollectionSubclass.class:
+        H4sIAAAAAAAAAK1WW1MURxT+evbKMMqyCgIqWSPqwgYX0XhjQwSCcZGLAhKV
+        JGbYHZaB2ZnNzCxBczOJuf4AH/KYZx+SqkQxqUqIj/lRqZyeGWfXZbAsK1XQ
+        3XO6z3e+c+vef/79/U8Ap/ADQ4dlV5es7JihaUrBVg19rrpU0GTLioExrEyu
+        yutyVpP1UnZmaZVODLmSqq1qdUq5unN53VZKijk0PDS5ZtiaqmdX18tZlaSm
+        LmvZsmyuKaaVvTwlVypKccr5HGJINFqKIcywN8haDFGG3hcGjyHOEM2pumoP
+        M4TSvQsSRDSLiEBiSHk4BR++PhrWZeKxm6FJKVfs25OqZTMk0711QeCyIQkJ
+        tIpoQZJB6ukpKppSkm3l1gD5tf3sXrQ1QUA7Q9heUS2GrsmdskCBiRcM3ZZV
+        nc6F0/nemwyt24IdwwGG2LqsVZWZZYZ2OheQEQndeEXEQaQYdj/LKoZXGdrS
+        29Pde1NCF3qacRhHyAQ5VlZ0CgLLMzQ/ZTaiaQyd6cDSGOKMjwfv5TLbDQ47
+        CocnDbOUXVXsJZMbyMq6btiym51pw56uahoPjUfHiqOfoTuoIsh3kwDUAhV0
+        llwsrCiFNQ/himzKZYUOMhwLcL1OMsdBSkO8ck5gUMQATkroRR8Py+sU72DP
+        KV6qNc4Lxyk7iuRZnOMq54m6SnZl2zB5turrKe/JSTsTuBHcaxJyeINjv0lW
+        S4o9p95RHKuUp7BFHxLGMMoPvEViuVgkn2s413SrWqkYpq0UZyrcDNEf3ygo
+        Fbfd3mY46ctTqpWiZKR8jdSyYaZMRS72G7p2O1VrpDjyDUVVF0cRl0VcwiS1
+        JrFxKij7AlVS85iXSaSgKTKFMGoqZWOdHE5uTyM1r7vr2Ii76zx1yaF6c8tV
+        3TGWvWIqRbVAzesYOPP8M7n+HakJFWr+7udbcKjxDnKo1d2A09XyEu/qm7xQ
+        dHuBN7aEdzEqYhHv8Y7cL9INckvCCJcJkCVcdGUFyr9tjJimTFWXTi8GtHSA
+        jO7B3Pz5gG5ML87PkwYNFG2Zo8axwnAkqNdqKZt3CcSwyjC8w73wgswkKNBE
+        rKHMsCeQeVs62KPMThfSDlY+5FaomI403NjBDUfX8NP3bYpyWJRtmWRCeT1E
+        TyvjQ4RuyTUSbaj8i6pBKJ5guL9194AodAiikOim/7goxCM0N3tzumPr7mA8
+        GU4KA8IAG408+SkqJEITrYlYlzAQH4wmmmgWLj25H5rYlxAdmZRo7vI1aIdN
+        NCUkvuOsWxK7/N3dXG82mQhzjOtP7nP0aFc4HklEObtBRsyRypfLVVte0pRa
+        zMY3bIUuUbp9j6/R5d80p5Z02a6a1HHhMaNIU8ukqitu2c5zXd6KRkHWFmRT
+        5d+esGe2qttqWcnr66qlksi/g0dqNzzD/sZjz+zumrPlwho98R6oOGdUzYJy
+        UeUfnZ7qwjZFuroFevMFxNAElkjyd5j8/YKSI8BGktb0s4DGL0mSI5lA8+6+
+        R9jVF8ptYs9v2PeLc/YrGkVnt53mdtyjlUR6dBod6OT55x3qIZ32kX7Fvv2b
+        OPQYRwU8cE7dczCEOk2+OoY07TH+wCDkYJzzMFozyeObOMWRMo9xejtMqw/T
+        in6c8d3L4GuaYxz1NUeFXiKPn2uLPOKoj0FFXAN1vRJ9r+iN8Rg1aF1g+HkH
+        LZfAML6hOerbp3sr2P748+xf9KM6SDy4w+IfuHQjOfEIU381hEL0QyH6EZ2m
+        iAovoV8fyhlaXfHrJE04bAecRvZX0fOS7Gcd9nP/A/sMreZx7aVw3sF1H2eB
+        Vjf+Fz5X+e9LLy6zXp23Zf7GwR8RCT3oy2xh8SHef4gPeFmE8K0zsianC6NO
+        hNvr7LT5dtq8uF3lP3w8/KxXa5G+h1h64DdzPYybtIgLkxihkntK7oJHTqpx
+        KgZjuFQkn4rkp1DBsheyMx5aSyap8pbeQiyzCb3WRS5Iiw/SghUYftxKDljF
+        o3bU8yvOYTZhNfZi3EMJedohfOfMd/E9zTyrVXJ5fRGhPD7KY4NG3ObDnTw+
+        xieLYBY+xWeLaLHQaeFz56/ZwpiFEQujFrocyTELvRb6LZy1kCPJf/behL1p
+        DgAA
+        """,
+        """
+        stubs/ImmutableCollectionExtensionsKt.class:
+        H4sIAAAAAAAAAJ2V3VLbRhiG37X8IyvCFrZJYkMS4wCBJCAgadIUSprSJHVj
+        SCZ0Mp3hSAaNR2DLjHfNJGdcS6+gLSedHnSYHvYWei+dfrsoklHsTpIBaXe/
+        n/d79kfrv//9408A9/GKYZaLfpPb9U6nL5xm293sttvunvC6/tO3wvU5dfgL
+        kQFjsA6cY8duO37Lftk8oKAMNIZk2+OCoTC/0FD+vvDadoNsawy3PjCuNyKR
+        ui/clttb26DIm41ur2UfuKLZczyf247vd4UjMbi93RXb/XaboqqHXdH2fHsv
+        hOR2BKw4swxZt3Mk3slqJi4hbcCAyZBpuaKhUJPnjRXnNZGHlUUC4wwadylk
+        /AL/jivnNBe3jZpSeQgshSvKywy6oiSDiasoGbiCMkOaIHdkZU2987HqJqZw
+        TRJep4iOcxQn3HKOqPCjuG0Y4SdAk4KCvvkemgwmZjFtYAZz59BbEkZT73wM
+        yMQCbkvoOwxGpMtw9QJntI+EsTjCNWqtS8OCM1hmGCO4zYGixuDg8vD6Ju7h
+        viT+gma8vkfr4YkNmt78whv6YD7yRM983Cl5+NlbdeeTVmi8EezsliucfUc4
+        ZEt0jjW6B5h8pRjYoewkyP7Wkz1avcT+CsM/ZydzxtmJkbCu06MbCV2jthq0
+        M0FbozZdMa3xil5IFhLLiWVGo0I4SlcKVrGSOx8FNoMiSmFErnbFOjuJ0v/6
+        Oa1T3UpS16wk+VKRVuTKWHrtmpWNC0cBlyyTcseiKpErb1lyiquM1gDV/70C
+        lw7pc8zueC3fEf2eyzD5uu8Lr+PW/WOPe5T1JLqx6IrZ7O678lPwfHe732m6
+        vR+lMh2/nW6/t+c+8+SgHGi8+UABK3T6krQHSVTkrUSjH+Te4BFeUJsmXp3a
+        irwPQt9XMR99dqFvLeajAx761i/4sigjRSMNDRrVyMqkV1v7HWO/yNOCLXob
+        lCfpUvScq2QuqJSRCzWmlAJF/4ZCpJBW1tSI7CJKwwgqcYIsKWQDjYmYxmSo
+        MUBwI05gjMiuYnoYwa04QY4IcoFGLaYxH2oMENyNE+RHZC9iKcieDQiyahfO
+        sBKHKFJKMZCxYzKrocwAxIM4RGloto6H+JL6MvunAGJGQZyioDbkFDfUspzi
+        7nu4Uzz4NVSvKZ2U+tOJdowei6Y8QQ/97tEyl6jqtqpdx0tqDyjza4re2IVW
+        x+M6vqE3ntTxLTbr+A5Pd8E4nuH5LiY47nF8r/5XOZY48qqf40hzLKj+PMc0
+        x5TqT3KUOBY5UhxVjuJ/gOL8xQkJAAA=
+        """,
+        """
+        stubs/ListObject.class:
+        H4sIAAAAAAAAAK1Y+18U1xX/3ln24TDIggICUbdG48JGFzXVBiiVGNMMIiaC
+        NEo0HXZHHJmd3c7MUkwfsa/0/W5smr7Td2tbbRKF2CbG/tY/qp+ee2d2dtmd
+        VcrHD3LvnXPv+Z7nPffIf/777nsAnsAHDEnHLc872UnDcU/NX9ZzbhyMYX7y
+        srakZU3NWsh65BGPUnYNUxwerTmhWq6+oNsjYyOTi0XXNKzs5aVC1iCqbWlm
+        tqDZi7rtZE+c1EolPX9SfI6Q6HoZcbQwbF4rJ44Yw8C6YeNIMMRGDctwxxgi
+        6YFZBTJaZUShMKR8nFzRNEmeUbSc7LHq+gRJ28ywSS+U3CtcOENneqDO8BEF
+        SXTIaEcng7J7d1439QXN1V8aIosaz25F1yZI6GZocS8ZDiFO1nucXJHIFS1X
+        Myzab0mrA+cYOhrcG8cjDPElzSzrpy4ydNO5kBgo2IGdMrYjxdCVbgzjwDkF
+        fdjVijgeJThSvqBbZChTGVorWoybJkNvusaaqpdGuHb7w/dGM40CxwTDo5NF
+        eyF7WXfnbS4gq1lW0dW8CEwV3amyaXI3+Oo4CWQYdoRFney0CcDIOXHsIxNz
+        l/Tcoo/wnGZrBZ0OMuwNMb2GMs1BFkZ4dmQxJGM/DijYizR3yyHybbjllFAL
+        usv9usb1PryCwzjCAT7CEDWsvL5M/hUzDxcPq9okJKqCEXyUs45xFuc4zz+R
+        vRSsoxjnO0+RdwwyTXOLNg9+bVqqPp0UzIRuhF9WBU/jOMf+OIXe1BxX9ZRV
+        oHraTFCCm5SmaiC3r+E61MjONt1sJn8SJ7mcUwz9gUvDkIea7zaHfp5DT5ND
+        nfK8d5m3ptUGHEIfCCE3gz2DWQ77AlWJi3axoPphdouVFSXItPGyLqJH8W5x
+        6EPBBZznbC8RWcvnKT2r6Gcsp1wqFW1Xz58qcZso044v5/QSX8Qxz3AooKcM
+        J0X3JhVwpC4W7ZSta/l9Rcu8kqrWtQTydclWk/IyLsrIYYHylJs+SxWTtBKX
+        vi+tNr/1Q00211z7qrc4S3YdhWItRzRn6hqlWszWC8UlnRfMhhtD3vd2hc6y
+        rZdMLed97KkVeLFsCXHkZM2+4rmREopbPPzgc+E5wJmlEhX7XQ8WJPTkFVWo
+        FnF48eipZtsaZJ4rFNOGulsoaVWts+F7o/uaqtodDrbm9Z0qF+b5+/J5XmMs
+        d5Y/MQqu4ryMV/AF/l70y/SGfYlXuJ189RVesEb56qu8WIjV1xW8yDkkfFOB
+        5nF8WzxTIRVvlh8x+JHv8VoddiSswC7jCuf5obhx47atUZVMp+dCuENo9PyP
+        zgyHPFDpuZkZ4qCBsk/jqAm8TtUiLHHjeINyLOxhqp6Z8VSL42cMY00e0XXq
+        rOA1/ELGz/FLhi2hNnWlw23NNHu9m0j5DZfyW0qA0ZwpuifuaGqZEurU9Mz4
+        1LHjCv6IXt7K/IkcsK5qSU1MpR88Sbcgr7ka0aTCUoSaT8aHKPUdi0RaNvgX
+        3Skpf4Cxo3evDsnSNkmWkin6TchSIkpzK80RmnfQHKM5TTM/M8jpiX+/Km27
+        e/VgorOlUxqShthT8YR0782YlIxMdCTjfdJQ4mAsuYlm6dl71yITPUlZ0JRk
+        a1+FR6EdNtGdbOOn6PTmymmB0044SX+ngsMmNiU7OI5Ytyc7A6wtQkpHcmsD
+        R3uyKzjVLSg9tZQauWxiZ7In2GG0s81H662cON2ZbOHrF+5di5KWsb6WRDQZ
+        4348yMjHSKmFQtnV5k29mgLHl12dGijqvPYvUrnpP122XKOgq9aS4Rh0crza
+        mlH9mjYWLM0t21SIW44V8zS1TxqW7pWMGY7MK3Qxp5mzmm3wb5+4ux436M7W
+        CGibdrXcIrXwPps8XSzbOf0Zg3/0+hizDZrhAGVilH7j4DnZy5OT7F2hNIrR
+        PAgkO3nvTetVokn4C3bTSP8VIMq7RBmlL4nmzYO30TYYGV3BlnfQc1OcvUOj
+        LHZjNMfwT1opxEensY3kcM9STfSRDgdIb6OnfwUfWsVuCdfFKc7Z7e36nHy1
+        B4/RHuMNJyIC40kfoyPT+fgKDnKkzCqeaITpCGA6kMGHA/MG8C+a48yznUaq
+        1ERu1G8VT0q4i+037qPfsNCvxpc0Ur1vbu/H1mcvtbI+Rlp8k5c5xiqOsRp+
+        z9Ny4GlqUn0v1XE9y3CjCZfnlGfqbFDvZ8OJ9dlALWu4Ns89SJupOm2oQ/WR
+        DvnatPoRmpFQH57WQJVWPzwe6Ok6UOpPfdAxmnlVVQToI6s4G6lBTXl7AaqC
+        cwKVr+ZoJfn4n6jDpyc+PISfvF8IteCyHCS53B75DnJnO/XbuPR+naVyoJMc
+        OJ16heDaelaF8Xs21fIP+zZ5SBKtL2PRvxYbReK3ruIdUyCmfcT/z7ba21ug
+        lRWUJl4UWBOces8WsWuDni0Jz37qIWg/IPQY3ZAewq/JceI/snF++rHhbMiO
+        MpYCO1xaffoh+YM61YeUsS/jMxu07HOBRp+lUtMXZMppv9x0ZT7A9jcQjVwf
+        zNzFK7fwxVv4Mr/EEbwnRrZJPIUxoVGsRk5XIKfLyySK4OEggsM+fmyw/xZe
+        vYHKk9qIEwtwYr7lz/O/hDTRU6rR82sb05Pw1XXhf2PD+BeCCpn1K2R08Ba+
+        dT3UDd51jnow5EQtCNJRXzmlqtN3wjE8VWpLeSUkGr7ro53wk7BtsP/xCtz3
+        b4bCeTnZFsC1BTnZJoAlAl7GD+4D/KPwkD8QmNav4Zqf7Ed8+9sznT/hHdFd
+        /DSzgl/Vv4vtAVw7Xsevg4z/sQB709fyMT8SCQ6zgt/VP9QJHyWB3wdVuEfg
+        03t7B9LZ2/jDW/jzTUGI+CIieF/Mt6mdgrju1ymSf51DRMXfVPydRtzgw00V
+        /8Bbc2AO3sY7c+hz0OvglvjX6uCCgxcdnHc4nSh7HOx1kBHrww6GHex0MOLg
+        qIOnBVF1MCkWZxycczD3Pw/jQRHOFwAA
+        """,
+        """
+        stubs/ListSubclass.class:
+        H4sIAAAAAAAAAK1Y+XcT1xX+3shaPB5jWWAb2wFUliBbARmTQmO7Dg4hzRgD
+        CTZuggPpWBqbsaWROjNyTbqE7vve0DTd072lLbQJ2ElP6/Jj/6ie3vdmNJKl
+        Ebg+HGDe0333fne/7x3+89/3/gngSfyDIWE75Xk7M2XYznR5PpvXbDsKxjA/
+        taStaJm8Zi5mLswv6Vln1KWUHSMv2MdqOFTT0Rd1a3R8dGq56OQNM7O0UsgY
+        RLVMLZ8paNaybtmZs+e0UknPnRM/Rxni9TqiaGHYsVlPFBGGgS3DRhFjiIwZ
+        puGMM4RSA7MKZLTJCENhSHo42WI+T/qMomlnTlf3Z0nbDoZWvVByrnPlFKDU
+        QJ3jowri6JTRgQSDcvBgTs/ri5qjvzpEHjXy7kJXKyR0M7Q41wybYddUY8wp
+        GLFs0XQ0wySOlpQ6cJmhsyHAUTzGEF3R8mX9wgJDN/EFZEHBXuyTsQdJhq5U
+        YyIHLivow/42RHGA4Mj8gm6Sq0xlaKtYMZHPM/SmavypxmmUW3c0+Gws3ahw
+        XAgcmCpai5kl3Zm3uIKMZppFR3NzcL7onC/n8zwMnjl2DGmGvUF5Jz8tAjCy
+        VKpHyMXsNT277CG8oFlaQSdGhsMBrtdQpjnI4iivjwyGZBzFMQWHkeJhOU6x
+        DfacSmpRd3hcN4Xeg1dwAic5wIcYwoaZ01cpvmLl6eJpVZukRFUwig9z0XEu
+        Yp/hFSjql5J1ChP85BmKjkGuaU7R4smvLUzVo5OB6cCD4HZV8CzOcOyPUOqp
+        EB3VNVaB6lozSSWep0JVfb19DQ1RozvT9LCZ/imc43ouMPT7IQ1CHmp+2hz6
+        RQ49TQG1y/NuO+9KqQ04hD4QQG4GewmzHPYlmhMLVrGgeml2ipUdFci08Zou
+        skf5brHph4KruMLFXiWylstReVbRL5l2uVQqWo6eu1DiPlGlnVnN6iW+iWKe
+        4bhPTxp2kvom6UskF4pW0tK13JGimb+erE62GHJ1xVZT8jIWZGSxSHXKXZ+l
+        mUlWiabvS6nNu36oyeGmtq9Gi4tktjAoNkuEs3ldo1KLWHqhuEKBTDR2DEXf
+        PRU2y5ZeymtZ98ehWoULZVOooyBr1nU3jFRQ3OORh/MF1wAXlko07vc/XJGw
+        k09UYVrI5sOjp1ptm5B5rVBOG+ZuoaRVrc4En40daWpqdzDYpvv3fLkwz++X
+        z/AZYzqz/IpRcANXZLyOz/L7ol+mW+zzfMLt47sv8oE1xndf5sNC7L6q4BUu
+        IeHrCjRX4pvimgqYeLOcxeAs3+GzOoglaMCu4jqX+b7ouAnL0mhKplJzAdIB
+        NHoAjM2MBFxQqbmZGZKgD1WfxlFjeJOmRVDhRvEW1VjQxVTlmXFNi+InDONN
+        LtEt2qzgDfxMxk/xc4adgT51pYJ9TTe7vZto+RXX8mvybUuDkN4nlcfeOSrw
+        nOZoRJMKKyF6WzL+CdOTYplIqwb/Re0i5Y4xNrJxY0iWdkuyFE/Sv5gsxcK0
+        ttEaonUvrRFaU7RynkFO371xYziWaElIQ9IQeyZ8/+2IFA9NdsajfdJQbDgS
+        b6VVev7+zdBkT1wWNCXe1leRUOiETXbH2zkXce+ocAucDsKJeycVHDbZGu/k
+        OGLfEU/4WDuFls74rgaJjniXz9UtKD21lBq9bHJfvMc/YXSy20PrrXBcTMRb
+        +P6l+ze5t5G+llg4HuERHGYUXSTVQqHsaPN5vZrXM6uOTq8iek4dXaYZ0jpt
+        LJqaU7ZofracLuZo6ZgyTN3t9BkuywdrMavlZzXL4L894sGLZdMxCrpqrhi2
+        QST/UTVRfbLRfV3Ptum0fdrRssv0MvdA5eli2crqzxn8R68nOtsgiGPU3GH6
+        F0UrWDzBn8/k79+pgCT8FgdoT695+r5DlDGiSbTuGLyH9sHQ2Bp2voueO4L3
+        XfrK4jRKaxR3aaeQHHFjN3p5jfKh5iGd8JHeQU//Gj6wjoMSbgkuLtntnnqS
+        fHcIj9MZ4y9GhATGUx5GZzrxxBqGOVJ6HU82wnT6MJ1I44O+ewO4x83lqINC
+        hEYtkRvtW8dTEjaw5/YD7BsR9q3RPuLj0cBu7u/TW/OX3qIeRkr8pihzjHWc
+        ZjXybqRlP9L0yvSiVCf1PMPtJlJuUJ6r80F9kA9nt+YDvTmDrXnhYdacr7OG
+        npge0nHPmjYvQzMS6tPT5pvS5qXHBb1YB0oPTA90nFY+OxUB+tg6Xg7VoCbd
+        Mx9VwWWByndztJM8/I/W4dMdHZzCjz0ohZrfLMOkl/sjv4/sywn9Hq79q85T
+        2bdJ9oNOl73ftq5XQfKuT7XyI55PLpJE+yUse22xXSTedZXo5AViykP8/3yr
+        7d4C7Ux/NPGhwJrg1Ee2iP3bjGxJRPbjj8D6AWHH2LbsEHGNT5D8ye3L0x8L
+        9rb8KGPF98Oh3SceUTzoqfmIKvY1fHKbnn3at+hTNGr6/Eq56I2brvS/sect
+        hEO3BtMbeP0uPncXX+BNHMK6+LJWcRVGhEXRGj1dvp4ut5Iogyf8DI54+JHB
+        /rv40m1UrtRGnIiPE/E8f5H/V0YTO6UaO7+yPTsJX90S/te2jX/Vn5AZb0KG
+        B+/iG7cCw+C2c9iFoSBqfpJOecYpVZu+FYzhmlI7yisp0fBtD+2sV4Ttg/1P
+        VOC+eycQzq3Jdh+u3a/JdgEsEfAqvvcA4B8Ep/yhwLR/Aze9Yj/p+d+RTvyI
+        v4g28OP0Gn5Rfy92+HAdeBO/9Cv+hwLsbc/Kx71MxDjMGn5Tf1HHPJSQJx3C
+        e2L9G96nlXfy7yhJv59DSMUfVPyRvvgT/9xS8Wf8ZQ7Mxl9xew59Nnpt3BF/
+        22xctfGKjSs2pxPlkI3DNtJif8LGiI19NkZtnLLxrCCqNqbE5pKNyzbm/gd3
+        15BHbhcAAA==
+        """,
+        """
+        stubs/MapObject.class:
+        H4sIAAAAAAAAALVY+3/T1hX/XvmJowTFIU9GyWgAJ4E60NJC7bEmWQIm4RFC
+        QwkrVHGUVMSWPEnOSPcoe7R7vzfWde/uvbEtrG2Ass/G2G/7o/bZuZIsO46c
+        OIF9PrZ0de+533Pu95x77pH+898P/gHgGfydYbtpFWfM5Gm5cHbmmpK1ImAM
+        1vg1eVFO5mRtPul0p5yeoqXmuGy6QiCjWcq8YqR8uo6nxhd0K6dqyWuL+aRK
+        vYYm55J52VhQDDM5RkgFZfa0/ZhikKq1RhBkaFylOYIwQ2/dqBFEGcJpVVOt
+        4wyBRO+UiBgaYghBZOh0cbJ6LkfqVF2zmTDHSHMTQ1TJF6wl6mBoTvSuZiAl
+        QkJzDNsRZxB7emaVnDIvW8rVAeJ0jegOtG6DgDaGoPWqahLeeBXvtPyGrK5Z
+        sqqZY8oSCSYyvdMkuIbVCD7EEFmUc0Xl7BxDG8n5UC/iCeyOYRe6GVoTa/3Z
+        Oy2iC3saEMGTRMwCV8kyxHbJiCmuQMR+RybBELJVkuy8YjH0jOvGfPKaYs0Y
+        XDopa5puyQ6FZ4q5nDyTU2hN+/xUr+0S0Y+DXM9TtDTVHOG82+4iKwdwiI8c
+        ZoiR5hHNMlTFrPbIpMIZPFfdl17tiR4+e6nu4D1OkE+ut07d4ktN8UjhwKRQ
+        xFEc4eYeo4WQueRKk7Pgb1eVPopU8oON8hEH5biDMqm+pth0kIOCJj2IGMIg
+        Fxhm2EYCtrNIUccqRcNeWBP0wRpDNU2x3W2KOIlRrolUh7I5RTYY9pdnvKiZ
+        xUJBNyxl9mxBMWxiRq5nlQJvRDDO8LTX362a3URetzeje043ug1Fnj2oa7ml
+        7vIujOJMVdROkte1+ZSzfc/FcBoTRE1WzxeKFlFzIlHTp/Zy54qaDZwcUkfd
+        Zspv1zC8sXmk9EGfKX59/b5U+9shFCiRtNQYOsSwe4PVURZy2cnMDc6YFJ8M
+        I/WubQOO9M3i+DK0GTZ2rWslnRzeWs8ZirPYUF4x5ik0pmsb++jR8tZjAf8/
+        BRBlzACRwtCeyPieEbTJaXwwl2OIJ6rOrN4phnRVZ9pPfw2baHpwztDzdKyR
+        jnIMpupkrIa9hpLXF8mr+zc4V8pT4msF/af7nZGUYwylkJOzSpmN+ny9ejEE
+        FHOBbLr3JDYKN+LvlQ2EHjVsplZVXGeK+RleXJCPolRTucf/IgZjKOKTvFjY
+        GaMSZomXBHbrU/zQ3s1bn+GtHG+9LlJVeYS3Pici5bS+IOIFjiLgDREjGOWt
+        L1Ulo7VF5kZ70CscJnGBI36VYbhOxPXxpnGZ431DxBUH+VsMF+sKl61YfxWv
+        cB3fZThaX0j6gWQxy0F+IELFNd76oYgFxyE/Yji2CeOrK0QdBY7yE96ykX9G
+        0ZHO5ux6mj9TER3NnJm8MHhmeETEO+jkZe6vGJ7b4vsCr4zdovy0YsmzsiXz
+        XJZfDNALC+OXENWpC9R1XeVPdEgKs4cYa3tw40BM6BBigtRD/2hMiPL2Hvrv
+        ozY9S0/QPUD3BrqHo/9+U+h4cONwUzwYFwYE5zrAhiJR4eE7YUEKnGqW4l3C
+        QMvhsLSD7sLJhzcZ9bW6fW1eX4fU3hXsYANChWTAxug4tU3q5PJc7nyPFOza
+        EZfiqzWGB0IvPbwZIvlwVzAakaLnO6RtXVF3tHIsRmNxqYFrqOgVpUaa0eTN
+        2F4xJknNnB06BkB5TCkVzsEFuybtzuTzRYuX6eVacOS6pWgmr22fWqA8sPN8
+        UbPUvJLRFlVTJcnBcvFLdeekOq/JVtGg3Bgc1mcV/uKjaoqTSC5wZJ599ayc
+        m5INlT+7nY2TlpxdoLBwn2OTetHIKqMqf+h0lU6tUYlDFFsh+kfAo6yThxut
+        7D0KgzDdnwOkOH/Tovb71CfgN0jQlV73qGeFetL0JNC9qe8OGvsC6btoeR/t
+        t23ZO3SN2aMS3SXcpZZI80gaHaSHc0gp0EV61kN6D+077+LD99Aj4JYtxWe2
+        OaPuTN7ai300xnjyrI3Ruz5Gn4tBaZfGOMYxF6O5jJEU8AC7lqtgmj2YZteU
+        Em0HbEl6yXLNStgqiAwOeQ9PswqTHEJiHiGU6xHwm/U8w3KNWY5rnq10G11T
+        tZA+uhFSugqJzhr/lXxsvZXQueSv/9RG+k9U6R/zwi1BiLb8fZy+FD97B+f/
+        WVM/nWKuS9M0K1BjVrcz4vkyhilcdJFewiVCcGx6kfroHHtkxJc9xI9T35XH
+        biOdfi4iZz9YA7HPGamBeNGO7xhmCDvgYss0Soeit+03Y62zO3iLbzeB2grm
+        XCsPk7RQA6nNtaOM9GpFKpqnFh3OW7KoerWMH+4u0uYs2ou8Hd0L0LbITd7j
+        Jm9bQgWCi/Q4PHjR3jH6Y+PpEzC25LkpiqWS50xM8A9lrkXn3YTb2v8v7Hob
+        ocCtvv4HKK7g+gpe4+klgHv2lW2zj5SwbZFUoafV09Pq8jnBP7LVgf/pTeP3
+        ufj9XrxU47PlMv5nl7dkvzTIP965+M+7+OG+/hXcWEbpaF2LE/Zwwh4PR+kU
+        cPyVdLNwqG8Fn/eHcVJoqOpYmeCfznxAvlg/SJpAhrxTpBLkzVt1gEzwL2Y+
+        Fny5fgtOEKeT+IprwcnSLuCu2nVgBV/zR/LbEaX9amdeQp3G12uhfnMrqC/b
+        qFdq2/rtrdt6Fd9xUacof/AM0uSg0v/gCr7nj+zkmsqyqYTcRMh5t6iyTwvS
+        kcX3XR0TruUtpQ1xoLQvbq63hBZPUYuXHluc9Ejwqgc/5sI3ektYwVvrATd6
+        wI3eChqdFRDwgv+Oe3tTO45wdPzYxbnkctxc5tg28qf+Me/QXFlWloxs9mhu
+        JprzNs36ujz8fIs8IIpfeNVWu60SaLgP4dId/PJd/Pq23VEqCgL4wL6/i/t0
+        X6Jpv6Vt97vLCGTw+wz+QFf8kV/+lKFC8c+XwUz8BX+9jC4TnSaW7V+Didul
+        9jMmjpj4m4mUiSETL5gYNHHSHhoxMWryidTea2K/iT4T/SZ2mxj4H6im5hh+
+        GwAA
+        """,
+        """
+        stubs/MapSubclass.class:
+        H4sIAAAAAAAAALVY+1/b1hX/XvkFRhDZBAJkNCwliYFQk7Rpk9rLChkkDpAE
+        aElD1qTCCCqwJU+SWehe2aPt3u9lXffu3lu2sa0l7fb5bFl+3B+1z86VZNkY
+        GQzJPh9burr33O8593vOPedK//nv3/8J4CncY4iZVnHeTE7KhZnifDYnm2YE
+        jMGaWJZX5WRO1paSl+eXlayVcnqKlprj0ukKgYxmKUuKkfLpOpuaWNGtnKol
+        l1fzSZV6DU3OJfOysaIYZnKckArKwqT9mGKQqrVGEGRo3qQ5gjBDX92oETQw
+        hNOqplpnGQKJvlkRUTRFEYLI0OniZPVcjtSpumZzYY6T5haGBiVfsNaog4hK
+        9G1mICVCQiyKfYgziL29C0pOWZIt5eYQw74tovvR1ggB7QxB6xXVZGid2MI8
+        EdCU1TVLVjVzXFkj0USmb45Ub+E1gg8wRFblXFG5vMjQTnI+5It4DIei6EYP
+        Q1tiq0f75kR04XATInicqFnhKlmG+C4ZMcsViDjmyCQYQrZKkl1SLIbeCd1Y
+        Si4r1rzBpZOypumW7JB4qZjLyfM5hdZ01E/11i4RAxjkep6gpanmKGfedhhZ
+        OYQTfOQkQ5Q0j2qWoSpmtU9mFIu0XanuS2/2RS+fvVZ3+J4lyMe3W6du8aWm
+        eKxwYFIo4jROcXPP0ELIXHKlyVnwt6tKH8Uq+cFG+ZCDctZBmVFfVWw6yEFB
+        kx5EjGCYC5xjaCQB21mkqGOTonNeYBP0YI2hmqbY7jZFXMAY10SqQ9mcIhsM
+        x8ozXtDMYqGgG5aycLmgGDYxo7eySoE3IphgeNLr71HNHiKvx5vRs6gbPYYi
+        LwzqWm6tp7wPG3CpKmpnyOvaUsrZwFeimMQUUZPV84WiRdScT9T0qb3cxaJm
+        AydH1DG3mfLbNQyv7R4pPegzxa9vwJdqfzuEwhDPE/5DJxgO7bA6ykMuO5nF
+        4XmT4pNhtN617cCRvlscX4Z2w0b3tlZS7fDWesVQnMWG8oqxRKExV9vYh4+W
+        Nx8J+P8pgChjBogUhgOJjG+NoE1O48O5HEM8UVW1+mYZ0lWdaT/9NWyi6cFF
+        Q89TWSMd5RhM1clYDXsNJa+vkleP7VBXylPiWwX9p/vVSMoxhlLIyVmlzEZ9
+        vt68GAKKukA23YcTO4Ub8ffyDkIPGzazm85cl4r5eX64IB810KnKLf+rGI6i
+        iI/zw8LBKB1i1viRwG59ghftQ7z1Kd7K8dZnRDpZnuKtz4pIOa3Pi3iOowh4
+        TcQoxnjrjapktPWYudMe9A4OM3ieI36Z4VydiNvjzeE6x/uaiBsO8jcYrtYV
+        Lnux/iZe5jq+zXC6vpD0A8ligYN8T4SKZd76vogVxyE/YDizC+OrT4g6Chzl
+        R7xlI/+E4Zk9vgzQka30PjCpWPKCbMk8TeVXA/Q+wvglREfQFeq6pfInqn/C
+        wgnGpPu3j0eFDiEqSL30b4gKDbx9mP5HqU3P0mN0D9C9ie7hjvu3T7bEg3Fh
+        SHCuQ2wk9ODtsCAFLsakeJcw1HoyLO2nu3DhwR1GfW1uX7vX1yEd6Ap2sCGh
+        QjJgY3RcbJQ6uTyXm+6Vgl3741J8s77wUOjFB3e4znBXsCEiNUx3SI1dDe5o
+        5ViUxuJSE9dQ0StKzTSjxZuxr2JMkmKcF8rtoOSklE7DwRX7oNmTyeeLFj97
+        lw94o7csRTP5gfWJFdrcjTPqkiZbRYNSWvCcvqDwNxZVU5z9/zyfy5OmnpVz
+        s7Kh8me38+B0UbPUvJLRVlVTpa7h8lmYXhxmLDm7QgHhSkdn9KKRVcZU/tDp
+        Tp3dMhEnKKpC9I+gEUyK85clWtmfKQAE/IxyDeNvbHRdp5409Ql0b+m/h+b+
+        QPo9tL6LA3+xZfk1ao/G6B7DX6kl0jySRgc6eYzxHOYiPe0hvYMDB9/DB99H
+        r4C7thSf2e6MujN56wiO0hjj2a82Rt/2GP0uBuVNGuMYZ1yMWBkjKeA+uter
+        YGIeTMw15W/UDtP9uC1Jb0muWQlbBZHBId/Hk6zCJIeQqEcIJWsE/GY962D5
+        zXJc87Sn/xlbLlUL6cM7IaWrkKhY+K/kI9uthAqLv/6LO+k/X6V/3Au3BCHa
+        8v/A5LX45XuY/ldN/VSGXJemaVagxqweZ8TzZRSzuOoivYhrhODY9AL1USF6
+        aMSXPMSPUt+NR24jlS8XkbMfrIHY74zUQLxqx3cU84QdcLFlGqWq5m373Vjr
+        7A7e4ttNoLaCRdfKkyQt1EBqd+0oI71SkYqWqEXVdU8WVa+W8ersIu3OoiPI
+        29G9Am2P3OQ9bvK2JVThXaRH4cGr9o7RHxlPH4OxJ8/NUiyVPGdiin/pci2a
+        dhNu28C/0f0WQoG7/QP3UdzArQ28ytNLAO/YV9Zol5SwbVGsQk+bp6fN5XOK
+        fyWrA/+Tu8bvd/EHvHipxmfrZfxPr+/JfmmYf31z8Z918cP9Axu4vY5Sad2K
+        E/Zwwh4Pp6kKOP5Kulk41L+Bz/nDOCk0VFVWpvi3Lx+QL9QPkiaQEa+KVIK8
+        frcOkCn+ycvHgi/Wb8F54nQGX3ItuFDaBdxV3cc38BV/JL8dUdqvduYl1Dl8
+        tRbq1/eC+pKNeqO2rd/cu6038S0XdZbyB88gLQ4q/Qc38B1/ZCfXVB6bSsgt
+        hJx3D1V2tSAdWXzX1THlWt5a2hDHS/viznZLaPUUtXrpsdVJjwSvevDjLnyz
+        t4QNvLkdcLMH3OytoNlZAQGv+O+4t3a14whHxw9dnGsux7Eyx7aRP/aPeYfm
+        ymNlyciYR3OMaM7bNOvb8vDTPfLg1fsA3rXvf8IG3ddI5ue0o96+jkAGv8jg
+        l3TFr/jl1xn8Br+9Dmbid/j9dXSZ6DTxB/vXZOJuqf2UiVMm/mgiZWLExHMm
+        hk1csIdGTYyZfCK1j5g4ZqLfxICJQyaG/gcbVySQHhsAAA==
+        """,
+        """
+        stubs/SetObject.class:
+        H4sIAAAAAAAAAK1WW1cTVxT+zuQ2TAYJUUSw2lRRA6kG0Wo1FEHEGuSiJFKV
+        VjskYxyYzKQzE4r2Zm/28gN86GNXH32oq61iXaul9q0/qqv7TMYhhtDFcrkW
+        nHNmn7O/vfe39z4n//z7+x8AjuJ7hjbbqc7b6ZzqTM8vqAUnAsagTCwoS0pa
+        V4xSuibO1CRVR9P52cG6A1nDUUuqlRnKTCyajq4Z6YWlclojqWUoerqsWIuq
+        ZafPTyqVilqcdD8zDLFGExEEGVqfMxNBmKF306gRiAzhQc3QnCGGQLJ3VoaE
+        qIQQZIYuD6dg6jqZ00zDDds+T2a2MIhqueLcIgFDe7L3+XAzMmJol9CGOIPc
+        01NUdbWkOOr1fiJw3dFt6GiBgO0MQeemZhPeRAPJFL5YMA1H0QzaDiazvVfp
+        1DpKI3iFIbKk6FV1+gbDdjrXhHcZu/GqhF1IMHQk12eu96qMbuyJIoK9BEeu
+        l1WDomRZhugzL0Z0nRhK1sUy6tOU4d4dar43mFpvcMhV2DthWqX0gurMW9xA
+        WjEM01FqtE+ZzlRV1zkNnju2iBTD7mappjgtAtAKdgQHKcTCTbWw6CFcUCyl
+        rNJBhgNNQq+T5DhIKcNLIo1+CYdwWMYBJDktR4jb5pETX5o9xgvDrSdi8hiO
+        c5U3yXWN7CqOafHM1BdM1pOTdqrpRvPukXESGY79FlktqU5Ou626VilPQZs+
+        ZIxgmB84TWKlWKSY13AuGXa1UjEtRy1OV7gZcn9suaBW+CKCMYYjvjyh2QlK
+        RsLXSNwwrYSlKsWDpqHfSqx1iIi3G4qqjkcJWQlnMU49R964FZTeRJWsRczL
+        JFTQVYUoDFtq2VyigOPr08jQUtt1bdCal6y7rrtEpqrled4yOZ4Zw5nlXSPj
+        EoYl5DHLW2CnRF15WcYpLhNAyTxTk71LhDvmiGUplOZkcq5JDzWRMSQG8yeb
+        lH9yLp8nDRooPIWjilAYtjVjJoICw75mZb92Jl9zLQJiZ2iDFt2kzzKuoSTh
+        Bm4ybG0aU0eyeaypje6GDazo3EqZcjFY0N0LmRNNt7CYncrlR6ZGx2R8gC5+
+        T1LyezbzuvB71CNqkiqgqDgKyYTyUoDeMsaHEF1qiyRa1vgX3c1C8TDDT6t3
+        eiRhhyAJsT30L0qCGKI5SnOA5t00872k+PddYcfqnQExHowL/UI/Ox0Rhac/
+        hoVYYLw9FukW+sWBcKyFZuHc03uB8c6Y5MrkWLT7mY5MO2y8JdbKd9x1W2yL
+        v9vG9WbisSDHuPz0XojQw91BMRQLc18HGMWBRLZcrjrKvK6usTy27Kh0A9LV
+        eWiRbu6dM1XD0cpq1ljSbI1OjqzdrdQfOa1kKE7VonIJjppFlb9RmqHWGiTP
+        kXmXmQVFn1UsjX97wp5GXP96fc5Aa85RCov08HpqUs6sWgX1rMY/ujyM2XWe
+        4TAlO0T/EfC0d/H8U7yfU6rCNPcBsTh/O2n9BckEOIjTSA84Sb4kySB9CTRv
+        6XuE1r7A4Aq2/obOB+7Zr2iU3N2oq/E1rWTSo9PYQXY4s3QDeEjHfKRf0blz
+        Ba89Ro+A++4prrm9tutp8tU+7Kc9xl8MBFyMEx5Geyr++goGOFLqMY6uh2n3
+        YdqRwht+eL24S3OE1WKnkZ4Wz7+ka4si4qiPcYLVgdaikvyo6NHwPGrQop9A
+        P2+gVXNgsJ57GulebG5/9P/sn/FZHSA/eMDSE5y9Ej/3COf/bKBC8qmQfEYn
+        yJrwAvr1VE7SasqvE54htgFOo/fT2POC3l9wvb/4ErzvpdXMS8G5yH/oefHM
+        ePXZkfoLu35AKHC/L7WK/EO88xBXeDoD+MYdWYvbPWGXmWidnQ7fTocX70X+
+        C8TDT3s1Eup7iLn7fhPWw9TIDtVgYiNUKs+cG/ack9d8eq85Rs0V2XdF9qm/
+        huseZcc9tLZUfJ634iqKqRVoa9VfA2nzQdqgYMHn7X0XbNFzbb8Xl8hhVmA0
+        9pDooYgw/YrrdPHJ5ScQrjxC5RfYD1xBwDMRwLfufAff0TxHalXiZWkOgSw+
+        zGKZRtziw+0sPsLHdMDGJ/h0DjEbXTY+c/+iNkZsnLIxbKPbleyzccBGyl0f
+        s3GSFv8BceJNatwNAAA=
+        """,
+        """
+        stubs/SetSubclass.class:
+        H4sIAAAAAAAAAK1W3VcTRxT/zeaTZZEQBQWrTRU1kGoQrVZDEVSsQT4UkKq0
+        2iFZ48JmN93dULRf9Otf8KEPfeizD+05rWJ7Tkt97B/V0zubZRPJ0sPxeA7M
+        zN6Z+7v3/ubeO/nn39//BHAa3zN02E510c7Oqs5sdbGgc9uOgTHwiSW+wrM6
+        N0rZ6cUlteDkapKqo+ni9FDDgbzhqCXVyg3nJpZNR9eM7NJKOauR1DK4ni1z
+        a1m17Oy1SV6pqMVJ9zPHkNhqIoYwQ9tLZmKIMvTtGDWGOEN0SDM0Z5ghlO6b
+        VyCjVUYECkO3h1MwdZ3MaabhBm5fIzO7GOJqueI8JAGxku57OdycggQ6ZLQj
+        yaD09hZVXS1xR703wNDedHQPOlsgoYsh7DzQbIbdE000EwHxgmk4XDPoQDid
+        77tDdptIjeENhtgK16vq9H2GLjoXwLyCg3hTxgGkGDrTzXfXd0dBDw61IobD
+        BEfOl1WD4mR5htZNL0Z1nThKN0RzyScqJ7w7Ebw3lGk2OOwqHJ4wrVJ2SXUW
+        LWEgyw3DdHiN+CnTmarquqDBc8eOI8NwMOiyKU6LALQCZedxCrHwQC0sewjX
+        ucXLKh1kOBYQeoNkVoCUciIpshiQcQInFRxDWtByirgNjpz40uwxkRpuRhGT
+        Z3BWqLxLrmtklzumJW6mMWXynpy0M4EbwfWj4DxyAvs9slqiZNEeqa5Vuqew
+        TR8KRjEiDlwkMS8WKeY6zk3DrlYqpuWoxemKMEPuj60W1IpYxDDGcMqXpzQ7
+        RZeR8jVS900rZam8eNw09Iepeo3E8f6WpGrgUUZexhWMU9WRN24GZXeQJfWI
+        RZpECrrKicKopZbNFQo42XyNDC21XdcGrUXKuuuGNjJVLS+KkpkVN2M486Jq
+        FNzEiIw5zIsS2C9TXd5ScEHIJNBlXq7JPiTCHXPUsjhdczq9EFBDATKG1NDc
+        +YD0Ty/MzZEGDRQeF6hxcIY9QczEUGA4EpT29TNzNddiIHaGtynRHfqs4C5K
+        Mu7jAfWlwJg608GxZrbrDdtY0YWVMkPvTp4Oan6br8ckXW6RO5xkUnklRE8V
+        E0OE+tUyiVY18UWNVyqeZPhxY61XlvZJspQ4RP9xWYpHaG6lOUTzQZrFXnrf
+        xtpgPBlOSgPSALsYefFTVEqExjsSsR5pID4YTbTQLF198Tg0vjchuzIl0dqz
+        qaHQDhtvSbSJHXfdntjl77YLvZlkIiwwbr14LNCjPeF4JBEVXg4yigCpfLlc
+        dfiirtapG1t1VGpr1A9PLFM7bpnVSgZ3qhbdcviSWVTF46IZai2v54SuKA6z
+        wPV5bmni2xP2zlQNRyureWNFszUS+V1xtN5zGfZvPfbSbtuswwvL9J56oPKs
+        WbUK6hVNfHR7qvNNijhJ9ROh/xhawBJJ8fxRvJ/TJUkw0UFreoNp/IIkQyST
+        aN7V/wxt/aGhdez+DXt/cc9+SaPs7orGouArd8XEaexDt8gDUcIe0hkf6Vfs
+        3b+Ot56jV8IT95TQ7KrteppidQRHaY+Jlo+Qi3HOw+jIJN9ex6BAyjzH6WaY
+        Dh+mAxm844fXhzWaYwK131Wht8HzL+3aoogE6nOcYw2gtahkPyrq+p5HW7To
+        V8zP22jVHBjC1zRHffvU2ILtX/o/+5d9VgfJDxGw/Aeu3E5efYZrf22hQvap
+        kH1GJ8ia9Ar6jVRO0mrKzxNxQ2wbnK3eT+PQK3p/3fX+xmvwvo9WM68F54b4
+        pebFM+PlZ2fmbxz4AZHQk/7MBuae4oOnuC2uM4Rv3JG1uNUTdZlRGux0+nY6
+        vXhviJ8QHn7Wy5FI/1MsPPGLsBGmRnakBpMYpVTZdG7Ec06p+/RRMEaXV9Sb
+        rig+9Xdxz6PsrIfWnkkuilLcQDGzDq2e/TWQdh+kHRxLPm8fu2DLnmtHvbji
+        AmYdxtYainsoIU87hG/d+TN8R/MCnalQyJ8sIJSHlYdNIxwxVPNYwad0wMYq
+        Hi4gYaPbxiP3r9XGqI0LNkZs9LiSIzaO2ci46zM2ztPiPxBMeXd8DQAA
+        """
+    )
+
+    @Test
+    fun mutableCollection_stdlib() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = mutableListOf(1)
+                val set = mutableSetOf(1)
+                val map = mutableMapOf(1 to 1)
+                val collection: MutableCollection<Int> = list
+
+                val listFunction = mutableStateOf(mutableListOf(1))
+                val listProperty = mutableStateOf(list)
+
+                val setFunction = mutableStateOf(mutableSetOf(1))
+                val setProperty = mutableStateOf(set)
+
+                val mapFunction = mutableStateOf(mutableMapOf(1 to 1))
+                val mapProperty = mutableStateOf(map)
+
+                val collectionProperty = mutableStateOf(collection)
+
+                fun test(
+                    listParam: MutableList<Int>,
+                    setParam: MutableSet<Int>,
+                    mapParam: MutableMap<Int, Int>,
+                    collectionParam: MutableCollection<Int>
+                ) {
+                    val listParameter = mutableStateOf(listParam)
+                    val setParameter = mutableStateOf(setParam)
+                    val mapParameter = mutableStateOf(mapParam)
+                    val collectionProperty = mutableStateOf(collectionParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expect(
+                """
+                    src/test/test.kt:11: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listFunction = mutableStateOf(mutableListOf(1))
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:12: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listProperty = mutableStateOf(list)
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:14: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setFunction = mutableStateOf(mutableSetOf(1))
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:15: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setProperty = mutableStateOf(set)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:17: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapFunction = mutableStateOf(mutableMapOf(1 to 1))
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:18: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapProperty = mutableStateOf(map)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:20: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionProperty = mutableStateOf(collection)
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:28: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val listParameter = mutableStateOf(listParam)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:29: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val setParameter = mutableStateOf(setParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:30: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val mapParameter = mutableStateOf(mapParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:31: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val collectionProperty = mutableStateOf(collectionParam)
+                                             ~~~~~~~~~~~~~~
+0 errors, 11 warnings
+            """
+            )
+    }
+
+    @Test
+    fun mutableCollection_stdlib_explicitExpressionType_noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = mutableListOf(1)
+                val set = mutableSetOf(1)
+                val map = mutableMapOf(1 to 1)
+                val collection: MutableCollection<Int> = list
+
+                val listFunction = mutableStateOf<List<Int>>(mutableListOf(1))
+                val listProperty = mutableStateOf<List<Int>>(list)
+
+                val setFunction = mutableStateOf<Set<Int>>(mutableSetOf(1))
+                val setProperty = mutableStateOf<Set<Int>>(set)
+
+                val mapFunction = mutableStateOf<Map<Int, Int>>(mutableMapOf(1 to 1))
+                val mapProperty = mutableStateOf<Map<Int, Int>>(map)
+
+                val collectionProperty = mutableStateOf<Collection<Int>>(collection)
+
+                fun test(
+                    listParam: MutableList<Int>,
+                    setParam: MutableSet<Int>,
+                    mapParam: MutableMap<Int, Int>,
+                    collectionParam: MutableCollection<Int>
+                ) {
+                    val listParameter = mutableStateOf<List<Int>>(listParam)
+                    val setParameter = mutableStateOf<Set<Int>>(setParam)
+                    val mapParameter = mutableStateOf<Map<Int, Int>>(mapParam)
+                    val collectionProperty = mutableStateOf<Collection<Int>>(collectionParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun mutableCollection_stdlib_explicitPropertyType_noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = mutableListOf(1)
+                val set = mutableSetOf(1)
+                val map = mutableMapOf(1 to 1)
+                val collection: MutableCollection<Int> = list
+
+                val listFunction: MutableState<List<Int>> = mutableStateOf(mutableListOf(1))
+                val listProperty: MutableState<List<Int>> = mutableStateOf(list)
+
+                val setFunction: MutableState<Set<Int>> = mutableStateOf(mutableSetOf(1))
+                val setProperty: MutableState<Set<Int>> = mutableStateOf(set)
+
+                val mapFunction: MutableState<Map<Int, Int>> = mutableStateOf(mutableMapOf(1 to 1))
+                val mapProperty: MutableState<Map<Int, Int>> = mutableStateOf(map)
+
+                val collectionProperty: MutableState<Collection<Int>> = mutableStateOf(collection)
+
+                fun test(
+                    listParam: MutableList<Int>,
+                    setParam: MutableSet<Int>,
+                    mapParam: MutableMap<Int, Int>,
+                    collectionParam: MutableCollection<Int>
+                ) {
+                    val listParameter: MutableState<List<Int>> = mutableStateOf(listParam)
+                    val setParameter: MutableState<Set<Int>> = mutableStateOf(setParam)
+                    val mapParameter: MutableState<Map<Int, Int>> = mutableStateOf(mapParam)
+                    val collectionProperty: MutableState<Collection<Int>> = mutableStateOf(collectionParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun mutableCollection_java() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = java.util.ArrayList<Int>()
+                val set = java.util.HashSet<Int>()
+                val linkedSet = java.util.LinkedHashSet<Int>()
+                val map = java.util.HashMap<Int, Int>()
+                val linkedMap = java.util.LinkedHashMap<Int, Int>()
+                val collection: java.util.Collection<Int> = list as java.util.Collection<Int>
+
+                val listFunction = mutableStateOf(java.util.ArrayList<Int>())
+                val listProperty = mutableStateOf(list)
+
+                val setFunction = mutableStateOf(java.util.HashSet<Int>())
+                val setProperty = mutableStateOf(set)
+
+                val linkedSetFunction = mutableStateOf(java.util.LinkedHashSet<Int>())
+                val linkedSetProperty = mutableStateOf(linkedSet)
+
+                val mapFunction = mutableStateOf(java.util.HashMap<Int, Int>())
+                val mapProperty = mutableStateOf(map)
+
+                val linkedMapFunction = mutableStateOf(java.util.LinkedHashMap<Int, Int>())
+                val linkedMapProperty = mutableStateOf(linkedMap)
+
+                val collectionProperty = mutableStateOf(collection)
+
+                fun test(
+                    listParam: java.util.ArrayList<Int>,
+                    setParam: java.util.HashSet<Int>,
+                    linkedSetParam: java.util.LinkedHashSet<Int>,
+                    mapParam: java.util.HashMap<Int, Int>,
+                    linkedMapParam: java.util.LinkedHashMap<Int, Int>,
+                    collectionParam: java.util.Collection<Int>
+                ) {
+                    val listParameter = mutableStateOf(listParam)
+                    val setParameter = mutableStateOf(setParam)
+                    val linkedSetParameter = mutableStateOf(linkedSetParam)
+                    val mapParameter = mutableStateOf(mapParam)
+                    val linkedMapParameter = mutableStateOf(linkedMapParam)
+                    val collectionProperty = mutableStateOf(collectionParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expect(
+                """
+src/test/test.kt:13: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listFunction = mutableStateOf(java.util.ArrayList<Int>())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:14: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listProperty = mutableStateOf(list)
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:16: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setFunction = mutableStateOf(java.util.HashSet<Int>())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:17: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setProperty = mutableStateOf(set)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:19: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedSetFunction = mutableStateOf(java.util.LinkedHashSet<Int>())
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:20: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedSetProperty = mutableStateOf(linkedSet)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:22: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapFunction = mutableStateOf(java.util.HashMap<Int, Int>())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:23: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapProperty = mutableStateOf(map)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:25: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedMapFunction = mutableStateOf(java.util.LinkedHashMap<Int, Int>())
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:26: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedMapProperty = mutableStateOf(linkedMap)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:28: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionProperty = mutableStateOf(collection)
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:38: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val listParameter = mutableStateOf(listParam)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:39: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val setParameter = mutableStateOf(setParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:40: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val linkedSetParameter = mutableStateOf(linkedSetParam)
+                                             ~~~~~~~~~~~~~~
+src/test/test.kt:41: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val mapParameter = mutableStateOf(mapParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:42: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val linkedMapParameter = mutableStateOf(linkedMapParam)
+                                             ~~~~~~~~~~~~~~
+src/test/test.kt:43: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val collectionProperty = mutableStateOf(collectionParam)
+                                             ~~~~~~~~~~~~~~
+0 errors, 17 warnings
+            """
+            )
+    }
+
+    /**
+     * Tests for Kotlin collection types that are actually just aliases for the java classes on JVM
+     */
+    @Test
+    fun mutableCollection_kotlinTypeAliases() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = kotlin.collections.ArrayList<Int>()
+                val set = kotlin.collections.HashSet<Int>()
+                val linkedSet = kotlin.collections.LinkedHashSet<Int>()
+                val map = kotlin.collections.HashMap<Int, Int>()
+                val linkedMap = kotlin.collections.LinkedHashMap<Int, Int>()
+
+                val listFunction = mutableStateOf(kotlin.collections.ArrayList<Int>())
+                val listProperty = mutableStateOf(list)
+
+                val setFunction = mutableStateOf(kotlin.collections.HashSet<Int>())
+                val setProperty = mutableStateOf(set)
+
+                val linkedSetFunction = mutableStateOf(kotlin.collections.LinkedHashSet<Int>())
+                val linkedSetProperty = mutableStateOf(linkedSet)
+
+                val mapFunction = mutableStateOf(kotlin.collections.HashMap<Int, Int>())
+                val mapProperty = mutableStateOf(map)
+
+                val linkedMapFunction = mutableStateOf(kotlin.collections.LinkedHashMap<Int, Int>())
+                val linkedMapProperty = mutableStateOf(linkedMap)
+
+                fun test(
+                    listParam: kotlin.collections.ArrayList<Int>,
+                    setParam: kotlin.collections.HashSet<Int>,
+                    linkedSetParam: kotlin.collections.LinkedHashSet<Int>,
+                    mapParam: kotlin.collections.HashMap<Int, Int>,
+                    linkedMapParam: kotlin.collections.LinkedHashMap<Int, Int>,
+                ) {
+                    val listParameter = mutableStateOf(listParam)
+                    val setParameter = mutableStateOf(setParam)
+                    val linkedSetParameter = mutableStateOf(linkedSetParam)
+                    val mapParameter = mutableStateOf(mapParam)
+                    val linkedMapParameter = mutableStateOf(linkedMapParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expect(
+                """
+                    src/test/test.kt:12: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listFunction = mutableStateOf(kotlin.collections.ArrayList<Int>())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:13: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listProperty = mutableStateOf(list)
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:15: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setFunction = mutableStateOf(kotlin.collections.HashSet<Int>())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:16: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setProperty = mutableStateOf(set)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:18: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedSetFunction = mutableStateOf(kotlin.collections.LinkedHashSet<Int>())
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:19: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedSetProperty = mutableStateOf(linkedSet)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:21: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapFunction = mutableStateOf(kotlin.collections.HashMap<Int, Int>())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:22: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapProperty = mutableStateOf(map)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:24: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedMapFunction = mutableStateOf(kotlin.collections.LinkedHashMap<Int, Int>())
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:25: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val linkedMapProperty = mutableStateOf(linkedMap)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:34: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val listParameter = mutableStateOf(listParam)
+                                        ~~~~~~~~~~~~~~
+src/test/test.kt:35: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val setParameter = mutableStateOf(setParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:36: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val linkedSetParameter = mutableStateOf(linkedSetParam)
+                                             ~~~~~~~~~~~~~~
+src/test/test.kt:37: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val mapParameter = mutableStateOf(mapParam)
+                                       ~~~~~~~~~~~~~~
+src/test/test.kt:38: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                    val linkedMapParameter = mutableStateOf(linkedMapParam)
+                                             ~~~~~~~~~~~~~~
+0 errors, 15 warnings
+            """
+            )
+    }
+
+    @Test
+    fun mutableCollection_sourceExtensions() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+                import stubs.*
+
+                val listFunction = mutableStateOf(mutableList())
+                val listProperty = mutableStateOf(MutableList)
+                val listObjectImplementation = mutableStateOf(MutableListObject)
+                val listSubclass = mutableStateOf(MutableListSubclass())
+
+                val setFunction = mutableStateOf(mutableSet())
+                val setProperty = mutableStateOf(MutableSet)
+                val setObjectImplementation = mutableStateOf(MutableSetObject)
+                val setSubclass = mutableStateOf(MutableSetSubclass())
+
+                val mapFunction = mutableStateOf(mutableMap())
+                val mapProperty = mutableStateOf(MutableMap)
+                val mapObjectImplementation = mutableStateOf(MutableMapObject)
+                val mapSubclass = mutableStateOf(MutableMapSubclass())
+
+                val collectionFunction = mutableStateOf(mutableCollection())
+                val collectionProperty = mutableStateOf(MutableCollection)
+                val collectionObjectImplementation = mutableStateOf(MutableCollectionObject)
+                val collectionSubclass = mutableStateOf(MutableCollectionSubclass())
+            """
+            ),
+            Stubs.SnapshotState,
+            KotlinMutableCollectionExtensions.kotlin
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expect(
+                """
+                    src/test/test.kt:7: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listFunction = mutableStateOf(mutableList())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:8: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listProperty = mutableStateOf(MutableList)
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:9: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listObjectImplementation = mutableStateOf(MutableListObject)
+                                               ~~~~~~~~~~~~~~
+src/test/test.kt:10: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listSubclass = mutableStateOf(MutableListSubclass())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:12: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setFunction = mutableStateOf(mutableSet())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:13: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setProperty = mutableStateOf(MutableSet)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:14: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setObjectImplementation = mutableStateOf(MutableSetObject)
+                                              ~~~~~~~~~~~~~~
+src/test/test.kt:15: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setSubclass = mutableStateOf(MutableSetSubclass())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:17: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapFunction = mutableStateOf(mutableMap())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:18: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapProperty = mutableStateOf(MutableMap)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:19: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapObjectImplementation = mutableStateOf(MutableMapObject)
+                                              ~~~~~~~~~~~~~~
+src/test/test.kt:20: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapSubclass = mutableStateOf(MutableMapSubclass())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:22: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionFunction = mutableStateOf(mutableCollection())
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:23: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionProperty = mutableStateOf(MutableCollection)
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:24: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionObjectImplementation = mutableStateOf(MutableCollectionObject)
+                                                     ~~~~~~~~~~~~~~
+src/test/test.kt:25: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionSubclass = mutableStateOf(MutableCollectionSubclass())
+                                         ~~~~~~~~~~~~~~
+0 errors, 16 warnings
+            """
+            )
+    }
+
+    @Test
+    fun mutableCollection_compiledExtensions() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+                import stubs.*
+
+                val listFunction = mutableStateOf(mutableList())
+                val listProperty = mutableStateOf(MutableList)
+                val listObjectImplementation = mutableStateOf(MutableListObject)
+                val listSubclass = mutableStateOf(MutableListSubclass())
+
+                val setFunction = mutableStateOf(mutableSet())
+                val setProperty = mutableStateOf(MutableSet)
+                val setObjectImplementation = mutableStateOf(MutableSetObject)
+                val setSubclass = mutableStateOf(MutableSetSubclass())
+
+                val mapFunction = mutableStateOf(mutableMap())
+                val mapProperty = mutableStateOf(MutableMap)
+                val mapObjectImplementation = mutableStateOf(MutableMapObject)
+                val mapSubclass = mutableStateOf(MutableMapSubclass())
+
+                val collectionFunction = mutableStateOf(mutableCollection())
+                val collectionProperty = mutableStateOf(MutableCollection)
+                val collectionObjectImplementation = mutableStateOf(MutableCollectionObject)
+                val collectionSubclass = mutableStateOf(MutableCollectionSubclass())
+            """
+            ),
+            Stubs.SnapshotState,
+            Stubs.Composable,
+            KotlinMutableCollectionExtensions.compiled
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expect(
+                """
+                    src/test/test.kt:7: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listFunction = mutableStateOf(mutableList())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:8: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listProperty = mutableStateOf(MutableList)
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:9: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listObjectImplementation = mutableStateOf(MutableListObject)
+                                               ~~~~~~~~~~~~~~
+src/test/test.kt:10: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val listSubclass = mutableStateOf(MutableListSubclass())
+                                   ~~~~~~~~~~~~~~
+src/test/test.kt:12: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setFunction = mutableStateOf(mutableSet())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:13: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setProperty = mutableStateOf(MutableSet)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:14: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setObjectImplementation = mutableStateOf(MutableSetObject)
+                                              ~~~~~~~~~~~~~~
+src/test/test.kt:15: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val setSubclass = mutableStateOf(MutableSetSubclass())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:17: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapFunction = mutableStateOf(mutableMap())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:18: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapProperty = mutableStateOf(MutableMap)
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:19: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapObjectImplementation = mutableStateOf(MutableMapObject)
+                                              ~~~~~~~~~~~~~~
+src/test/test.kt:20: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val mapSubclass = mutableStateOf(MutableMapSubclass())
+                                  ~~~~~~~~~~~~~~
+src/test/test.kt:22: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionFunction = mutableStateOf(mutableCollection())
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:23: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionProperty = mutableStateOf(MutableCollection)
+                                         ~~~~~~~~~~~~~~
+src/test/test.kt:24: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionObjectImplementation = mutableStateOf(MutableCollectionObject)
+                                                     ~~~~~~~~~~~~~~
+src/test/test.kt:25: Warning: Creating a MutableState object with a mutable collection type [MutableCollectionMutableState]
+                val collectionSubclass = mutableStateOf(MutableCollectionSubclass())
+                                         ~~~~~~~~~~~~~~
+0 errors, 16 warnings
+            """
+            )
+    }
+
+    @Test
+    fun immutableCollection_stdlib_noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+
+                val list = listOf(1)
+                val set = setOf(1)
+                val map = mapOf(1 to 1)
+                val collection: Collection<Int> = list
+
+                val listFunction = mutableStateOf(listOf(1))
+                val listProperty = mutableStateOf(list)
+
+                val setFunction = mutableStateOf(setOf(1))
+                val setProperty = mutableStateOf(set)
+
+                val mapFunction = mutableStateOf(mapOf(1 to 1))
+                val mapProperty = mutableStateOf(map)
+
+                val collectionProperty = mutableStateOf(collection)
+
+                fun test(
+                    listParam: List<Int>,
+                    setParam: Set<Int>,
+                    mapParam: Map<Int, Int>,
+                    collectionParam: Collection<Int>
+                ) {
+                    val listParameter = mutableStateOf(listParam)
+                    val setParameter = mutableStateOf(setParam)
+                    val mapParameter = mutableStateOf(mapParam)
+                    val collectionProperty = mutableStateOf(collectionParam)
+                }
+            """
+            ),
+            Stubs.SnapshotState
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun immutableCollection_sourceExtensions_noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+                import stubs.*
+
+                val listFunction = mutableStateOf(list())
+                val listProperty = mutableStateOf(List)
+                val listObjectImplementation = mutableStateOf(ListObject)
+                val listSubclass = mutableStateOf(ListSubclass())
+
+                val setFunction = mutableStateOf(set())
+                val setProperty = mutableStateOf(Set)
+                val setObjectImplementation = mutableStateOf(SetObject)
+                val setSubclass = mutableStateOf(SetSubclass())
+
+                val mapFunction = mutableStateOf(map())
+                val mapProperty = mutableStateOf(Map)
+                val mapObjectImplementation = mutableStateOf(MapObject)
+                val mapSubclass = mutableStateOf(MapSubclass())
+
+                val collectionFunction = mutableStateOf(collection())
+                val collectionProperty = mutableStateOf(Collection)
+                val collectionObjectImplementation = mutableStateOf(CollectionObject)
+                val collectionSubclass = mutableStateOf(CollectionSubclass())
+            """
+            ),
+            Stubs.SnapshotState,
+            KotlinImmutableCollectionExtensions.kotlin
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun immutableCollection_compiledExtensions_noErrors() {
+        lint().files(
+            kotlin(
+                """
+                package test
+
+                import androidx.compose.runtime.*
+                import stubs.*
+
+                val listFunction = mutableStateOf(list())
+                val listProperty = mutableStateOf(List)
+                val listObjectImplementation = mutableStateOf(ListObject)
+                val listSubclass = mutableStateOf(ListSubclass())
+
+                val setFunction = mutableStateOf(set())
+                val setProperty = mutableStateOf(Set)
+                val setObjectImplementation = mutableStateOf(SetObject)
+                val setSubclass = mutableStateOf(SetSubclass())
+
+                val mapFunction = mutableStateOf(map())
+                val mapProperty = mutableStateOf(Map)
+                val mapObjectImplementation = mutableStateOf(MapObject)
+                val mapSubclass = mutableStateOf(MapSubclass())
+
+                val collectionFunction = mutableStateOf(collection())
+                val collectionProperty = mutableStateOf(Collection)
+                val collectionObjectImplementation = mutableStateOf(CollectionObject)
+                val collectionSubclass = mutableStateOf(CollectionSubclass())
+            """
+            ),
+            Stubs.SnapshotState,
+            Stubs.Composable,
+            KotlinImmutableCollectionExtensions.compiled
+        )
+            .skipTestModes(TestMode.TYPE_ALIAS)
+            .run()
+            .expectClean()
+    }
+}
+/* ktlint-enable max-line-length */
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/ListUtils.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/ListUtils.kt
index 2e6554c..cb0552e 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/ListUtils.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/ListUtils.kt
@@ -22,6 +22,10 @@
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEach].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
@@ -36,6 +40,10 @@
  * Returns a [Set] of all elements.
  *
  * The returned set preserves the element iteration order of the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 internal fun <T> List<T>.fastToSet(): Set<T> = HashSet<T>(size).also { set ->
     fastForEach { item -> set.add(item) }
@@ -44,6 +52,10 @@
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEachIndexed].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastForEachIndexed(action: (Int, T) -> Unit) {
@@ -57,6 +69,10 @@
 /**
  * Returns a list containing the results of applying the given [transform] function
  * to each element in the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastMap(transform: (T) -> R): List<R> {
@@ -75,6 +91,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which case
  * only the first [limit] elements will be appended, followed by the [truncated] string (which
  * defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 internal fun <T> List<T>.fastJoinToString(
     separator: CharSequence = ", ",
@@ -95,6 +115,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which
  * case only the first [limit] elements will be appended, followed by the [truncated] string
  * (which defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 private fun <T, A : Appendable> List<T>.fastJoinTo(
     buffer: A,
@@ -134,6 +158,10 @@
 /**
  * Returns a list containing the results of applying the given [transform] function
  * to each element in the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastMapNotNull(transform: (T) -> R?): List<R> {
@@ -149,6 +177,10 @@
  * Returns a list containing only elements matching the given [predicate].
  * @param [predicate] function that takes the index of an element and the element itself
  * and returns the result of predicate evaluation on the element.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastFilterIndexed(predicate: (index: Int, T) -> Boolean): List<T> {
diff --git a/compose/test-utils/OWNERS b/compose/test-utils/OWNERS
index 305021a..b2c0d56 100644
--- a/compose/test-utils/OWNERS
+++ b/compose/test-utils/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 jellefresen@google.com
diff --git a/compose/ui/ui-inspection/src/androidTest/AndroidManifest.xml b/compose/ui/ui-inspection/src/androidTest/AndroidManifest.xml
index bc217cf..48da372 100644
--- a/compose/ui/ui-inspection/src/androidTest/AndroidManifest.xml
+++ b/compose/ui/ui-inspection/src/androidTest/AndroidManifest.xml
@@ -17,6 +17,7 @@
 
     <application>
         <activity android:name="androidx.compose.ui.inspection.testdata.AndroidViewTestActivity" />
+        <activity android:name="androidx.compose.ui.inspection.testdata.ComposeViewTestActivity" />
         <activity android:name="androidx.compose.ui.inspection.testdata.DialogTestActivity" />
         <activity android:name="androidx.compose.ui.inspection.testdata.ParametersTestActivity" />
         <activity android:name="androidx.compose.ui.inspection.testdata.RippleTestActivity" />
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/ComposeViewTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/ComposeViewTest.kt
new file mode 100644
index 0000000..9f6366a
--- /dev/null
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/ComposeViewTest.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.inspection
+
+import androidx.compose.ui.inspection.rules.ComposeInspectionRule
+import androidx.compose.ui.inspection.rules.sendCommand
+import androidx.compose.ui.inspection.testdata.ComposeViewTestActivity
+import androidx.compose.ui.inspection.util.GetComposablesCommand
+import androidx.compose.ui.inspection.util.GetParametersCommand
+import androidx.compose.ui.inspection.util.flatten
+import androidx.compose.ui.inspection.util.toMap
+import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.ComposableNode
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+class ComposeViewTest {
+    @get:Rule
+    val rule = ComposeInspectionRule(ComposeViewTestActivity::class)
+
+    @Test
+    fun composeView(): Unit = runBlocking {
+        val response = rule.inspectorTester.sendCommand(
+            GetComposablesCommand(rule.rootId, skipSystemComposables = false)
+        ).getComposablesResponse
+        val strings = response.stringsList.toMap()
+        val roots = response.rootsList
+        assertThat(roots).hasSize(3)
+        val firstText = roots[0].nodesList.findNode("Text", strings)
+        val secondText = roots[1].nodesList.findNode("Text", strings)
+        val thirdText = roots[2].nodesList.findNode("Text", strings)
+        assertThat(firstText?.textParameter).isEqualTo("one")
+        assertThat(secondText?.textParameter).isEqualTo("two")
+        assertThat(thirdText?.textParameter).isEqualTo("three")
+    }
+
+    private fun Iterable<ComposableNode>.findNode(
+        name: String,
+        strings: Map<Int, String>
+    ): ComposableNode? = flatMap { it.flatten() }.singleOrNull { strings[it.name] == name }
+
+    private val ComposableNode.textParameter: String?
+        get() = runBlocking {
+            val params = rule.inspectorTester.sendCommand(
+                GetParametersCommand(
+                    rule.rootId,
+                    skipSystemComposables = false,
+                    composableId = id
+                )
+            ).getParametersResponse
+            val strings = params.stringsList.toMap()
+            val param = params.parameterGroup.parameterList.single { strings[it.name] == "text" }
+            strings[param.int32Value]
+        }
+}
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/testdata/ComposeViewTestActivity.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/testdata/ComposeViewTestActivity.kt
new file mode 100644
index 0000000..3c36a5a
--- /dev/null
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/testdata/ComposeViewTestActivity.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.inspection.testdata
+
+import android.os.Bundle
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Column
+import androidx.compose.material.Text
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.viewinterop.AndroidView
+
+class ComposeViewTestActivity : ComponentActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContent {
+            Column {
+                Text("one")
+                AndroidView({ context ->
+                    LinearLayout(context).apply {
+                        orientation = LinearLayout.VERTICAL
+                        addView(TextView(context).apply { text = "AndroidView" })
+                        addView(ComposeView(context).apply {
+                            setContent {
+                                Column {
+                                    Text("two")
+                                    AndroidView({ context ->
+                                        LinearLayout(context).apply {
+                                            orientation = LinearLayout.VERTICAL
+                                            addView(ComposeView(context).apply {
+                                                setContent {
+                                                    Text("three")
+                                                }
+                                            })
+                                        }
+                                    })
+                                }
+                            }
+                        })
+                    }
+                })
+            }
+        }
+    }
+}
diff --git a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt
index 6999d46..af7dab6 100644
--- a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt
+++ b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt
@@ -27,7 +27,7 @@
 import androidx.compose.ui.inspection.inspector.NodeParameterReference
 import androidx.compose.ui.inspection.proto.StringTable
 import androidx.compose.ui.inspection.proto.convert
-import androidx.compose.ui.inspection.proto.toComposableNodes
+import androidx.compose.ui.inspection.proto.toComposableRoot
 import androidx.compose.ui.inspection.util.ThreadUtils
 import androidx.compose.ui.unit.IntOffset
 import androidx.inspection.Connection
@@ -37,7 +37,6 @@
 import com.google.protobuf.ByteString
 import com.google.protobuf.InvalidProtocolBufferException
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.Command
-import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.ComposableRoot
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.GetAllParametersCommand
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.GetAllParametersResponse
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.GetComposablesCommand
@@ -66,19 +65,31 @@
 
 class ComposeLayoutInspector(
     connection: Connection,
+    @Suppress("unused")
     private val environment: InspectorEnvironment
 ) : Inspector(connection) {
 
     /** Cache data which allows us to reuse previously queried inspector nodes */
     private class CacheData(
         val rootView: View,
+        val trees: List<CacheTree>
+    ) {
+        /** The cached nodes as a map from node id to InspectorNode */
+        val lookup: Map<Long, InspectorNode>
+            get() = _lookup ?: trees.flatMap { it.nodes }
+                .flatMap { it.flatten() }
+                .associateBy { it.id }
+                .also { _lookup = it }
+
+        private var _lookup: Map<Long, InspectorNode>? = null
+    }
+
+    /** Cache data for a tree of [InspectorNode]s under a [viewParent] */
+    internal class CacheTree(
         val viewParent: View,
         val nodes: List<InspectorNode>,
         val viewsToSkip: List<Long>
-    ) {
-        /** The cached nodes as a map from node id to InspectorNode */
-        val lookup = nodes.flatMap { it.flatten() }.associateBy { it.id }
-    }
+    )
 
     private val layoutInspectorTree = LayoutInspectorTree()
 
@@ -142,21 +153,13 @@
         val windowPos = IntOffset(location[0], location[1])
 
         val stringTable = StringTable()
-        val nodes = data?.nodes ?: emptyList()
-        val composeNodes = nodes.toComposableNodes(stringTable, windowPos)
+        val trees = data?.trees ?: emptyList()
+        val roots = trees.map { it.toComposableRoot(stringTable, windowPos) }
 
         callback.reply {
             getComposablesResponse = GetComposablesResponse.newBuilder().apply {
                 addAllStrings(stringTable.toStringEntries())
-                addRoots(
-                    ComposableRoot.newBuilder().apply {
-                        if (data != null) {
-                            viewId = data.viewParent.uniqueDrawingId
-                            addAllNodes(composeNodes)
-                            addAllViewsToSkip(data.viewsToSkip)
-                        }
-                    }
-                )
+                addAllRoots(roots)
             }.build()
         }
     }
@@ -284,15 +287,20 @@
 
         val data = ThreadUtils.runOnMainThread {
             layoutInspectorTree.resetAccumulativeState()
-            val data = getAndroidComposeViews(rootViewId, skipSystemComposables, generation).map {
-                CacheData(it.rootView, it.viewParent, it.createNodes(), it.viewsToSkip)
+            val composeViews = getAndroidComposeViews(rootViewId, skipSystemComposables, generation)
+            val composeViewsByRoot = composeViews.groupBy { it.rootView.uniqueDrawingId }
+            val data = composeViewsByRoot.mapValues { (_, composeViews) ->
+                CacheData(
+                    composeViews.first().rootView,
+                    composeViews.map { CacheTree(it.viewParent, it.createNodes(), it.viewsToSkip) }
+                )
             }
             layoutInspectorTree.resetAccumulativeState()
             data
         }.get()
 
         cachedNodes.clear()
-        data.associateByTo(cachedNodes) { it.rootView.uniqueDrawingId }
+        cachedNodes.putAll(data)
         cachedGeneration = generation
         cachedSystemComposablesSkipped = skipSystemComposables
         return cachedNodes[rootViewId]
diff --git a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/proto/ComposeExtensions.kt b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/proto/ComposeExtensions.kt
index fa17f3c..3526f27 100644
--- a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/proto/ComposeExtensions.kt
+++ b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/proto/ComposeExtensions.kt
@@ -18,6 +18,7 @@
 
 import android.view.inspector.WindowInspector
 import androidx.annotation.VisibleForTesting
+import androidx.compose.ui.inspection.ComposeLayoutInspector.CacheTree
 import androidx.compose.ui.inspection.LambdaLocation
 import androidx.compose.ui.inspection.inspector.InspectorNode
 import androidx.compose.ui.inspection.inspector.NodeParameter
@@ -28,6 +29,7 @@
 import androidx.compose.ui.unit.IntOffset
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.Bounds
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.ComposableNode
+import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.ComposableRoot
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.LambdaValue
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.Parameter
 import layoutinspector.compose.inspection.LayoutInspectorComposeProtocol.ParameterReference
@@ -233,12 +235,14 @@
     }.build()
 }
 
-fun Iterable<InspectorNode>.toComposableNodes(
+internal fun CacheTree.toComposableRoot(
     stringTable: StringTable,
     windowPos: IntOffset
-): List<ComposableNode> {
-    return this.map { it.toComposableNode(stringTable, windowPos) }
-}
+): ComposableRoot = ComposableRoot.newBuilder().also { root ->
+    root.viewId = viewParent.uniqueDrawingId
+    root.addAllNodes(nodes.map { it.toComposableNode(stringTable, windowPos) })
+    root.addAllViewsToSkip(viewsToSkip)
+}.build()
 
 fun Iterable<NodeParameter>.convertAll(stringTable: StringTable): List<Parameter> {
     return this.map { it.convert(stringTable) }
diff --git a/compose/ui/ui-test-junit4/OWNERS b/compose/ui/ui-test-junit4/OWNERS
index 305021a..b2c0d56 100644
--- a/compose/ui/ui-test-junit4/OWNERS
+++ b/compose/ui/ui-test-junit4/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 jellefresen@google.com
diff --git a/compose/ui/ui-test-junit4/api/1.1.0-beta04.txt b/compose/ui/ui-test-junit4/api/1.1.0-beta04.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/1.1.0-beta04.txt
+++ b/compose/ui/ui-test-junit4/api/1.1.0-beta04.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/api/current.ignore b/compose/ui/ui-test-junit4/api/current.ignore
index 6e4d61f..a21b2a6 100644
--- a/compose/ui/ui-test-junit4/api/current.ignore
+++ b/compose/ui/ui-test-junit4/api/current.ignore
@@ -1,7 +1,3 @@
 // Baseline format: 1.0
-RemovedClass: androidx.compose.ui.test.junit4.android.ComposeIdlingResource_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.ComposeIdlingResource_androidKt
-RemovedClass: androidx.compose.ui.test.junit4.android.ComposeRootRegistry_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.ComposeRootRegistry_androidKt
-RemovedClass: androidx.compose.ui.test.junit4.android.EspressoLink_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.EspressoLink_androidKt
+ChangedSuperclass: androidx.compose.ui.test.junit4.android.ComposeNotIdleException:
+    Class androidx.compose.ui.test.junit4.android.ComposeNotIdleException superclass changed from java.lang.Throwable to java.lang.Exception
diff --git a/compose/ui/ui-test-junit4/api/current.txt b/compose/ui/ui-test-junit4/api/current.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/current.txt
+++ b/compose/ui/ui-test-junit4/api/current.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/api/public_plus_experimental_1.1.0-beta04.txt b/compose/ui/ui-test-junit4/api/public_plus_experimental_1.1.0-beta04.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/public_plus_experimental_1.1.0-beta04.txt
+++ b/compose/ui/ui-test-junit4/api/public_plus_experimental_1.1.0-beta04.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt b/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/api/restricted_1.1.0-beta04.txt b/compose/ui/ui-test-junit4/api/restricted_1.1.0-beta04.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/restricted_1.1.0-beta04.txt
+++ b/compose/ui/ui-test-junit4/api/restricted_1.1.0-beta04.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/api/restricted_current.ignore b/compose/ui/ui-test-junit4/api/restricted_current.ignore
index 6e4d61f..a21b2a6 100644
--- a/compose/ui/ui-test-junit4/api/restricted_current.ignore
+++ b/compose/ui/ui-test-junit4/api/restricted_current.ignore
@@ -1,7 +1,3 @@
 // Baseline format: 1.0
-RemovedClass: androidx.compose.ui.test.junit4.android.ComposeIdlingResource_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.ComposeIdlingResource_androidKt
-RemovedClass: androidx.compose.ui.test.junit4.android.ComposeRootRegistry_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.ComposeRootRegistry_androidKt
-RemovedClass: androidx.compose.ui.test.junit4.android.EspressoLink_androidKt:
-    Removed class androidx.compose.ui.test.junit4.android.EspressoLink_androidKt
+ChangedSuperclass: androidx.compose.ui.test.junit4.android.ComposeNotIdleException:
+    Class androidx.compose.ui.test.junit4.android.ComposeNotIdleException superclass changed from java.lang.Throwable to java.lang.Exception
diff --git a/compose/ui/ui-test-junit4/api/restricted_current.txt b/compose/ui/ui-test-junit4/api/restricted_current.txt
index a71c843..56b11a6 100644
--- a/compose/ui/ui-test-junit4/api/restricted_current.txt
+++ b/compose/ui/ui-test-junit4/api/restricted_current.txt
@@ -76,7 +76,7 @@
 
 package androidx.compose.ui.test.junit4.android {
 
-  public final class ComposeNotIdleException extends java.lang.Throwable {
+  public final class ComposeNotIdleException extends java.lang.Exception {
     ctor public ComposeNotIdleException(String? message, Throwable? cause);
   }
 
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeNotIdleException.android.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeNotIdleException.android.kt
index bd68df1..815c8d6 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeNotIdleException.android.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeNotIdleException.android.kt
@@ -19,4 +19,4 @@
 /**
  * Thrown in cases where Compose can't get idle in Espresso's defined time limit.
  */
-class ComposeNotIdleException(message: String?, cause: Throwable?) : Throwable(message, cause)
+class ComposeNotIdleException(message: String?, cause: Throwable?) : Exception(message, cause)
diff --git a/compose/ui/ui-test-manifest/OWNERS b/compose/ui/ui-test-manifest/OWNERS
index 42abc4e..b2c0d56 100644
--- a/compose/ui/ui-test-manifest/OWNERS
+++ b/compose/ui/ui-test-manifest/OWNERS
@@ -1,2 +1 @@
 jellefresen@google.com
-pavlis@google.com
diff --git a/compose/ui/ui-test-manifest/integration-tests/testapp/OWNERS b/compose/ui/ui-test-manifest/integration-tests/testapp/OWNERS
index 42abc4e..b2c0d56 100644
--- a/compose/ui/ui-test-manifest/integration-tests/testapp/OWNERS
+++ b/compose/ui/ui-test-manifest/integration-tests/testapp/OWNERS
@@ -1,2 +1 @@
 jellefresen@google.com
-pavlis@google.com
diff --git a/compose/ui/ui-test/OWNERS b/compose/ui/ui-test/OWNERS
index 305021a..b2c0d56 100644
--- a/compose/ui/ui-test/OWNERS
+++ b/compose/ui/ui-test/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 jellefresen@google.com
diff --git a/compose/ui/ui-text/OWNERS b/compose/ui/ui-text/OWNERS
index f00bb31..9a0b796 100644
--- a/compose/ui/ui-text/OWNERS
+++ b/compose/ui/ui-text/OWNERS
@@ -1,6 +1,5 @@
 include /TEXT_OWNERS
 
-pavlis@google.com
 adamp@google.com
 mount@google.com
 popam@google.com
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TempListUtils.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TempListUtils.kt
index 79b7c59..b86d941 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TempListUtils.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/TempListUtils.kt
@@ -24,6 +24,10 @@
 
 /**
  * Returns a list containing only elements matching the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastFilter(predicate: (T) -> Boolean): List<T> {
@@ -40,6 +44,10 @@
  * having distinct keys returned by the given [selector] function.
  *
  * The elements in the resulting list are in the same order as they were in the source collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, K> List<T>.fastDistinctBy(selector: (T) -> K): List<T> {
@@ -56,6 +64,10 @@
 /**
  * Returns the first element yielding the largest value of the given function or `null` if there
  * are no elements.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R : Comparable<R>> List<T>.fastMinByOrNull(selector: (T) -> R): T? {
@@ -80,7 +92,12 @@
  *
  * Returns the specified [initial] value if the collection is empty.
  *
- * @param [operation] function that takes current accumulator value and an element, and calculates the next accumulator value.
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
+ *
+ * @param [operation] function that takes current accumulator value and an element, and calculates
+ * the next accumulator value.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastFold(initial: R, operation: (acc: R, T) -> R): R {
@@ -95,6 +112,10 @@
 /**
  * Returns a single list of all elements yielded from results of [transform] function being invoked
  * on each element of original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastFlatMap(transform: (T) -> Iterable<R>): List<R> {
@@ -109,6 +130,10 @@
 
 /**
  * Returns a list containing all elements not matching the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastFilterNot(predicate: (T) -> Boolean): List<T> {
@@ -122,6 +147,10 @@
 
 /**
  * Returns a list containing the first elements satisfying the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastTakeWhile(predicate: (T) -> Boolean): List<T> {
@@ -139,6 +168,10 @@
 /**
  * Returns a list containing all elements except first [n] elements.
  *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
+ *
  * @throws IllegalArgumentException if [n] is negative.
  */
 internal fun <T> List<T>.fastDrop(n: Int): List<T> {
@@ -167,6 +200,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which case
  * only the first [limit] elements will be appended, followed by the [truncated] string (which
  * defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 internal fun <T> List<T>.fastJoinToString(
     separator: CharSequence = ", ",
@@ -187,6 +224,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which
  * case only the first [limit] elements will be appended, followed by the [truncated] string
  * (which defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 private fun <T, A : Appendable> List<T>.fastJoinTo(
     buffer: A,
diff --git a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
index f52e504..863a04a 100644
--- a/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
+++ b/compose/ui/ui-tooling/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/ComposeViewAdapterTest.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.tooling
 
 import android.app.Activity
+import android.os.Build
 import android.os.Bundle
 import androidx.compose.animation.core.InternalAnimationApi
 import androidx.compose.ui.tooling.animation.PreviewAnimationClock
@@ -336,10 +337,14 @@
                 onDraw = { onDrawCounter++ }
             )
         }
+
+        // API before 22, might issue an additional draw under testing.
+        val expectedDrawCount = if (Build.VERSION.SDK_INT < 22) 2 else 1
         repeat(5) {
             activityTestRule.runOnUiThread {
                 assertEquals(1, compositionCount.get())
-                assertTrue("At most, 1 draw is expected", onDrawCounter < 2)
+                assertTrue("At most, $expectedDrawCount draw is expected ($onDrawCounter happened)",
+                    onDrawCounter <= expectedDrawCount)
             }
             Thread.sleep(250)
         }
diff --git a/compose/ui/ui-util/src/commonMain/kotlin/androidx/compose/ui/util/ListUtils.kt b/compose/ui/ui-util/src/commonMain/kotlin/androidx/compose/ui/util/ListUtils.kt
index bf2f53d..bfa9798 100644
--- a/compose/ui/ui-util/src/commonMain/kotlin/androidx/compose/ui/util/ListUtils.kt
+++ b/compose/ui/ui-util/src/commonMain/kotlin/androidx/compose/ui/util/ListUtils.kt
@@ -22,6 +22,10 @@
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEach].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
@@ -35,6 +39,10 @@
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEachIndexed].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastForEachIndexed(action: (Int, T) -> Unit) {
@@ -47,6 +55,10 @@
 
 /**
  * Returns `true` if all elements match the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastAll(predicate: (T) -> Boolean): Boolean {
@@ -57,6 +69,10 @@
 
 /**
  * Returns `true` if at least one element matches the given [predicate].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastAny(predicate: (T) -> Boolean): Boolean {
@@ -67,6 +83,10 @@
 
 /**
  * Returns the first value that [predicate] returns `true` for or `null` if nothing matches.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastFirstOrNull(predicate: (T) -> Boolean): T? {
@@ -78,6 +98,10 @@
 /**
  * Returns the sum of all values produced by [selector] function applied to each element in the
  * list.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T> List<T>.fastSumBy(selector: (T) -> Int): Int {
@@ -92,6 +116,10 @@
 /**
  * Returns a list containing the results of applying the given [transform] function
  * to each element in the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T, R> List<T>.fastMap(transform: (T) -> R): List<R> {
@@ -107,6 +135,10 @@
 /**
  * Returns the first element yielding the largest value of the given function or `null` if there
  * are no elements.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T, R : Comparable<R>> List<T>.fastMaxBy(selector: (T) -> R): T? {
@@ -128,6 +160,10 @@
 /**
  * Applies the given [transform] function to each element of the original collection
  * and appends the results to the given [destination].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 inline fun <T, R, C : MutableCollection<in R>> List<T>.fastMapTo(
diff --git a/compose/ui/ui/api/public_plus_experimental_1.1.0-beta04.txt b/compose/ui/ui/api/public_plus_experimental_1.1.0-beta04.txt
index b293eee..eced941 100644
--- a/compose/ui/ui/api/public_plus_experimental_1.1.0-beta04.txt
+++ b/compose/ui/ui/api/public_plus_experimental_1.1.0-beta04.txt
@@ -1607,12 +1607,14 @@
     method public int getMove();
     method public int getPress();
     method public int getRelease();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public int getScroll();
     method public int getUnknown();
     property public final int Enter;
     property public final int Exit;
     property public final int Move;
     property public final int Press;
     property public final int Release;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final int Scroll;
     property public final int Unknown;
   }
 
@@ -1670,7 +1672,7 @@
 
   @androidx.compose.runtime.Immutable public final class PointerInputChange {
     ctor public PointerInputChange(long id, long uptimeMillis, long position, boolean pressed, long previousUptimeMillis, long previousPosition, boolean previousPressed, androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type);
-    ctor @androidx.compose.ui.ExperimentalComposeUiApi public PointerInputChange(long id, long uptimeMillis, long position, boolean pressed, long previousUptimeMillis, long previousPosition, boolean previousPressed, androidx.compose.ui.input.pointer.ConsumedData consumed, int type, java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical);
+    method @androidx.compose.ui.ExperimentalComposeUiApi public void consume();
     method public androidx.compose.ui.input.pointer.PointerInputChange copy(optional long id, optional long currentTime, optional long currentPosition, optional boolean currentPressed, optional long previousTime, optional long previousPosition, optional boolean previousPressed, optional androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type);
     method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.input.pointer.PointerInputChange copy(optional long id, optional long currentTime, optional long currentPosition, optional boolean currentPressed, optional long previousTime, optional long previousPosition, optional boolean previousPressed, optional androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type, java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical);
     method public androidx.compose.ui.input.pointer.ConsumedData getConsumed();
@@ -1681,16 +1683,20 @@
     method public long getPreviousPosition();
     method public boolean getPreviousPressed();
     method public long getPreviousUptimeMillis();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public long getScrollDelta();
     method public int getType();
     method public long getUptimeMillis();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public boolean isConsumed();
     property public final androidx.compose.ui.input.pointer.ConsumedData consumed;
     property @androidx.compose.ui.ExperimentalComposeUiApi public final java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical;
     property public final long id;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final boolean isConsumed;
     property public final long position;
     property public final boolean pressed;
     property public final long previousPosition;
     property public final boolean previousPressed;
     property public final long previousUptimeMillis;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final long scrollDelta;
     property public final int type;
     property public final long uptimeMillis;
   }
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index b293eee..eced941 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -1607,12 +1607,14 @@
     method public int getMove();
     method public int getPress();
     method public int getRelease();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public int getScroll();
     method public int getUnknown();
     property public final int Enter;
     property public final int Exit;
     property public final int Move;
     property public final int Press;
     property public final int Release;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final int Scroll;
     property public final int Unknown;
   }
 
@@ -1670,7 +1672,7 @@
 
   @androidx.compose.runtime.Immutable public final class PointerInputChange {
     ctor public PointerInputChange(long id, long uptimeMillis, long position, boolean pressed, long previousUptimeMillis, long previousPosition, boolean previousPressed, androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type);
-    ctor @androidx.compose.ui.ExperimentalComposeUiApi public PointerInputChange(long id, long uptimeMillis, long position, boolean pressed, long previousUptimeMillis, long previousPosition, boolean previousPressed, androidx.compose.ui.input.pointer.ConsumedData consumed, int type, java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical);
+    method @androidx.compose.ui.ExperimentalComposeUiApi public void consume();
     method public androidx.compose.ui.input.pointer.PointerInputChange copy(optional long id, optional long currentTime, optional long currentPosition, optional boolean currentPressed, optional long previousTime, optional long previousPosition, optional boolean previousPressed, optional androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type);
     method @androidx.compose.ui.ExperimentalComposeUiApi public androidx.compose.ui.input.pointer.PointerInputChange copy(optional long id, optional long currentTime, optional long currentPosition, optional boolean currentPressed, optional long previousTime, optional long previousPosition, optional boolean previousPressed, optional androidx.compose.ui.input.pointer.ConsumedData consumed, optional int type, java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical);
     method public androidx.compose.ui.input.pointer.ConsumedData getConsumed();
@@ -1681,16 +1683,20 @@
     method public long getPreviousPosition();
     method public boolean getPreviousPressed();
     method public long getPreviousUptimeMillis();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public long getScrollDelta();
     method public int getType();
     method public long getUptimeMillis();
+    method @androidx.compose.ui.ExperimentalComposeUiApi public boolean isConsumed();
     property public final androidx.compose.ui.input.pointer.ConsumedData consumed;
     property @androidx.compose.ui.ExperimentalComposeUiApi public final java.util.List<androidx.compose.ui.input.pointer.HistoricalChange> historical;
     property public final long id;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final boolean isConsumed;
     property public final long position;
     property public final boolean pressed;
     property public final long previousPosition;
     property public final boolean previousPressed;
     property public final long previousUptimeMillis;
+    property @androidx.compose.ui.ExperimentalComposeUiApi public final long scrollDelta;
     property public final int type;
     property public final long uptimeMillis;
   }
diff --git a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/LayoutNodeModifierBenchmark.kt b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/LayoutNodeModifierBenchmark.kt
index e93fc61..f462daa 100644
--- a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/LayoutNodeModifierBenchmark.kt
+++ b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/LayoutNodeModifierBenchmark.kt
@@ -121,6 +121,41 @@
         }
     }
 
+    @Test
+    fun setDrawModifiersToSameValue() {
+        modifiers = mutableListOf<Modifier>().apply {
+            repeat(numberOfModifiers) {
+                this += Modifier.drawBehind { }
+            }
+        }
+        combinedModifier = modifiers.fold<Modifier, Modifier>(Modifier) { acc, modifier ->
+            acc.then(modifier)
+        }
+
+        val altModifier = mutableListOf<Modifier>().apply {
+            repeat(numberOfModifiers) {
+                this += Modifier.drawBehind { }
+            }
+        }.fold<Modifier, Modifier>(Modifier) { acc, modifier ->
+            acc.then(modifier)
+        }
+
+        rule.activityTestRule.runOnUiThread {
+            rule.activityTestRule.activity.setContent {
+                TestModifierUpdaterLayout {
+                    testModifierUpdater = it
+                }
+            }
+        }
+
+        rule.activityTestRule.runOnUiThread {
+            rule.benchmarkRule.measureRepeated {
+                testModifierUpdater.updateModifier(combinedModifier)
+                testModifierUpdater.updateModifier(altModifier)
+            }
+        }
+    }
+
     class SimpleAndroidBenchmarkRule() : TestRule {
         @Suppress("DEPRECATION")
         val activityTestRule =
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index e1712fe..1e133f1 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -70,7 +70,7 @@
         testImplementation(libs.truth)
         testImplementation(libs.mockitoCore)
         testImplementation(libs.mockitoKotlin)
-        testImplementation(libs.robolectric)
+        testImplementation("org.robolectric:robolectric:4.6.1") // TODO(b/205731854): fix tests to work with SDK 31 and robolectric 4.7
         testImplementation(project(":compose:ui:ui-test-junit4"))
         testImplementation(project(":compose:test-utils"))
 
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/EventTypesDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/EventTypesDemo.kt
index 36b1565..29478d5 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/EventTypesDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/gestures/EventTypesDemo.kt
@@ -22,7 +22,6 @@
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
 import androidx.compose.material.Text
@@ -30,8 +29,10 @@
 import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clipToBounds
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.input.pointer.PointerEvent
 import androidx.compose.ui.input.pointer.PointerEventType
@@ -50,10 +51,10 @@
 }
 
 @Composable
-private fun DrawEvents(events: List<PointerEventType>, counts: List<Int>) {
+@OptIn(ExperimentalComposeUiApi::class)
+private fun DrawEvents(events: List<Pair<PointerEventType, Any>>) {
     for (i in events.lastIndex downTo 0) {
-        val type = events[i]
-        val count = counts[i]
+        val (type, value) = events[i]
 
         val color = when (type) {
             PointerEventType.Press -> Color.Red
@@ -61,9 +62,10 @@
             PointerEventType.Release -> Color.Yellow
             PointerEventType.Enter -> Color.Green
             PointerEventType.Exit -> Color.Blue
-            else -> Color(0xFF800080) // Purple
+            PointerEventType.Scroll -> Color(0xFF800080) // Purple
+            else -> Color.Black
         }
-        TextItem("$type $count", color)
+        TextItem("$type $value", color)
     }
 }
 
@@ -72,59 +74,62 @@
  */
 @Composable
 fun EventTypesDemo() {
-    val innerPointerEventTypes = remember { mutableStateListOf<PointerEventType>() }
-    val innerPointerEventCounts = remember { mutableStateListOf<Int>() }
-    val outerPointerEventTypes = remember { mutableStateListOf<PointerEventType>() }
-    val outerPointerEventCounts = remember { mutableStateListOf<Int>() }
+    val innerPointerEvents = remember { mutableStateListOf<Pair<PointerEventType, Any>>() }
+    val outerPointerEvents = remember { mutableStateListOf<Pair<PointerEventType, Any>>() }
     Box(
         Modifier.pointerInput(Unit) {
             awaitPointerEventScope {
                 while (true) {
                     val event = awaitPointerEvent()
                     event.changes.forEach { it.consumeAllChanges() }
-                    addEvent(event, outerPointerEventTypes, outerPointerEventCounts)
+                    addEvent(event, outerPointerEvents)
                 }
             }
         }
     ) {
         Column {
-            DrawEvents(outerPointerEventTypes, outerPointerEventCounts)
+            DrawEvents(outerPointerEvents)
         }
         Column(
-            Modifier
-                .align(Alignment.CenterEnd)
-                .requiredSize(200.dp)
+            Modifier.size(200.dp)
                 .border(2.dp, Color.Black)
+                .align(Alignment.CenterEnd)
                 .clipToBounds()
                 .pointerInput(Unit) {
                     awaitPointerEventScope {
                         while (true) {
                             val event = awaitPointerEvent()
-                            addEvent(event, innerPointerEventTypes, innerPointerEventCounts)
+                            addEvent(event, innerPointerEvents)
                         }
                     }
                 }
         ) {
-            DrawEvents(innerPointerEventTypes, innerPointerEventCounts)
+            DrawEvents(innerPointerEvents)
         }
     }
 }
 
+@OptIn(ExperimentalComposeUiApi::class)
 private fun addEvent(
     event: PointerEvent,
-    events: MutableList<PointerEventType>,
-    counts: MutableList<Int>
+    events: MutableList<Pair<PointerEventType, Any>>,
 ) {
     event.changes.forEach { it.consumeAllChanges() }
-    if (events.lastOrNull() == event.type) {
-        counts[counts.lastIndex]++
+    val scrollTotal = event.changes.foldRight(Offset.Zero) { c, acc -> acc + c.scrollDelta }
+    if (events.lastOrNull()?.first == event.type) {
+        val (type, value) = events.last()
+        if (type == PointerEventType.Scroll) {
+            events[events.lastIndex] = type to ((value as Offset) + scrollTotal)
+        } else {
+            events[events.lastIndex] = type to ((value as Int) + 1)
+        }
+    } else if (event.type == PointerEventType.Scroll) {
+        events += event.type to scrollTotal
     } else {
-        events += event.type
-        counts += 1
+        events += event.type to 1
     }
 
     while (events.size > 100) {
         events.removeAt(0)
-        counts.removeAt(0)
     }
 }
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
index 4b86181..211a4dc 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
@@ -2216,7 +2216,7 @@
                 dialogComposeView = LocalView.current as AndroidComposeView
                 delegate = ViewCompat.getAccessibilityDelegate(dialogComposeView!!) as
                     AndroidComposeViewAccessibilityDelegateCompat
-                provider = delegate.getAccessibilityNodeProvider(dialogComposeView).provider
+                provider = delegate.getAccessibilityNodeProvider(dialogComposeView!!).provider
                     as AccessibilityNodeProvider
 
                 with(LocalDensity.current) {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
index c1b7f74..2c6747b 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
@@ -38,6 +38,7 @@
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Stable
@@ -49,6 +50,7 @@
 import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.testutils.assertPixels
 import androidx.compose.ui.draw.DrawModifier
+import androidx.compose.ui.draw.clipToBounds
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.draw.drawWithContent
 import androidx.compose.ui.geometry.Offset
@@ -3575,6 +3577,76 @@
         assertTrue(composeView.isTransitionGroup)
     }
 
+    @Test
+    fun drawnInCorrectLayer() {
+        var innerDrawLatch = CountDownLatch(1)
+        var outerDrawLatch = CountDownLatch(1)
+        var outerColor by mutableStateOf(Color.Blue)
+        var innerColor by mutableStateOf(Color.White)
+        activityTestRule.runOnUiThread {
+            activity.setContent {
+                with(LocalDensity.current) {
+                    Box(Modifier.size(30.toDp())
+                        .drawBehind {
+                            drawRect(outerColor)
+                            outerDrawLatch.countDown()
+                        }
+                        .drawLatchModifier()
+                        .padding(10.toDp())
+                        .clipToBounds()
+                        .drawBehind {
+                            // clipped by the layer
+                            drawRect(innerColor, Offset(-10f, -10f), Size(30f, 30f))
+                            innerDrawLatch.countDown()
+                        }
+                        .drawLatchModifier()
+                        .size(10.toDp())
+                    )
+                }
+            }
+        }
+        assertTrue(innerDrawLatch.await(1, TimeUnit.SECONDS))
+        assertTrue(outerDrawLatch.await(1, TimeUnit.SECONDS))
+
+        validateSquareColors(
+            outerColor = Color.Blue,
+            innerColor = Color.White,
+            size = 10
+        )
+
+        innerDrawLatch = CountDownLatch(1)
+        outerDrawLatch = CountDownLatch(1)
+        drawLatch = CountDownLatch(1)
+
+        // changing the inner color should only affect the inner layer
+        innerColor = Color.Yellow
+
+        assertTrue(innerDrawLatch.await(1, TimeUnit.SECONDS))
+
+        validateSquareColors(
+            outerColor = Color.Blue,
+            innerColor = Color.Yellow,
+            size = 10
+        )
+
+        assertEquals(1, outerDrawLatch.count)
+        innerDrawLatch = CountDownLatch(1)
+        drawLatch = CountDownLatch(1)
+
+        // changing the outer color should only affect the outer layer
+        outerColor = Color.Red
+
+        assertTrue(outerDrawLatch.await(1, TimeUnit.SECONDS))
+
+        validateSquareColors(
+            outerColor = Color.Red,
+            innerColor = Color.Yellow,
+            size = 10
+        )
+
+        assertEquals(1, innerDrawLatch.count)
+    }
+
     private fun Modifier.layout(onLayout: () -> Unit) = layout { measurable, constraints ->
         val placeable = measurable.measure(constraints)
         layout(placeable.width, placeable.height) {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CaptureFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CaptureFocusTest.kt
index 0dcf0c8..5e49f81 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CaptureFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/CaptureFocusTest.kt
@@ -44,10 +44,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -71,10 +71,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(ActiveParent))
+                    .focusTarget(FocusModifier(ActiveParent))
             )
         }
 
@@ -98,10 +98,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -124,7 +124,7 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
                     .focusProperties { canFocus = false }
@@ -154,15 +154,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
                     .focusProperties { canFocus = false }
                     .focusable()
             ) {
-                Box(modifier = Modifier
-                    .focusRequester(initialFocus)
-                    .focusable()
+                Box(
+                    Modifier
+                        .focusRequester(initialFocus)
+                        .focusable()
                 )
             }
         }
@@ -189,10 +190,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ClearFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ClearFocusTest.kt
index c556531..250c1d7 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ClearFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ClearFocusTest.kt
@@ -50,7 +50,7 @@
         // Arrange.
         val modifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = modifier)
+            Box(Modifier.focusTarget(modifier))
         }
 
         // Act.
@@ -71,8 +71,8 @@
         val parent = FocusModifier(ActiveParent)
         val modifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = parent) {
-                Box(modifier = modifier)
+            Box(Modifier.focusTarget(parent)) {
+                Box(Modifier.focusTarget(modifier))
             }
             SideEffect {
                 parent.focusedChild = modifier.focusNode
@@ -96,7 +96,7 @@
         // Arrange.
         val modifier = FocusModifier(ActiveParent)
         rule.setFocusableContent {
-            Box(modifier = modifier)
+            Box(Modifier.focusTarget(modifier))
         }
 
         // Act.
@@ -112,9 +112,9 @@
         val modifier = FocusModifier(ActiveParent)
         val child = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = parent) {
-                Box(modifier = modifier) {
-                    Box(modifier = child)
+            Box(Modifier.focusTarget(parent)) {
+                Box(Modifier.focusTarget(modifier)) {
+                    Box(Modifier.focusTarget(child))
                 }
             }
             SideEffect {
@@ -144,10 +144,10 @@
         val grandchild = FocusModifier(ActiveParent)
         val greatGrandchild = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = modifier) {
-                Box(modifier = child) {
-                    Box(modifier = grandchild) {
-                        Box(modifier = greatGrandchild)
+            Box(Modifier.focusTarget(modifier)) {
+                Box(Modifier.focusTarget(child)) {
+                    Box(Modifier.focusTarget(grandchild)) {
+                        Box(Modifier.focusTarget(greatGrandchild))
                     }
                 }
             }
@@ -181,7 +181,7 @@
         // Arrange.
         val modifier = FocusModifier(Captured)
         rule.setFocusableContent {
-            Box(modifier = modifier)
+            Box(Modifier.focusTarget(modifier))
         }
 
         // Act.
@@ -210,8 +210,8 @@
         val parent = FocusModifier(ActiveParent)
         val modifier = FocusModifier(Captured)
         rule.setFocusableContent {
-            Box(modifier = parent) {
-                Box(modifier = modifier)
+            Box(Modifier.focusTarget(parent)) {
+                Box(Modifier.focusTarget(modifier))
             }
             SideEffect {
                 parent.focusedChild = modifier.focusNode
@@ -243,7 +243,7 @@
         // Arrange.
         val modifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = modifier)
+            Box(Modifier.focusTarget(modifier))
         }
 
         // Act.
@@ -263,7 +263,11 @@
         // Arrange.
         val modifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(modifier))
+            Box(
+                Modifier
+                    .focusProperties { canFocus = false }
+                    .focusTarget(modifier)
+            )
         }
 
         // Act.
@@ -283,7 +287,7 @@
         // Arrange.
         val modifier = FocusModifier(DeactivatedParent)
         rule.setFocusableContent {
-            Box(modifier = modifier)
+            Box(Modifier.focusTarget(modifier))
         }
 
         // Act.
@@ -299,9 +303,13 @@
         val modifier = FocusModifier(ActiveParent)
         val child = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = parent) {
-                Box(modifier = Modifier.focusProperties { canFocus = false }.then(modifier)) {
-                    Box(modifier = child)
+            Box(Modifier.focusTarget(parent)) {
+                Box(
+                    Modifier
+                        .focusProperties { canFocus = false }
+                        .focusTarget(modifier)
+                ) {
+                    Box(Modifier.focusTarget(child))
                 }
             }
             SideEffect {
@@ -330,9 +338,15 @@
         val modifier = FocusModifier(ActiveParent)
         val child = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(parent)) {
-                Box(modifier = Modifier.focusProperties { canFocus = false }.then(modifier)) {
-                    Box(modifier = child)
+            Box(Modifier
+                .focusProperties { canFocus = false }
+                .focusTarget(parent)
+            ) {
+                Box(Modifier
+                    .focusProperties { canFocus = false }
+                    .focusTarget(modifier)
+                ) {
+                    Box(Modifier.focusTarget(child))
                 }
             }
             SideEffect {
@@ -363,14 +377,17 @@
         val greatGrandchild = FocusModifier(ActiveParent)
         val greatGreatGrandchild = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(modifier)) {
-                Box(modifier = child) {
-                    Box(modifier = Modifier
+            Box(Modifier
+                .focusProperties { canFocus = false }
+                .focusTarget(modifier)
+            ) {
+                Box(modifier = Modifier.focusTarget(child)) {
+                    Box(Modifier
                         .focusProperties { canFocus = false }
-                        .then(grandchild)
+                        .focusTarget(grandchild)
                     ) {
-                        Box(modifier = greatGrandchild) {
-                            Box(modifier = greatGreatGrandchild)
+                        Box(Modifier.focusTarget(greatGrandchild)) {
+                            Box(Modifier.focusTarget(greatGreatGrandchild))
                         }
                     }
                 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindFocusableChildrenTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindFocusableChildrenTest.kt
index f3038a1..8982445 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindFocusableChildrenTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindFocusableChildrenTest.kt
@@ -51,12 +51,12 @@
         // layoutNode--focusNode1--focusNode2--focusNode3--focusNode4
         rule.setContent {
             Box(
-                modifier = Modifier
-                .then(focusModifier1)
-                .focusProperties { canFocus = false }
-                .then(focusModifier2)
-                .then(focusModifier3)
-                .then(focusModifier4)
+                Modifier
+                    .focusTarget(focusModifier1)
+                    .focusProperties { canFocus = false }
+                    .focusTarget(focusModifier2)
+                    .focusTarget(focusModifier3)
+                    .focusTarget(focusModifier4)
             )
         }
 
@@ -84,12 +84,12 @@
         // layoutNode--focusNode1--nonFocusNode--focusNode2--focusNode3
         rule.setContent {
             Box(
-                modifier = Modifier
-                    .then(focusModifier1)
+                Modifier
+                    .focusTarget(focusModifier1)
                     .background(color = Red)
                     .focusProperties { canFocus = false }
-                    .then(focusModifier2)
-                    .then(focusModifier3)
+                    .focusTarget(focusModifier2)
+                    .focusTarget(focusModifier3)
             )
         }
 
@@ -121,16 +121,18 @@
         val focusModifier3 = FocusModifier(Inactive)
         val focusModifier4 = FocusModifier(Inactive)
         rule.setContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = Modifier
-                    .focusProperties { canFocus = false }
-                    .then(focusModifier1)
-                    .then(focusModifier2)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(
+                    Modifier
+                        .focusProperties { canFocus = false }
+                        .focusTarget(focusModifier1)
+                        .focusTarget(focusModifier2)
                 )
-                Box(modifier = Modifier
-                    .then(focusModifier3)
-                    .focusProperties { canFocus = false }
-                    .then(focusModifier4)
+                Box(
+                    Modifier
+                        .focusTarget(focusModifier3)
+                        .focusProperties { canFocus = false }
+                        .focusTarget(focusModifier4)
                 )
             }
         }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindParentFocusNodeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindParentFocusNodeTest.kt
index 494246c..286bd23 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindParentFocusNodeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FindParentFocusNodeTest.kt
@@ -46,7 +46,7 @@
         // Arrange.
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
@@ -70,12 +70,14 @@
         val modifier4 = FocusModifier(Inactive)
         val modifier5 = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = modifier1
-                .focusProperties { canFocus = !deactivated }
-                .then(modifier2)
-                .then(modifier3)
-                .then(modifier4)
-                .then(modifier5)
+            Box(
+                Modifier
+                    .focusTarget(modifier1)
+                    .focusProperties { canFocus = !deactivated }
+                    .focusTarget(modifier2)
+                    .focusTarget(modifier3)
+                    .focusTarget(modifier4)
+                    .focusTarget(modifier5)
             )
         }
 
@@ -99,11 +101,12 @@
         val modifier3 = FocusModifier(Inactive)
         rule.setFocusableContent {
             Box(
-                modifier = modifier1
+                Modifier
+                    .focusTarget(modifier1)
                     .focusProperties { canFocus = !deactivated }
-                    .then(modifier2)
+                    .focusTarget(modifier2)
                     .background(color = Red)
-                    .then(modifier3)
+                    .focusTarget(modifier3)
             )
         }
 
@@ -128,11 +131,13 @@
         val parentFocusModifier2 = FocusModifier(Inactive)
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier1
-                .focusProperties { canFocus = !deactivated }
-                .then(parentFocusModifier2)
+            Box(
+                Modifier
+                    .focusTarget(parentFocusModifier1)
+                    .focusProperties { canFocus = !deactivated }
+                    .focusTarget(parentFocusModifier2)
             ) {
-                Box(modifier = focusModifier)
+                Box(Modifier.focusTarget(focusModifier))
             }
         }
 
@@ -162,13 +167,13 @@
         val parentFocusModifier = FocusModifier(Inactive)
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = greatGrandparentFocusModifier) {
-                Box(modifier = grandparentFocusModifier) {
-                    Box(modifier = Modifier
+            Box(Modifier.focusTarget(greatGrandparentFocusModifier)) {
+                Box(Modifier.focusTarget(grandparentFocusModifier)) {
+                    Box(Modifier
                         .focusProperties { canFocus = !deactivated }
-                        .then(parentFocusModifier)
+                        .focusTarget(parentFocusModifier)
                     ) {
-                        Box(modifier = focusModifier)
+                        Box(Modifier.focusTarget(focusModifier))
                     }
                 }
             }
@@ -197,13 +202,13 @@
         val grandparentFocusModifier = FocusModifier(Inactive)
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = greatGrandparentFocusModifier) {
-                Box(modifier = Modifier
+            Box(Modifier.focusTarget(greatGrandparentFocusModifier)) {
+                Box(Modifier
                     .focusProperties { canFocus = !deactivated }
-                    .then(grandparentFocusModifier)
+                    .focusTarget(grandparentFocusModifier)
                 ) {
                     Box {
-                        Box(modifier = focusModifier)
+                        Box(Modifier.focusTarget(focusModifier))
                     }
                 }
             }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusChangedTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusChangedTest.kt
index ec729ec..88b4d3c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusChangedTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FocusChangedTest.kt
@@ -46,7 +46,7 @@
                 modifier = Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -106,7 +106,7 @@
                 modifier = Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -196,7 +196,7 @@
                 modifier = Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
@@ -236,7 +236,7 @@
                                 .onFocusChanged { focusState5 = it }
                                 .onFocusChanged { focusState6 = it }
                                 .focusRequester(focusRequester)
-                                .then(FocusModifier(Inactive))
+                                .focusTarget(FocusModifier(Inactive))
                         )
                     }
                 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FreeFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FreeFocusTest.kt
index a0845c9..0ecc2d73a 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FreeFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/FreeFocusTest.kt
@@ -43,10 +43,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -67,10 +67,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(ActiveParent))
+                    .focusTarget(FocusModifier(ActiveParent))
             )
         }
 
@@ -91,10 +91,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -115,11 +115,11 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
                     .focusProperties { canFocus = false }
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
@@ -140,10 +140,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
index ad2151b..1e38ac4 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
@@ -25,36 +25,30 @@
 import androidx.compose.ui.focus.FocusStateImpl.DeactivatedParent
 import androidx.compose.ui.focus.FocusStateImpl.Inactive
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
 
 @SmallTest
-@RunWith(Parameterized::class)
-class RequestFocusTest(private val propagateFocus: Boolean) {
+@RunWith(AndroidJUnit4::class)
+class RequestFocusTest {
     @get:Rule
     val rule = createComposeRule()
 
-    companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "propagateFocus = {0}")
-        fun initParameters() = listOf(true, false)
-    }
-
     @Test
     fun active_isUnchanged() {
         // Arrange.
         val focusModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -69,12 +63,12 @@
         // Arrange.
         val focusModifier = FocusModifier(Captured)
         rule.setFocusableContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -88,12 +82,15 @@
         // Arrange.
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(focusModifier))
+            Box(Modifier
+                .focusProperties { canFocus = false }
+                .focusTarget(focusModifier)
+            )
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -107,12 +104,12 @@
         // Arrange.
         val focusModifier = FocusModifier(ActiveParent)
         rule.setFocusableContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
     }
 
@@ -122,8 +119,8 @@
         val focusModifier = FocusModifier(ActiveParent)
         val childFocusModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = focusModifier) {
-                Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(focusModifier)) {
+                Box(Modifier.focusTarget(childFocusModifier))
             }
         }
         rule.runOnIdle {
@@ -132,23 +129,14 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> {
-                    // Unchanged.
-                    assertThat(focusModifier.focusState).isEqualTo(ActiveParent)
-                    assertThat(childFocusModifier.focusState).isEqualTo(Active)
-                }
-                false -> {
-                    assertThat(focusModifier.focusState).isEqualTo(Active)
-                    assertThat(focusModifier.focusedChild).isNull()
-                    assertThat(childFocusModifier.focusState).isEqualTo(Inactive)
-                }
-            }
+            assertThat(focusModifier.focusState).isEqualTo(Active)
+            assertThat(focusModifier.focusedChild).isNull()
+            assertThat(childFocusModifier.focusState).isEqualTo(Inactive)
         }
     }
 
@@ -157,12 +145,12 @@
         // Arrange.
         val focusModifier = FocusModifier(DeactivatedParent)
         rule.setFocusableContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
     }
 
@@ -172,8 +160,11 @@
         val focusModifier = FocusModifier(ActiveParent)
         val childFocusModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(focusModifier)) {
-                Box(modifier = childFocusModifier)
+            Box(Modifier
+                .focusProperties { canFocus = false }
+                .focusTarget(focusModifier)
+            ) {
+                Box(Modifier.focusTarget(childFocusModifier))
             }
         }
         rule.runOnIdle {
@@ -182,14 +173,14 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-           // Unchanged.
-           assertThat(focusModifier.focusState).isEqualTo(DeactivatedParent)
-           assertThat(childFocusModifier.focusState).isEqualTo(Active)
+            // Unchanged.
+            assertThat(focusModifier.focusState).isEqualTo(DeactivatedParent)
+            assertThat(childFocusModifier.focusState).isEqualTo(Active)
         }
     }
 
@@ -200,9 +191,12 @@
         val childFocusModifier = FocusModifier(Active)
         val grandchildFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = Modifier.focusProperties { canFocus = false }.then(focusModifier)) {
-                Box(modifier = childFocusModifier) {
-                    Box(modifier = grandchildFocusModifier)
+            Box(Modifier
+                .focusProperties { canFocus = false }
+                .focusTarget(focusModifier)
+            ) {
+                Box(Modifier.focusTarget(childFocusModifier)) {
+                    Box(Modifier.focusTarget(grandchildFocusModifier))
                 }
             }
         }
@@ -212,24 +206,15 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> {
-                    assertThat(focusModifier.focusState).isEqualTo(DeactivatedParent)
-                    assertThat(childFocusModifier.focusState).isEqualTo(Active)
-                    assertThat(grandchildFocusModifier.focusState).isEqualTo(Inactive)
-                }
-                false -> {
                     assertThat(focusModifier.focusState).isEqualTo(DeactivatedParent)
                     assertThat(childFocusModifier.focusState).isEqualTo(Active)
                     assertThat(childFocusModifier.focusedChild).isNull()
                     assertThat(grandchildFocusModifier.focusState).isEqualTo(Inactive)
-                }
-            }
         }
     }
 
@@ -238,12 +223,12 @@
         // Arrange.
         val rootFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = rootFocusModifier)
+            Box(Modifier.focusTarget(rootFocusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            rootFocusModifier.focusNode.requestFocus(propagateFocus)
+            rootFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -258,29 +243,20 @@
         val rootFocusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = rootFocusModifier) {
-                Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(rootFocusModifier)) {
+                Box(Modifier.focusTarget(childFocusModifier))
             }
         }
 
         // Act.
         rule.runOnIdle {
-            rootFocusModifier.focusNode.requestFocus(propagateFocus)
+            rootFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> {
-                    // Unchanged.
-                    assertThat(rootFocusModifier.focusState).isEqualTo(ActiveParent)
-                    assertThat(childFocusModifier.focusState).isEqualTo(Active)
-                }
-                false -> {
                     assertThat(rootFocusModifier.focusState).isEqualTo(Active)
                     assertThat(childFocusModifier.focusState).isEqualTo(Inactive)
-                }
-            }
         }
     }
 
@@ -291,32 +267,23 @@
         val focusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier) {
-                    Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier)) {
+                    Box(Modifier.focusTarget(childFocusModifier))
                 }
             }
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> {
-                    assertThat(parentFocusModifier.focusState).isEqualTo(ActiveParent)
-                    assertThat(focusModifier.focusState).isEqualTo(ActiveParent)
-                    assertThat(childFocusModifier.focusState).isEqualTo(Active)
-                }
-                false -> {
-                    assertThat(parentFocusModifier.focusState).isEqualTo(ActiveParent)
+            assertThat(parentFocusModifier.focusState).isEqualTo(ActiveParent)
                     assertThat(focusModifier.focusState).isEqualTo(Active)
                     assertThat(childFocusModifier.focusState).isEqualTo(Inactive)
-                }
-            }
         }
     }
 
@@ -325,12 +292,12 @@
         // Arrange.
         val rootFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = rootFocusModifier)
+            Box(Modifier.focusTarget(rootFocusModifier))
         }
 
         // Act.
         rule.runOnIdle {
-            rootFocusModifier.focusNode.requestFocus(propagateFocus)
+            rootFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -345,22 +312,19 @@
         val rootFocusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = rootFocusModifier) {
-                Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(rootFocusModifier)) {
+                Box(Modifier.focusTarget(childFocusModifier))
             }
         }
 
         // Act.
         rule.runOnIdle {
-            rootFocusModifier.focusNode.requestFocus(propagateFocus)
+            rootFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> assertThat(rootFocusModifier.focusState).isEqualTo(ActiveParent)
-                false -> assertThat(rootFocusModifier.focusState).isEqualTo(Active)
-            }
+            assertThat(rootFocusModifier.focusState).isEqualTo(Active)
         }
     }
 
@@ -371,24 +335,21 @@
         val parentFocusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = grandParentFocusModifier) {
-                Box(modifier = parentFocusModifier) {
-                    Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(grandParentFocusModifier)) {
+                Box(Modifier.focusTarget(parentFocusModifier)) {
+                    Box(Modifier.focusTarget(childFocusModifier))
                 }
             }
         }
 
         // Act.
         rule.runOnIdle {
-            parentFocusModifier.focusNode.requestFocus(propagateFocus)
+            parentFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> assertThat(parentFocusModifier.focusState).isEqualTo(ActiveParent)
-                false -> assertThat(parentFocusModifier.focusState).isEqualTo(Active)
-            }
+            assertThat(parentFocusModifier.focusState).isEqualTo(Active)
         }
     }
 
@@ -399,16 +360,16 @@
         val parentFocusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = grandParentFocusModifier) {
-                Box(modifier = parentFocusModifier) {
-                    Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(grandParentFocusModifier)) {
+                Box(Modifier.focusTarget(parentFocusModifier)) {
+                    Box(Modifier.focusTarget(childFocusModifier))
                 }
             }
         }
 
         // Act.
         rule.runOnIdle {
-            childFocusModifier.focusNode.requestFocus(propagateFocus)
+            childFocusModifier.focusNode.requestFocus()
         }
         // Assert.
         rule.runOnIdle {
@@ -423,16 +384,16 @@
         val parentFocusModifier = FocusModifier(Inactive)
         val childFocusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = grandParentFocusModifier) {
-                Box(modifier = parentFocusModifier) {
-                    Box(modifier = childFocusModifier)
+            Box(Modifier.focusTarget(grandParentFocusModifier)) {
+                Box(Modifier.focusTarget(parentFocusModifier)) {
+                    Box(Modifier.focusTarget(childFocusModifier))
                 }
             }
         }
 
         // Act.
         rule.runOnIdle {
-            childFocusModifier.focusNode.requestFocus(propagateFocus)
+            childFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -447,14 +408,14 @@
         val parentFocusModifier = FocusModifier(Active)
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier))
             }
         }
 
         // After executing requestFocus, siblingNode will be 'Active'.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -470,8 +431,8 @@
         val parentFocusModifier = FocusModifier(ActiveParent)
         val focusModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier))
             }
         }
         rule.runOnIdle {
@@ -480,21 +441,13 @@
 
         // Act.
         rule.runOnIdle {
-            parentFocusModifier.focusNode.requestFocus(propagateFocus)
+            parentFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
         rule.runOnIdle {
-            when (propagateFocus) {
-                true -> {
-                    assertThat(parentFocusModifier.focusState).isEqualTo(ActiveParent)
-                    assertThat(focusModifier.focusState).isEqualTo(Active)
-                }
-                false -> {
-                    assertThat(parentFocusModifier.focusState).isEqualTo(Active)
+            assertThat(parentFocusModifier.focusState).isEqualTo(Active)
                     assertThat(focusModifier.focusState).isEqualTo(Inactive)
-                }
-            }
         }
     }
 
@@ -504,8 +457,8 @@
         val parentFocusModifier = FocusModifier(ActiveParent)
         val focusModifier = FocusModifier(Captured)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier))
             }
         }
         rule.runOnIdle {
@@ -514,7 +467,7 @@
 
         // Act.
         rule.runOnIdle {
-            parentFocusModifier.focusNode.requestFocus(propagateFocus)
+            parentFocusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -531,9 +484,9 @@
         val focusModifier = FocusModifier(Inactive)
         val siblingModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier)
-                Box(modifier = siblingModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier))
+                Box(Modifier.focusTarget(siblingModifier))
             }
         }
         rule.runOnIdle {
@@ -542,7 +495,7 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -560,9 +513,9 @@
         val focusModifier = FocusModifier(Inactive)
         val siblingModifier = FocusModifier(Captured)
         rule.setFocusableContent {
-            Box(modifier = parentFocusModifier) {
-                Box(modifier = focusModifier)
-                Box(modifier = siblingModifier)
+            Box(Modifier.focusTarget(parentFocusModifier)) {
+                Box(Modifier.focusTarget(focusModifier))
+                Box(Modifier.focusTarget(siblingModifier))
             }
         }
         rule.runOnIdle {
@@ -571,7 +524,7 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -591,12 +544,12 @@
         val auntModifier = FocusModifier(ActiveParent)
         val cousinModifier = FocusModifier(Active)
         rule.setFocusableContent {
-            Box(modifier = grandParentModifier) {
-                Box(modifier = parentModifier) {
-                    Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(grandParentModifier)) {
+                Box(Modifier.focusTarget(parentModifier)) {
+                    Box(Modifier.focusTarget(focusModifier))
                 }
-                Box(modifier = auntModifier) {
-                    Box(modifier = cousinModifier)
+                Box(Modifier.focusTarget(auntModifier)) {
+                    Box(Modifier.focusTarget(cousinModifier))
                 }
             }
         }
@@ -613,7 +566,7 @@
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
@@ -630,16 +583,16 @@
         val parentModifier = FocusModifier(Inactive)
         val focusModifier = FocusModifier(Inactive)
         rule.setFocusableContent {
-            Box(modifier = grandParentModifier) {
-                Box(modifier = parentModifier) {
-                    Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(grandParentModifier)) {
+                Box(Modifier.focusTarget(parentModifier)) {
+                    Box(Modifier.focusTarget(focusModifier))
                 }
             }
         }
 
         // Act.
         rule.runOnIdle {
-            focusModifier.focusNode.requestFocus(propagateFocus)
+            focusModifier.focusNode.requestFocus()
         }
 
         // Assert.
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterCaptureFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterCaptureFocusTest.kt
index 749d6fa..84ee29a 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterCaptureFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterCaptureFocusTest.kt
@@ -42,10 +42,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -66,10 +66,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -90,10 +90,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
@@ -115,16 +115,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -147,16 +147,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -179,16 +179,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterFreeFocusTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterFreeFocusTest.kt
index 4848951..9805036 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterFreeFocusTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/focus/ReusedFocusRequesterFreeFocusTest.kt
@@ -42,10 +42,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -66,10 +66,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -90,10 +90,10 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
@@ -115,16 +115,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Active))
+                    .focusTarget(FocusModifier(Active))
             )
         }
 
@@ -147,16 +147,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Captured))
+                    .focusTarget(FocusModifier(Captured))
             )
         }
 
@@ -179,16 +179,16 @@
         val focusRequester = FocusRequester()
         rule.setFocusableContent {
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState1 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
             Box(
-                modifier = Modifier
+                Modifier
                     .onFocusChanged { focusState2 = it }
                     .focusRequester(focusRequester)
-                    .then(FocusModifier(Inactive))
+                    .focusTarget(FocusModifier(Inactive))
             )
         }
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/gesture/Utils.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/gesture/Utils.kt
index 31dc186..fb57437 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/gesture/Utils.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/gesture/Utils.kt
@@ -17,6 +17,8 @@
 package androidx.compose.ui.gesture
 
 import android.view.MotionEvent
+import android.view.MotionEvent.AXIS_HSCROLL
+import android.view.MotionEvent.AXIS_VSCROLL
 import android.view.View
 
 // We only need this because IR compiler doesn't like converting lambdas to Runnables
@@ -87,8 +89,10 @@
     MotionEvent.PointerProperties().apply { this.id = id }
 
 @Suppress("RemoveRedundantQualifierName")
-internal fun PointerCoords(x: Float, y: Float) =
+internal fun PointerCoords(x: Float, y: Float, scrollX: Float = 0f, scrollY: Float = 0f) =
     MotionEvent.PointerCoords().apply {
         this.x = x
         this.y = y
+        setAxisValue(AXIS_HSCROLL, scrollX)
+        setAxisValue(AXIS_VSCROLL, scrollY)
     }
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
index 5f5158f..c972784 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
@@ -28,6 +28,7 @@
 import android.view.MotionEvent.ACTION_HOVER_MOVE
 import android.view.MotionEvent.ACTION_MOVE
 import android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT
+import android.view.MotionEvent.ACTION_SCROLL
 import android.view.MotionEvent.ACTION_UP
 import android.view.MotionEvent.TOOL_TYPE_FINGER
 import android.view.MotionEvent.TOOL_TYPE_MOUSE
@@ -50,6 +51,7 @@
 import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.ui.AbsoluteAlignment
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.OpenComposeView
 import androidx.compose.ui.composed
@@ -70,6 +72,7 @@
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastAll
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -740,10 +743,24 @@
         assertThat(event.type).isEqualTo(expectedHoverType)
     }
 
+    @OptIn(ExperimentalComposeUiApi::class)
+    private fun assertScrollEvent(
+        event: PointerEvent,
+        scrollExpected: Offset
+    ) {
+        assertThat(event.changes).hasSize(1)
+        val change = event.changes[0]
+        assertThat(change.pressed).isFalse()
+        assertThat(event.type).isEqualTo(PointerEventType.Scroll)
+        // we agreed to reverse the delta in android to be in line with other platforms
+        assertThat(change.scrollDelta).isEqualTo(-scrollExpected)
+    }
+
     private fun dispatchMouseEvent(
-        action: Int = ACTION_HOVER_ENTER,
+        action: Int,
         layoutCoordinates: LayoutCoordinates,
-        offset: Offset = Offset.Zero
+        offset: Offset = Offset.Zero,
+        scrollDelta: Offset = Offset.Zero
     ) {
         rule.runOnUiThread {
             val root = layoutCoordinates.findRoot()
@@ -754,13 +771,14 @@
                 1,
                 0,
                 arrayOf(PointerProperties(0).also { it.toolType = MotionEvent.TOOL_TYPE_MOUSE }),
-                arrayOf(PointerCoords(pos.x, pos.y))
+                arrayOf(PointerCoords(pos.x, pos.y, scrollDelta.x, scrollDelta.y))
             )
 
             val androidComposeView = findAndroidComposeView(container) as AndroidComposeView
             when (action) {
                 ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT ->
                     androidComposeView.dispatchHoverEvent(event)
+                ACTION_SCROLL -> androidComposeView.dispatchGenericMotionEvent(event)
                 else -> androidComposeView.dispatchTouchEvent(event)
             }
         }
@@ -981,6 +999,149 @@
     }
 
     @Test
+    fun dispatchScroll() {
+        var layoutCoordinates: LayoutCoordinates? = null
+        val latch = CountDownLatch(1)
+        val events = mutableListOf<PointerEvent>()
+        val scrollDelta = Offset(0.35f, 0.65f)
+        rule.runOnUiThread {
+            container.setContent {
+                Box(
+                    Modifier.fillMaxSize().onGloballyPositioned {
+                        layoutCoordinates = it
+                        latch.countDown()
+                    }.pointerInput(Unit) {
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                event.changes[0].consumeAllChanges()
+                                events += event
+                            }
+                        }
+                    }
+                )
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        dispatchMouseEvent(ACTION_SCROLL, layoutCoordinates!!, scrollDelta = scrollDelta)
+        rule.runOnUiThread {
+            assertThat(events).hasSize(2) // synthetic enter and scroll
+            assertHoverEvent(events[0], isEnter = true)
+            assertScrollEvent(events[1], scrollExpected = scrollDelta)
+        }
+    }
+
+    @Test
+    fun dispatchScroll_whenButtonPressed() {
+        var layoutCoordinates: LayoutCoordinates? = null
+        val latch = CountDownLatch(1)
+        val events = mutableListOf<PointerEvent>()
+        val scrollDelta = Offset(0.35f, 0.65f)
+        rule.runOnUiThread {
+            container.setContent {
+                Box(
+                    Modifier.fillMaxSize().onGloballyPositioned {
+                        layoutCoordinates = it
+                        latch.countDown()
+                    }.pointerInput(Unit) {
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                event.changes[0].consumeAllChanges()
+                                events += event
+                            }
+                        }
+                    }
+                )
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        // press the button first before scroll
+        dispatchMouseEvent(ACTION_DOWN, layoutCoordinates!!)
+        dispatchMouseEvent(ACTION_SCROLL, layoutCoordinates!!, scrollDelta = scrollDelta)
+        rule.runOnUiThread {
+            assertThat(events).hasSize(3) // synthetic enter, button down, scroll
+            assertHoverEvent(events[0], isEnter = true)
+            assert(events[1].changes.fastAll { it.changedToDownIgnoreConsumed() })
+            assertScrollEvent(events[2], scrollExpected = scrollDelta)
+        }
+    }
+
+    @Test
+    fun dispatchScroll_batch() {
+        var layoutCoordinates: LayoutCoordinates? = null
+        val latch = CountDownLatch(1)
+        val events = mutableListOf<PointerEvent>()
+        val scrollDelta1 = Offset(0.32f, -0.75f)
+        val scrollDelta2 = Offset(0.14f, 0.35f)
+        val scrollDelta3 = Offset(-0.30f, -0.12f)
+        val scrollDelta4 = Offset(-0.05f, 0.68f)
+        rule.runOnUiThread {
+            container.setContent {
+                Box(
+                    Modifier.fillMaxSize().onGloballyPositioned {
+                        layoutCoordinates = it
+                        latch.countDown()
+                    }.pointerInput(Unit) {
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                event.changes[0].consumeAllChanges()
+                                events += event
+                            }
+                        }
+                    }
+                )
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        listOf(scrollDelta1, scrollDelta2, scrollDelta3, scrollDelta4).fastForEach {
+            dispatchMouseEvent(ACTION_SCROLL, layoutCoordinates!!, scrollDelta = it)
+        }
+        rule.runOnUiThread {
+            assertThat(events).hasSize(5) // 4 + synthetic enter
+            assertHoverEvent(events[0], isEnter = true)
+            assertScrollEvent(events[1], scrollExpected = scrollDelta1)
+            assertScrollEvent(events[2], scrollExpected = scrollDelta2)
+            assertScrollEvent(events[3], scrollExpected = scrollDelta3)
+            assertScrollEvent(events[4], scrollExpected = scrollDelta4)
+        }
+    }
+
+    @Test
+    fun mouseScroll_ignoredAsDownEvent() {
+        var layoutCoordinates: LayoutCoordinates? = null
+        val latch = CountDownLatch(1)
+        val events = mutableListOf<PointerEvent>()
+        val scrollDelta = Offset(0.35f, 0.65f)
+        rule.runOnUiThread {
+            container.setContent {
+                Box(
+                    Modifier.fillMaxSize().onGloballyPositioned {
+                        layoutCoordinates = it
+                        latch.countDown()
+                    }.pointerInput(Unit) {
+                        awaitPointerEventScope {
+                            while (true) {
+                                val event = awaitPointerEvent()
+                                event.changes[0].consumeAllChanges()
+                                events += event
+                            }
+                        }
+                    }
+                )
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        dispatchMouseEvent(ACTION_SCROLL, layoutCoordinates!!, scrollDelta = scrollDelta)
+        rule.runOnUiThread {
+            assertThat(events).hasSize(2) // hover enter + scroll
+            assertThat(events[1].changes).isNotEmpty()
+            assertThat(events[1].changes[0].changedToDown()).isFalse()
+        }
+    }
+
+    @Test
     fun hoverEnterPressExitEnterExitRelease() {
         var outerCoordinates: LayoutCoordinates? = null
         var innerCoordinates: LayoutCoordinates? = null
@@ -1029,39 +1190,48 @@
 
     @Test
     fun hoverPressEnterRelease() {
-        var outerCoordinates: LayoutCoordinates? = null
-        var innerCoordinates: LayoutCoordinates? = null
+        var missCoordinates: LayoutCoordinates? = null
+        var hitCoordinates: LayoutCoordinates? = null
         val latch = CountDownLatch(1)
         val eventLog = mutableListOf<PointerEvent>()
         rule.runOnUiThread {
             container.setContent {
-                Box(
-                    Modifier.fillMaxSize().onGloballyPositioned {
-                        outerCoordinates = it
-                        latch.countDown()
-                    }
-                ) {
+                Box(Modifier.fillMaxSize()) {
                     Box(
-                        Modifier.align(Alignment.Center).size(50.dp).pointerInput(Unit) {
-                            awaitPointerEventScope {
-                                while (true) {
-                                    val event = awaitPointerEvent()
-                                    event.changes[0].consumeAllChanges()
-                                    eventLog += event
+                        Modifier.align(AbsoluteAlignment.TopLeft).size(50.dp)
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        awaitPointerEvent()
+                                    }
                                 }
+                            }.onGloballyPositioned {
+                                missCoordinates = it
+                                latch.countDown()
                             }
-                        }.onGloballyPositioned { innerCoordinates = it }
+                    )
+                    Box(
+                        Modifier.align(AbsoluteAlignment.BottomRight).size(50.dp)
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        val event = awaitPointerEvent()
+                                        event.changes[0].consumeAllChanges()
+                                        eventLog += event
+                                    }
+                                }
+                            }.onGloballyPositioned { hitCoordinates = it }
                     )
                 }
             }
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
-        dispatchMouseEvent(ACTION_HOVER_ENTER, outerCoordinates!!)
-        dispatchMouseEvent(ACTION_HOVER_EXIT, outerCoordinates!!)
-        dispatchMouseEvent(ACTION_DOWN, outerCoordinates!!)
-        dispatchMouseEvent(ACTION_MOVE, innerCoordinates!!)
-        dispatchMouseEvent(ACTION_UP, innerCoordinates!!)
-        dispatchMouseEvent(ACTION_HOVER_ENTER, innerCoordinates!!)
+        dispatchMouseEvent(ACTION_HOVER_ENTER, missCoordinates!!)
+        dispatchMouseEvent(ACTION_HOVER_EXIT, missCoordinates!!)
+        dispatchMouseEvent(ACTION_DOWN, missCoordinates!!)
+        dispatchMouseEvent(ACTION_MOVE, hitCoordinates!!)
+        dispatchMouseEvent(ACTION_UP, hitCoordinates!!)
+        dispatchMouseEvent(ACTION_HOVER_ENTER, hitCoordinates!!)
         rule.runOnUiThread {
             assertThat(eventLog).hasSize(1)
             assertThat(eventLog[0].type).isEqualTo(PointerEventType.Enter)
@@ -1404,7 +1574,8 @@
 
         // Hit the bottom box, but clipped
         dispatchMouseEvent(ACTION_HOVER_MOVE, coords)
-        dispatchMouseEvent(ACTION_HOVER_MOVE, coords,
+        dispatchMouseEvent(
+            ACTION_HOVER_MOVE, coords,
             Offset(0f, (coords.size.height / 2 - 1).toFloat())
         )
 
@@ -1413,17 +1584,20 @@
         }
 
         // Now hit the box in the unclipped region
-        dispatchMouseEvent(ACTION_HOVER_MOVE, coords,
+        dispatchMouseEvent(
+            ACTION_HOVER_MOVE, coords,
             Offset(0f, (coords.size.height / 2 + 1).toFloat())
         )
 
         // Now hit the bottom of the clipped region
-        dispatchMouseEvent(ACTION_HOVER_MOVE, coords,
+        dispatchMouseEvent(
+            ACTION_HOVER_MOVE, coords,
             Offset(0f, (coords.size.height - 1).toFloat())
         )
 
         // Now leave
-        dispatchMouseEvent(ACTION_HOVER_MOVE, coords,
+        dispatchMouseEvent(
+            ACTION_HOVER_MOVE, coords,
             Offset(0f, coords.size.height.toFloat() + 1f)
         )
 
@@ -1570,6 +1744,71 @@
         }
     }
 
+    @Test
+    fun restartStreamAfterNotProcessing() {
+        // Stylus hover enter/exit events should be sent to pointer input areas
+        val eventLog = mutableListOf<PointerEvent>()
+        var hitCoordinates: LayoutCoordinates? = null
+        var missCoordinates: LayoutCoordinates? = null
+        val latch = CountDownLatch(2)
+        rule.runOnUiThread {
+            container.setContent {
+                Box(Modifier.fillMaxSize()) {
+                    Box(Modifier.size(50.dp).align(AbsoluteAlignment.TopLeft)
+                        .pointerInput(Unit) {
+                            awaitPointerEventScope {
+                                while (true) {
+                                    val event = awaitPointerEvent()
+                                    event.changes.forEach { it.consumeAllChanges() }
+                                    eventLog += event
+                                }
+                            }
+                        }.onGloballyPositioned {
+                            hitCoordinates = it
+                            latch.countDown()
+                        }
+                    )
+                    Box(Modifier.size(50.dp).align(AbsoluteAlignment.BottomRight)
+                        .onGloballyPositioned {
+                            missCoordinates = it
+                            latch.countDown()
+                        }
+                    )
+                }
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+        val miss = missCoordinates!!
+        val hit = hitCoordinates!!
+
+        // This should hit
+        dispatchTouchEvent(ACTION_DOWN, hit)
+        dispatchTouchEvent(ACTION_UP, hit)
+
+        // This should miss
+        dispatchTouchEvent(ACTION_DOWN, miss)
+
+        // This should hit
+        dispatchTouchEvent(ACTION_DOWN, hit)
+
+        rule.runOnUiThread {
+            assertThat(eventLog).hasSize(3)
+            val down1 = eventLog[0]
+            val up1 = eventLog[1]
+            val down2 = eventLog[2]
+            assertThat(down1.changes).hasSize(1)
+            assertThat(up1.changes).hasSize(1)
+            assertThat(down2.changes).hasSize(1)
+
+            assertThat(down1.type).isEqualTo(PointerEventType.Press)
+            assertThat(up1.type).isEqualTo(PointerEventType.Release)
+            assertThat(down2.type).isEqualTo(PointerEventType.Press)
+
+            assertThat(up1.changes[0].id).isEqualTo(down1.changes[0].id)
+            assertThat(down2.changes[0].id.value).isEqualTo(down1.changes[0].id.value + 2)
+        }
+    }
+
     private fun createPointerEventAt(eventTime: Int, action: Int, locationInWindow: IntArray) =
         MotionEvent(
             eventTime,
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterAndroidViewHookupTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterAndroidViewHookupTest.kt
index 59d7e44..51e8a95 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterAndroidViewHookupTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInteropFilterAndroidViewHookupTest.kt
@@ -34,6 +34,7 @@
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -477,6 +478,7 @@
         assertThat(captureRequestDisallow.disallowIntercept).isFalse()
     }
 
+    @FlakyTest(bugId = 206967867)
     @Test
     fun disallowTriggeredWhenMovementInClickChildAfterRequestDisallow() {
         var clicked = false
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/NodesRemeasuredOnceTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/NodesRemeasuredOnceTest.kt
index 51ee357..28bb807 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/NodesRemeasuredOnceTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/NodesRemeasuredOnceTest.kt
@@ -119,6 +119,34 @@
             assertThat(remeasurements).isEqualTo(2)
         }
     }
+
+    @Test
+    fun remeasuringChildWithExtraLayer_notPlacedChild() {
+        val height = mutableStateOf(10)
+        var remeasurements = 0
+
+        rule.setContent {
+            WrapChild(onMeasured = { actualHeight ->
+                assertThat(actualHeight).isEqualTo(height.value)
+                remeasurements++
+            }) {
+                NotPlaceChild(height) {
+                    WrapChild {
+                        Child(height)
+                    }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(remeasurements).isEqualTo(1)
+            height.value = 20
+        }
+
+        rule.runOnIdle {
+            assertThat(remeasurements).isEqualTo(2)
+        }
+    }
 }
 
 @Composable
@@ -134,6 +162,16 @@
 }
 
 @Composable
+private fun NotPlaceChild(height: State<Int>, content: @Composable () -> Unit) {
+    Layout(content = content) { measurables, constraints ->
+        layout(constraints.maxWidth, height.value) {
+            measurables.first()
+                .measure(constraints.copy(minHeight = 0, maxHeight = Constraints.Infinity))
+        }
+    }
+}
+
+@Composable
 private fun Child(height: State<Int>) {
     Layout { _, constraints ->
         layout(constraints.maxWidth, height.value) {}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/LayoutNodeWrapperInitializationTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/LayoutNodeWrapperInitializationTest.kt
index a72033a..0436ac3 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/LayoutNodeWrapperInitializationTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/node/LayoutNodeWrapperInitializationTest.kt
@@ -23,6 +23,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusModifier
 import androidx.compose.ui.focus.FocusStateImpl
+import androidx.compose.ui.focus.focusTarget
 import androidx.compose.ui.input.key.KeyInputModifier
 import androidx.compose.ui.input.pointer.PointerInputModifier
 import androidx.compose.ui.input.pointer.PointerInteropFilter
@@ -49,7 +50,7 @@
 
         // Act.
         rule.setContent {
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Assert.
@@ -117,7 +118,7 @@
         rule.setContent {
             scope = currentRecomposeScope
             focusModifier = FocusModifier(FocusStateImpl.Inactive)
-            Box(modifier = focusModifier)
+            Box(Modifier.focusTarget(focusModifier))
         }
 
         // Act.
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
index 6193daf..f6c3140 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
@@ -27,6 +27,7 @@
 import android.view.MotionEvent.ACTION_HOVER_MOVE
 import android.view.MotionEvent.ACTION_POINTER_DOWN
 import android.view.MotionEvent.ACTION_POINTER_UP
+import android.view.MotionEvent.ACTION_SCROLL
 import android.view.MotionEvent.ACTION_UP
 import android.view.MotionEvent.TOOL_TYPE_ERASER
 import android.view.MotionEvent.TOOL_TYPE_FINGER
@@ -95,6 +96,7 @@
 
         val isHover = action == ACTION_HOVER_EXIT || action == ACTION_HOVER_MOVE ||
             action == ACTION_HOVER_ENTER
+        val isScroll = action == ACTION_SCROLL
 
         if (isHover) {
             val hoverId = motionEvent.getPointerId(motionEvent.actionIndex)
@@ -117,7 +119,11 @@
                     positionCalculator,
                     motionEvent,
                     i,
-                    !isHover && i != upIndex
+                    // "pressed" means:
+                    // 1. we're not hovered
+                    // 2. we didn't get UP event for a pointer
+                    // 3. button on the mouse is pressed BUT it's not a "scroll" simulated button
+                    !isHover && i != upIndex && (!isScroll || motionEvent.buttonState != 0)
                 )
             )
         }
@@ -132,6 +138,15 @@
     }
 
     /**
+     * An ACTION_DOWN or ACTION_POINTER_DOWN was received, but not handled, so the stream should
+     * be considered ended.
+     */
+    fun endStream(pointerId: Int) {
+        canHover.delete(pointerId)
+        motionEventToComposePointerIdMap.delete(pointerId)
+    }
+
+    /**
      * Add any new pointer IDs.
      */
     private fun addFreshIds(motionEvent: MotionEvent) {
@@ -167,7 +182,7 @@
                 val actionIndex = motionEvent.actionIndex
                 val pointerId = motionEvent.getPointerId(actionIndex)
                 if (!canHover.get(pointerId, false)) {
-                    motionEventToComposePointerIdMap.delete(motionEvent.getPointerId(actionIndex))
+                    motionEventToComposePointerIdMap.delete(pointerId)
                     canHover.delete(pointerId)
                 }
             }
@@ -277,6 +292,17 @@
                 }
             }
         }
+        val scrollDelta = if (motionEvent.actionMasked == ACTION_SCROLL) {
+            val x = motionEvent.getAxisValue(MotionEvent.AXIS_HSCROLL)
+            val y = motionEvent.getAxisValue(MotionEvent.AXIS_VSCROLL)
+            // NOTE: we revert the scroll offset because android is special compared to other
+            // platforms and send the reversed sign for up and down mouse wheel scroll. In order to
+            // support better x-platform mouse scroll, we revert to be in line with desktop
+            // platforms.
+            Offset(x, y) * -1f
+        } else {
+            Offset.Zero
+        }
 
         val issuesEnterExit = canHover.get(motionEvent.getPointerId(index), false)
         return PointerInputEventData(
@@ -287,7 +313,8 @@
             pressed,
             toolType,
             issuesEnterExit,
-            historical
+            historical,
+            scrollDelta
         )
     }
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.android.kt
index fde4a0a..82ac8cb 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.android.kt
@@ -18,6 +18,8 @@
 
 import android.view.KeyEvent
 import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_SCROLL
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastMap
 
@@ -49,6 +51,7 @@
     actual var type: PointerEventType = calculatePointerEventType()
         internal set
 
+    @OptIn(ExperimentalComposeUiApi::class)
     private fun calculatePointerEventType(): PointerEventType {
         val motionEvent = motionEvent
         if (motionEvent != null) {
@@ -61,6 +64,7 @@
                 MotionEvent.ACTION_MOVE -> PointerEventType.Move
                 MotionEvent.ACTION_HOVER_ENTER -> PointerEventType.Enter
                 MotionEvent.ACTION_HOVER_EXIT -> PointerEventType.Exit
+                ACTION_SCROLL -> PointerEventType.Scroll
 
                 else -> PointerEventType.Unknown
             }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEvent.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEvent.android.kt
index c3ee76b..3862b31 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEvent.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEvent.android.kt
@@ -22,4 +22,4 @@
     actual val uptime: Long,
     actual val pointers: List<PointerInputEventData>,
     val motionEvent: MotionEvent
-)
\ No newline at end of file
+)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 9c3862d..45b6659 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -32,7 +32,9 @@
 import android.view.MotionEvent.ACTION_HOVER_ENTER
 import android.view.MotionEvent.ACTION_HOVER_EXIT
 import android.view.MotionEvent.ACTION_HOVER_MOVE
+import android.view.MotionEvent.ACTION_SCROLL
 import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_POINTER_DOWN
 import android.view.MotionEvent.ACTION_POINTER_UP
 import android.view.MotionEvent.ACTION_UP
 import android.view.MotionEvent.TOOL_TYPE_MOUSE
@@ -590,15 +592,15 @@
             view,
             object : AccessibilityDelegateCompat() {
                 override fun onInitializeAccessibilityNodeInfo(
-                    host: View?,
-                    info: AccessibilityNodeInfoCompat?
+                    host: View,
+                    info: AccessibilityNodeInfoCompat
                 ) {
                     super.onInitializeAccessibilityNodeInfo(host, info)
                     var parentId = SemanticsNode(layoutNode.outerSemantics!!, false).parent!!.id
                     if (parentId == semanticsOwner.unmergedRootSemanticsNode.id) {
                         parentId = AccessibilityNodeProviderCompat.HOST_VIEW_ID
                     }
-                    info!!.setParent(thisView, parentId)
+                    info.setParent(thisView, parentId)
                 }
             }
         )
@@ -1016,6 +1018,14 @@
         if (autofillSupported()) _autofill?.performAutofill(values)
     }
 
+    override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
+        return if (event.actionMasked == ACTION_SCROLL) {
+            handleMotionEvent(event).dispatchedToAPointerInputModifier
+        } else {
+            super.dispatchGenericMotionEvent(event)
+        }
+    }
+
     // TODO(shepshapard): Test this method.
     override fun dispatchTouchEvent(motionEvent: MotionEvent): Boolean {
         if (hoverExitReceived) {
@@ -1142,11 +1152,21 @@
                 lastDownPointerPosition = it
             }
 
-            pointerInputEventProcessor.process(
+            val result = pointerInputEventProcessor.process(
                 pointerInputEvent,
                 this,
                 isInBounds(motionEvent)
             )
+            val action = motionEvent.actionMasked
+            if ((action == ACTION_DOWN || action == ACTION_POINTER_DOWN) &&
+                !result.dispatchedToAPointerInputModifier
+            ) {
+                // We aren't handling the pointer, so the event stream has ended for us.
+                // The next time we receive a pointer event, it should be considered a new
+                // pointer.
+                motionEventAdapter.endStream(motionEvent.getPointerId(motionEvent.actionIndex))
+            }
+            result
         } else {
             pointerInputEventProcessor.processCancel()
             ProcessResult(
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
index 64cd3cf..e413d5f 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
@@ -1238,7 +1238,7 @@
             AccessibilityNodeInfoCompat.ACTION_FOCUS -> {
                 if (node.unmergedConfig.getOrNull(SemanticsProperties.Focused) == false) {
                     node.layoutNode.outerLayoutNodeWrapper.findLastFocusWrapper()
-                        ?.requestFocus(propagateFocus = false) ?: return false
+                        ?.requestFocus() ?: return false
                     return true
                 } else {
                     return false
@@ -1545,7 +1545,7 @@
         sendEventForVirtualView(previousVirtualViewId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT)
     }
 
-    override fun getAccessibilityNodeProvider(host: View?): AccessibilityNodeProviderCompat {
+    override fun getAccessibilityNodeProvider(host: View): AccessibilityNodeProviderCompat {
         return nodeProvider
     }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
index 9e39112..086de49 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Modifier.kt
@@ -125,7 +125,7 @@
      *
      * @sample androidx.compose.ui.samples.ModifierParameterSample
      */
-    // The companion object implements `Modifier` so that it may be used  as the start of a
+    // The companion object implements `Modifier` so that it may be used as the start of a
     // modifier extension factory expression.
     companion object : Modifier {
         override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R = initial
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/TempListUtils.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/TempListUtils.kt
index 940317c..d5c4d7c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/TempListUtils.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/TempListUtils.kt
@@ -27,6 +27,10 @@
  * to each pair of two adjacent elements in this collection.
  *
  * The returned list is empty if this collection contains less than two elements.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastZipWithNext(transform: (T, T) -> R): List<R> {
@@ -50,6 +54,10 @@
  * Throws an exception if this collection is empty. If the collection can be empty in an expected
  * way, please use [reduceOrNull] instead. It returns `null` when its receiver is empty.
  *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
+ *
  * @param [operation] function that takes current accumulator value and an element,
  * and calculates the next accumulator value.
  */
@@ -71,6 +79,10 @@
  * If any of two pairs would have the same key the last one gets added to the map.
  *
  * The returned map preserves the entry iteration order of the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, K, V> List<T>.fastAssociate(transform: (T) -> Pair<K, V>): Map<K, V> {
@@ -86,6 +98,10 @@
  * Returns a list of values built from the elements of `this` collection and the [other] collection with the same index
  * using the provided [transform] function applied to each pair of elements.
  * The returned list has length of the shortest collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R, V> List<T>.fastZip(
@@ -104,6 +120,10 @@
 /**
  * Returns a list containing the results of applying the given [transform] function
  * to each element in the original collection.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastMapNotNull(transform: (T) -> R?): List<R> {
@@ -122,6 +142,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which case
  * only the first [limit] elements will be appended, followed by the [truncated] string (which
  * defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 internal fun <T> List<T>.fastJoinToString(
     separator: CharSequence = ", ",
@@ -142,6 +166,10 @@
  * If the collection could be huge, you can specify a non-negative value of [limit], in which
  * case only the first [limit] elements will be appended, followed by the [truncated] string
  * (which defaults to "...").
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 private fun <T, A : Appendable> List<T>.fastJoinTo(
     buffer: A,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
index b9c3df2..70c6454 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
@@ -70,7 +70,7 @@
      */
     val modifier: Modifier
         // TODO(b/168831247): return an empty Modifier when there are no focusable children.
-        get() = focusModifier
+        get() = Modifier.focusTarget(focusModifier)
 
     lateinit var layoutDirection: LayoutDirection
 
@@ -152,29 +152,29 @@
         if (destination == null) {
             // Check if we need to wrap around (no destination and a non-root item is focused)
             if (focusModifier.focusState.hasFocus && !focusModifier.focusState.isFocused) {
-                    // Next and Previous wraps around.
-                    return when (focusDirection) {
-                        Next, Previous -> {
-                            // Clear Focus to send focus the root node.
-                            // Wrap around by requesting focus for the root and then calling moveFocus.
-                            clearFocus(force = false)
+                // Next and Previous wraps around.
+                return when (focusDirection) {
+                    Next, Previous -> {
+                        // Clear Focus to send focus the root node.
+                        // Wrap around by requesting focus for the root and then calling moveFocus.
+                        clearFocus(force = false)
 
-                            if (focusModifier.focusState.isFocused) {
-                                moveFocus(focusDirection)
-                            } else {
-                                false
-                            }
+                        if (focusModifier.focusState.isFocused) {
+                            moveFocus(focusDirection)
+                        } else {
+                            false
                         }
-                        else -> false
                     }
+                    else -> false
+                }
             }
             return false
         }
 
         checkNotNull(destination.findParentFocusNode()) { "Move focus landed at the root." }
 
-        // If we found a potential next item, call requestFocus() to move focus to it.
-        destination.requestFocus(propagateFocus = false)
+        // If we found a potential next item, move focus to it.
+        destination.requestFocus()
         return true
     }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
index b96a96a..ef8a6da 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
@@ -42,9 +42,7 @@
     //  using this internal constructor.
     inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo
 ) : ModifierLocalConsumer,
-    ModifierLocalProvider<FocusProperties>,
     InspectorValueInfo(inspectorInfo) {
-
     // TODO(b/188684110): Move focusState and focusedChild to ModifiedFocusNode and make this
     //  modifier stateless.
     var focusState: FocusStateImpl = initialFocus
@@ -63,12 +61,6 @@
             focusNode.setUpdatedProperties(ModifierLocalFocusProperties.current)
         }
     }
-
-    override val key = ModifierLocalFocusProperties
-
-    // Writing the FocusProperties ModifierLocal so that any child focus modifiers don't read
-    // properties that were meant for this focus modifier.
-    override val value = DefaultFocusProperties
 }
 
 /**
@@ -85,7 +77,8 @@
  * @sample androidx.compose.ui.samples.FocusableSampleUsingLowerLevelFocusTarget
  */
 fun Modifier.focusTarget(): Modifier = composed(debugInspectorInfo { name = "focusTarget" }) {
-    remember { FocusModifier(Inactive).then(NoFocusListener) }
+    val focusModifier = remember { FocusModifier(Inactive) }
+    focusTarget(focusModifier)
 }
 
 /**
@@ -96,7 +89,17 @@
     ReplaceWith("focusTarget()", "androidx.compose.ui.focus.focusTarget")
 )
 fun Modifier.focusModifier(): Modifier = composed(debugInspectorInfo { name = "focusModifier" }) {
-    remember { FocusModifier(Inactive).then(NoFocusListener) }
+    val focusModifier = remember { FocusModifier(Inactive) }
+    focusTarget(focusModifier)
+}
+
+/**
+ * A helper function that allows you to pass in an instance of FocusModifier.
+ * This is only used internally, to set the root focus modifier or in tests where we need to set an
+ * initial focus state or inspect the focus modifier state after running some operation.
+ */
+internal fun Modifier.focusTarget(focusModifier: FocusModifier): Modifier {
+    return this.then(focusModifier).then(ResetFocusModifierLocals)
 }
 
 /**
@@ -107,11 +110,47 @@
 internal val ModifierLocalHasFocusEventListener = modifierLocalOf { false }
 
 /**
- * A modifier that updates the HasFocusEventListener modifier local value to false.
- * This is used after every focusModifier because the listeners that appeared before
- * are not applicable further down the hierarchy.
+ * The Focus Modifier reads the state of some Modifier Locals that are set by the parents. Consider
+ * the following example:
+ *
+ *     Box(
+ *         Modifier
+ *             .focusRequester(item1)
+ *             .onFocusChanged { ... }
+ *             .focusOrder { next = item2 }
+ *             .focusProperties { canFocus = false }
+ *             .focusTarget()          // focusModifier1
+ *     ) {
+ *         Box(
+ *             Modifier.focusTarget()  // focusModifier2
+ *         )
+ *     }
+ *
+ * Here, the focusRequester, onFocusChanged, focusOrder and focusProperties modifiers provide
+ * modifier local values that are intended for focusModifier1.
+ *
+ * We don't want these modifier locals to be read by focusModifier2.
+ *
+ * Add this modifier after every FocusModifier to reset all the focus related modifier locals, so
+ * that focus modifiers further down the tree do not read these values.
  */
-internal object NoFocusListener : ModifierLocalProvider<Boolean> {
-    override val key: ProvidableModifierLocal<Boolean> get() = ModifierLocalHasFocusEventListener
-    override val value: Boolean get() = false
-}
+internal val ResetFocusModifierLocals: Modifier = Modifier
+    // Reset the FocusProperties modifier local.
+    .then(
+        object : ModifierLocalProvider<FocusProperties> {
+            override val key: ProvidableModifierLocal<FocusProperties>
+                get() = ModifierLocalFocusProperties
+            override val value: FocusProperties
+                get() = DefaultFocusProperties
+        }
+
+    )
+    // Update the HasFocusEventListener modifier local value to false.
+    .then(
+        object : ModifierLocalProvider<Boolean> {
+            override val key: ProvidableModifierLocal<Boolean>
+                get() = ModifierLocalHasFocusEventListener
+            override val value: Boolean
+                get() = false
+        }
+    )
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
index 7f0d6f9..c5b77d3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
@@ -52,7 +52,7 @@
      */
     fun requestFocus() {
         check(focusRequesterNodes.isNotEmpty()) { focusRequesterNotInitialized }
-        focusRequesterNodes.forEach { it.findFocusNode()?.requestFocus(propagateFocus = false) }
+        focusRequesterNodes.forEach { it.findFocusNode()?.requestFocus() }
     }
 
     /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
index 6399c69..7de10b2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
@@ -27,44 +27,26 @@
 /**
  * Request focus for this node.
  *
- * @param propagateFocus Whether the focus should be propagated to the node's children.
- *
  * In Compose, the parent [FocusNode][ModifiedFocusNode] controls focus for its focusable
  * children. Calling this function will send a focus request to this
  * [FocusNode][ModifiedFocusNode]'s parent [FocusNode][ModifiedFocusNode].
  */
-internal fun ModifiedFocusNode.requestFocus(propagateFocus: Boolean = true) {
+internal fun ModifiedFocusNode.requestFocus() {
     when (focusState) {
         Active, Captured, Deactivated, DeactivatedParent -> {
             // There is no change in focus state, but we send a focus event to notify the user
             // that the focus request is completed.
             sendOnFocusEvent(focusState)
         }
-        ActiveParent -> {
-            val currentFocusedChild = focusedChild
-            requireNotNull(currentFocusedChild)
+        ActiveParent -> if (clearChildFocus()) grantFocus()
 
-            // We don't need to do anything if [propagateFocus] is true,
-            // since this subtree already has focus.
-            if (propagateFocus) {
-                sendOnFocusEvent(focusState)
-                return
-            }
-
-            if (currentFocusedChild.clearFocus()) {
-                grantFocus(propagateFocus)
-                focusedChild = null
-            }
-        }
         Inactive -> {
             val focusParent = findParentFocusNode()
-            if (focusParent == null) {
-                if (requestFocusForOwner()) {
-                    grantFocus(propagateFocus)
+                if (focusParent != null) {
+                    focusParent.requestFocusForChild(this)
+                } else if (requestFocusForOwner()) {
+                    grantFocus()
                 }
-            } else {
-                focusParent.requestFocusForChild(this, propagateFocus)
-            }
         }
     }
 }
@@ -150,30 +132,23 @@
          * If the node is [ActiveParent], we need to clear focus from the [Active] descendant
          * first, before clearing focus from this node.
          */
-        ActiveParent -> {
-            val currentFocusedChild = focusedChild
-            requireNotNull(currentFocusedChild)
-            currentFocusedChild.clearFocus(forcedClear).also { success ->
-                if (success) {
-                    focusState = Inactive
-                    focusedChild = null
-                }
-            }
+        ActiveParent -> if (clearChildFocus()) {
+            focusState = Inactive
+            true
+        } else {
+            false
         }
         /**
          * If the node is [DeactivatedParent], we need to clear focus from the [Active] descendant
          * first, before clearing focus from this node.
          */
-        DeactivatedParent -> {
-            val currentFocusedChild = focusedChild
-            requireNotNull(currentFocusedChild)
-            currentFocusedChild.clearFocus(forcedClear).also { success ->
-                if (success) {
-                    focusState = Deactivated
-                    focusedChild = null
-                }
-            }
+        DeactivatedParent -> if (clearChildFocus()) {
+            focusState = Deactivated
+            true
+        } else {
+            false
         }
+
         /**
          * If the node is [Captured], deny requests to clear focus, except for a forced clear.
          */
@@ -190,38 +165,34 @@
     }
 }
 
-/**
- * This function grants focus to this node.
- *
- * @param propagateFocus Whether the focus should be propagated to the node's children.
- *
- * Note: This function is private, and should only be called by a parent [ModifiedFocusNode] to
- * grant focus to one of its child [ModifiedFocusNode]s.
- */
-private fun ModifiedFocusNode.grantFocus(propagateFocus: Boolean) {
+// This function grants focus to this node.
+// Note: This is a private function that just changes the state of this node and does not affect any
+// other nodes in the hierarchy.
+private fun ModifiedFocusNode.grantFocus() {
+    // No Focused Children, or we don't want to propagate focus to children.
+    focusState = when (focusState) {
+        Inactive, Active, ActiveParent -> Active
+        Captured -> Captured
+        Deactivated, DeactivatedParent -> error("Granting focus to a deactivated node.")
+    }
+}
 
-    // TODO (b/144126570) use ChildFocusability.
-    //  For now we assume children get focus before parent).
+// This function grants focus to the specified child.
+// Note: This is a private function and should only be called by a parent to grant focus to one of
+// its child. It does not affect any other nodes in the hierarchy.
+private fun ModifiedFocusNode.grantFocusToChild(childNode: ModifiedFocusNode): Boolean {
+    childNode.grantFocus()
+    focusedChild = childNode
+    return true
+}
 
-    // TODO (b/144126759): Design a system to decide which child gets focus.
-    //  for now we grant focus to the first child.
-    val focusedCandidate = focusableChildren(excludeDeactivated = false).firstOrNull()
-
-    if (focusedCandidate == null || !propagateFocus) {
-        // No Focused Children, or we don't want to propagate focus to children.
-        focusState = when (focusState) {
-            Inactive, Active, ActiveParent -> Active
-            Captured -> Captured
-            Deactivated, DeactivatedParent -> error("Granting focus to a deactivated node.")
-        }
+// This function clears any focus from the focused child.
+private fun ModifiedFocusNode.clearChildFocus(): Boolean {
+    return if (requireNotNull(focusedChild).clearFocus()) {
+        focusedChild = null
+        true
     } else {
-        focusState = when (focusState) {
-            Inactive, Active, ActiveParent -> ActiveParent
-            Captured -> { Captured; return }
-            Deactivated, DeactivatedParent -> DeactivatedParent
-        }
-        focusedChild = focusedCandidate
-        focusedCandidate.grantFocus(propagateFocus)
+        false
     }
 }
 
@@ -230,61 +201,35 @@
  * focus.
  *
  * @param childNode: The node that is requesting focus.
- * @param propagateFocus Whether the focus should be propagated to the node's children.
  * @return true if focus was granted, false otherwise.
  */
-private fun ModifiedFocusNode.requestFocusForChild(
-    childNode: ModifiedFocusNode,
-    propagateFocus: Boolean
-): Boolean {
+private fun ModifiedFocusNode.requestFocusForChild(childNode: ModifiedFocusNode): Boolean {
 
     // Only this node's children can ask for focus.
     if (!focusableChildren(excludeDeactivated = false).contains(childNode)) {
         error("Non child node cannot request focus.")
     }
 
-    return when (focusState) {
+   return when (focusState) {
         /**
          * If this node is [Active], it can give focus to the requesting child.
          */
         Active -> {
             focusState = ActiveParent
-            focusedChild = childNode
-            childNode.grantFocus(propagateFocus)
-            true
+            grantFocusToChild(childNode)
         }
         /**
          * If this node is [ActiveParent] ie, one of the parent's descendants is [Active],
          * remove focus from the currently focused child and grant it to the requesting child.
          */
-        ActiveParent -> {
-            val previouslyFocusedNode = focusedChild
-            requireNotNull(previouslyFocusedNode)
-            if (previouslyFocusedNode.clearFocus()) {
-                focusedChild = childNode
-                childNode.grantFocus(propagateFocus)
-                true
-            } else {
-                // Currently focused component does not want to give up focus.
-                false
-            }
-        }
-        DeactivatedParent -> {
-            val previouslyFocusedNode = focusedChild
-            if (previouslyFocusedNode == null) {
-                // we use DeactivatedParent and focusedchild == null to indicate an intermediate
-                // state where a parent requested focus so that it can transfer it to a child.
-                focusedChild = childNode
-                childNode.grantFocus(propagateFocus)
-                true
-            } else if (previouslyFocusedNode.clearFocus()) {
-                focusedChild = childNode
-                childNode.grantFocus(propagateFocus)
-                true
-            } else {
-                // Currently focused component does not want to give up focus.
-                false
-            }
+        ActiveParent -> if (clearChildFocus()) grantFocusToChild(childNode) else false
+
+        DeactivatedParent -> when {
+            // DeactivatedParent && NoFocusChild is used to indicate an intermediate state where
+            // this parent requested focus so that it can transfer it to a child.
+            focusedChild == null -> grantFocusToChild(childNode)
+            clearChildFocus() -> grantFocusToChild(childNode)
+            else -> false
         }
         /**
          * If this node is not [Active], we must gain focus first before granting it
@@ -292,19 +237,18 @@
          */
         Inactive -> {
             val focusParent = findParentFocusNode()
-            if (focusParent == null) {
-                // If the owner successfully gains focus, proceed otherwise return false.
-                if (requestFocusForOwner()) {
+            when {
+                // If this node is the root, request focus from the compose owner.
+                focusParent == null && requestFocusForOwner() -> {
                     focusState = Active
-                    requestFocusForChild(childNode, propagateFocus)
-                } else {
-                    false
+                    requestFocusForChild(childNode)
                 }
-            } else if (focusParent.requestFocusForChild(this, propagateFocus = false)) {
-                requestFocusForChild(childNode, propagateFocus)
-            } else {
+                // For non-root nodes, request focus for this node before the child.
+                focusParent != null && focusParent.requestFocusForChild(this) ->
+                    requestFocusForChild(childNode)
+
                 // Could not gain focus, so have no focus to give.
-                false
+                else -> false
             }
         }
         /**
@@ -317,7 +261,7 @@
          */
         Deactivated -> {
             activateNode()
-            val childGrantedFocus = requestFocusForChild(childNode, propagateFocus)
+            val childGrantedFocus = requestFocusForChild(childNode)
             deactivateNode()
             childGrantedFocus
         }
@@ -325,7 +269,5 @@
 }
 
 private fun ModifiedFocusNode.requestFocusForOwner(): Boolean {
-    val owner = layoutNode.owner
-    requireNotNull(owner, { "Owner not initialized." })
-    return owner.requestFocus()
+    return layoutNode.owner?.requestFocus() ?: error("Owner not initialized.")
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/InternalPointerInput.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/InternalPointerInput.kt
index b0d20eb..4a64979 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/InternalPointerInput.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/InternalPointerInput.kt
@@ -47,7 +47,8 @@
     val down: Boolean,
     val type: PointerType,
     val issuesEnterExit: Boolean = false,
-    val historical: List<HistoricalChange> = mutableListOf()
+    val historical: List<HistoricalChange> = mutableListOf(),
+    val scrollDelta: Offset = Offset.Zero
 )
 
 /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
index 53e6827..34632aa 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.input.pointer.PointerEventPass.Initial
 import androidx.compose.ui.input.pointer.PointerEventPass.Main
 import androidx.compose.ui.layout.LayoutCoordinates
-import androidx.compose.ui.node.InternalCoreApi
 import androidx.compose.ui.unit.IntSize
 
 /**
@@ -108,7 +107,7 @@
 /**
  * Describes a pointer input change event that has occurred at a particular point in time.
  */
-expect class PointerEvent @OptIn(InternalCoreApi::class) internal constructor(
+expect class PointerEvent internal constructor(
     changes: List<PointerInputChange>,
     internalPointerEvent: InternalPointerEvent?
 ) {
@@ -263,7 +262,7 @@
 /**
  * The device type that produces a [PointerInputChange], such as a mouse or stylus.
  */
-inline class PointerType internal constructor(private val value: Int) {
+inline class PointerType private constructor(private val value: Int) {
 
     override fun toString(): String = when (value) {
         1 -> "Touch"
@@ -304,7 +303,7 @@
 /**
  * Indicates the primary reason that the [PointerEvent] was sent.
  */
-inline class PointerEventType(internal val value: Int) {
+inline class PointerEventType private constructor(internal val value: Int) {
     companion object {
         /**
          * An unknown reason for the event.
@@ -344,14 +343,25 @@
          * [Enter], [Exit], and [Enter] will be received.
          */
         val Exit = PointerEventType(5)
+
+        /**
+         * A scroll event was sent. This can happen, for example, due to a mouse scroll wheel.
+         * This event indicates that the [PointerInputChange.scrollDelta]'s [Offset] is non-zero.
+         */
+        @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET")
+        @ExperimentalComposeUiApi
+        @get:ExperimentalComposeUiApi
+        val Scroll = PointerEventType(6)
     }
 
+    @OptIn(ExperimentalComposeUiApi::class)
     override fun toString(): String = when (this) {
         Press -> "Press"
         Release -> "Release"
         Move -> "Move"
         Enter -> "Enter"
         Exit -> "Exit"
+        Scroll -> "Scroll"
         else -> "Unknown"
     }
 }
@@ -419,8 +429,41 @@
         get() = _historical ?: listOf()
     private var _historical: List<HistoricalChange>? = null
 
+    /**
+     * The amount of scroll wheel movement in the horizontal and vertical directions.
+     */
+    @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET")
     @ExperimentalComposeUiApi
-    constructor(
+    @get:ExperimentalComposeUiApi
+    val scrollDelta: Offset
+        get() = _scrollDelta
+    private var _scrollDelta: Offset = Offset.Zero
+
+    /**
+     * Indicates whether the change was consumed or not. Note that the change must be consumed in
+     * full as there's no partial consumption system provided.
+     */
+    @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET")
+    @ExperimentalComposeUiApi
+    @get:ExperimentalComposeUiApi
+    val isConsumed: Boolean
+        get() = consumed.downChange || consumed.positionChange
+
+    /**
+     * Consume change event, claiming all the corresponding change info to the caller. This is
+     * usually needed when, button, when being clicked, consumed the "up" event so no other parents
+     * of this button could consume this "up" again.
+     *
+     * "Consumption" is just an indication of the claim and each pointer input handler
+     * implementation must manually check this flag to respect it.
+     */
+    @ExperimentalComposeUiApi
+    fun consume() {
+        consumed.downChange = true
+        consumed.positionChange = true
+    }
+
+    internal constructor(
         id: PointerId,
         uptimeMillis: Long,
         position: Offset,
@@ -430,7 +473,8 @@
         previousPressed: Boolean,
         consumed: ConsumedData,
         type: PointerType,
-        historical: List<HistoricalChange>
+        historical: List<HistoricalChange>,
+        scrollDelta: Offset,
     ) : this(
         id,
         uptimeMillis,
@@ -443,6 +487,7 @@
         type
     ) {
         _historical = historical
+        _scrollDelta = scrollDelta
     }
 
     fun copy(
@@ -465,7 +510,8 @@
         previousPressed,
         consumed,
         type,
-        this.historical
+        this.historical,
+        this.scrollDelta
     )
 
     @ExperimentalComposeUiApi
@@ -490,7 +536,34 @@
         previousPressed,
         consumed,
         type,
-        historical
+        historical,
+        this.scrollDelta
+    )
+
+    internal fun copy(
+        id: PointerId = this.id,
+        currentTime: Long = this.uptimeMillis,
+        currentPosition: Offset = this.position,
+        currentPressed: Boolean = this.pressed,
+        previousTime: Long = this.previousUptimeMillis,
+        previousPosition: Offset = this.previousPosition,
+        previousPressed: Boolean = this.previousPressed,
+        consumed: ConsumedData = this.consumed,
+        type: PointerType = this.type,
+        historical: List<HistoricalChange> = this.historical,
+        scrollDelta: Offset
+    ): PointerInputChange = PointerInputChange(
+        id,
+        currentTime,
+        currentPosition,
+        currentPressed,
+        previousTime,
+        previousPosition,
+        previousPressed,
+        consumed,
+        type,
+        historical,
+        scrollDelta
     )
 
     override fun toString(): String {
@@ -503,7 +576,8 @@
             "previousPressed=$previousPressed, " +
             "consumed=$consumed, " +
             "type=$type, " +
-            "historical=$historical)"
+            "historical=$historical," +
+            "scrollDelta=$scrollDelta)"
     }
 }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessor.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessor.kt
index e5f1347..20cf960 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessor.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessor.kt
@@ -147,7 +147,8 @@
                     previousDown,
                     ConsumedData(),
                     it.type,
-                    it.historical
+                    it.historical,
+                    it.scrollDelta
                 )
             if (it.down) {
                 previousPointerInputData[it.id] = PointerInputData(
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 d3d6f92..3c08f7a 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
@@ -60,11 +60,8 @@
         }
     }
 
-    /**
-     * An initialization function that is called when the [LayoutNodeWrapper] is initially created,
-     * and also called when the [LayoutNodeWrapper] is re-used.
-     */
-    open fun onInitialize() {
+    override fun onInitialize() {
+        super.onInitialize()
         wrapped.wrappedBy = this
     }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedDrawNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DrawEntity.kt
similarity index 74%
rename from compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedDrawNode.kt
rename to compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DrawEntity.kt
index 3f8536f..aa8d3a2c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedDrawNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DrawEntity.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,13 +21,21 @@
 import androidx.compose.ui.draw.DrawModifier
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.Canvas
+import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.toSize
 
-internal class ModifiedDrawNode(
-    wrapped: LayoutNodeWrapper,
-    drawModifier: DrawModifier
-) : DelegatingLayoutNodeWrapper<DrawModifier>(wrapped, drawModifier), OwnerScope {
+internal class DrawEntity(
+    val layoutNodeWrapper: LayoutNodeWrapper,
+    val modifier: DrawModifier
+) : OwnerScope {
+    private val layoutNode: LayoutNode
+        get() = layoutNodeWrapper.layoutNode
+
+    private val size: IntSize
+        get() = layoutNodeWrapper.size
+
+    var next: DrawEntity? = null
 
     private var cacheDrawModifier: DrawCacheModifier? = updateCacheDrawModifier()
 
@@ -38,7 +46,7 @@
 
         override val layoutDirection: LayoutDirection get() = layoutNode.layoutDirection
 
-        override val size: Size get() = measuredSize.toSize()
+        override val size: Size get() = layoutNodeWrapper.size.toSize()
     }
 
     // Flag to determine if the cache should be re-built
@@ -71,30 +79,30 @@
         }
     }
 
-    override fun onInitialize() {
-        super.onInitialize()
+    fun onInitialize() {
         cacheDrawModifier = updateCacheDrawModifier()
         invalidateCache = true
+        next?.onInitialize()
     }
 
-    override fun onMeasureResultChanged(width: Int, height: Int) {
-        super.onMeasureResultChanged(width, height)
+    fun onMeasureResultChanged(width: Int, height: Int) {
         invalidateCache = true
+        next?.onMeasureResultChanged(width, height)
     }
 
     // This is not thread safe
-    override fun performDraw(canvas: Canvas) {
-        val size = measuredSize.toSize()
+    fun draw(canvas: Canvas) {
+        val size = size.toSize()
         if (cacheDrawModifier != null && invalidateCache) {
             layoutNode.requireOwner().snapshotObserver.observeReads(
                 this,
-                onCommitAffectingModifiedDrawNode,
+                onCommitAffectingDrawEntity,
                 updateCache
             )
         }
 
         val drawScope = layoutNode.mDrawScope
-        drawScope.draw(canvas, size, wrapped) {
+        drawScope.draw(canvas, size, layoutNodeWrapper, this) {
             with(drawScope) {
                 with(modifier) {
                     draw()
@@ -107,15 +115,15 @@
         // Callback invoked whenever a state parameter that is read within the cache
         // execution callback is updated. This marks the cache flag as dirty and
         // invalidates the current layer.
-        private val onCommitAffectingModifiedDrawNode: (ModifiedDrawNode) -> Unit =
-            { modifiedDrawNode ->
-                if (modifiedDrawNode.isValid) {
-                    modifiedDrawNode.invalidateCache = true
-                    modifiedDrawNode.invalidateLayer()
+        private val onCommitAffectingDrawEntity: (DrawEntity) -> Unit =
+            { drawEntity ->
+                if (drawEntity.isValid) {
+                    drawEntity.invalidateCache = true
+                    drawEntity.layoutNodeWrapper.invalidateLayer()
                 }
             }
     }
 
     override val isValid: Boolean
-        get() = isAttached
-}
\ No newline at end of file
+        get() = layoutNodeWrapper.isAttached
+}
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 ab6d3c9..71b3960 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
@@ -653,6 +653,8 @@
             val addedCallback = hasNewPositioningCallback()
             onPositionedCallbacks?.clear()
 
+            innerLayoutNodeWrapper.onInitialize()
+
             // Create a new chain of LayoutNodeWrappers, reusing existing ones from wrappers
             // when possible.
             val outerWrapper = modifier.foldOut(innerLayoutNodeWrapper) { mod, toWrap ->
@@ -660,6 +662,13 @@
                     mod.onRemeasurementAvailable(this)
                 }
 
+                if (mod is DrawModifier) {
+                    val drawEntity = DrawEntity(toWrap, mod)
+                    drawEntity.next = toWrap.drawEntityHead
+                    toWrap.drawEntityHead = drawEntity
+                    drawEntity.onInitialize()
+                }
+
                 // Re-use the layoutNodeWrapper if possible.
                 reuseLayoutNodeWrapper(mod, toWrap)?.let {
                     return@foldOut it
@@ -686,10 +695,6 @@
                         .initialize()
                         .assignChained(toWrap)
                 }
-                if (mod is DrawModifier) {
-                    wrapper = ModifiedDrawNode(wrapper, mod)
-                        .initialize()
-                }
                 if (mod is FocusModifier) {
                     wrapper = ModifiedFocusNode(wrapper, mod)
                         .initialize()
@@ -1176,8 +1181,23 @@
         val infoList = mutableVectorOf<ModifierInfo>()
         forEachDelegate { wrapper ->
             wrapper as DelegatingLayoutNodeWrapper<*>
-            val info = ModifierInfo(wrapper.modifier, wrapper, wrapper.layer)
+            val layer = wrapper.layer
+            val info = ModifierInfo(wrapper.modifier, wrapper, layer)
             infoList += info
+            var node = wrapper.drawEntityHead // head
+            while (node != null) {
+                infoList += ModifierInfo(node.modifier, wrapper, layer)
+                node = node.next
+            }
+        }
+        var innerNode = innerLayoutNodeWrapper.drawEntityHead
+        while (innerNode != null) {
+            infoList += ModifierInfo(
+                innerNode.modifier,
+                innerLayoutNodeWrapper,
+                innerLayoutNodeWrapper.layer
+            )
+            innerNode = innerNode.next
         }
         return infoList.asMutableList()
     }
@@ -1243,7 +1263,9 @@
     private fun copyWrappersToCache() {
         forEachDelegate {
             wrapperCache += it as DelegatingLayoutNodeWrapper<*>
+            it.drawEntityHead = null
         }
+        innerLayoutNodeWrapper.drawEntityHead = null
     }
 
     private fun markReusedModifiers(modifier: Modifier) {
@@ -1330,7 +1352,7 @@
         forEachDelegateIncludingInner {
             if (it.layer != null) {
                 return false
-            } else if (it is ModifiedDrawNode) {
+            } else if (it.drawEntityHead != null) {
                 return true
             }
         }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
index 8493379..de1893f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
@@ -36,27 +36,36 @@
     // draw calls for all composables.
     // As a result there could be thread safety concerns here for multi-threaded drawing
     // scenarios, generally a single ComponentDrawScope should be shared for a particular thread
-    private var wrapped: LayoutNodeWrapper? = null
+    private var drawEntity: DrawEntity? = null
 
     override fun drawContent() {
-        drawIntoCanvas { canvas -> wrapped?.draw(canvas) }
+        drawIntoCanvas { canvas ->
+            val drawEntity = drawEntity!!
+            val nextDrawEntity = drawEntity.next
+            if (nextDrawEntity != null) {
+                nextDrawEntity.draw(canvas)
+            } else {
+                drawEntity.layoutNodeWrapper.performDraw(canvas)
+            }
+        }
     }
 
     internal inline fun draw(
         canvas: Canvas,
         size: Size,
-        LayoutNodeWrapper: LayoutNodeWrapper,
+        layoutNodeWrapper: LayoutNodeWrapper,
+        drawEntity: DrawEntity,
         block: DrawScope.() -> Unit
     ) {
-        val previousWrapper = wrapped
-        wrapped = LayoutNodeWrapper
+        val previousDrawEntity = this.drawEntity
+        this.drawEntity = drawEntity
         canvasDrawScope.draw(
-            LayoutNodeWrapper.measureScope,
-            LayoutNodeWrapper.measureScope.layoutDirection,
+            layoutNodeWrapper.measureScope,
+            layoutNodeWrapper.measureScope.layoutDirection,
             canvas,
             size,
             block
         )
-        wrapped = previousWrapper
+        this.drawEntity = previousDrawEntity
     }
 }
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 7f82f7b..a240c7d 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
@@ -154,6 +154,7 @@
         }
         layoutNode.owner?.onLayoutChange(layoutNode)
         measuredSize = IntSize(width, height)
+        drawEntityHead?.onMeasureResultChanged(width, height)
     }
 
     var position: IntOffset = IntOffset.Zero
@@ -190,6 +191,11 @@
 
     private val snapshotObserver get() = layoutNode.requireOwner().snapshotObserver
 
+    /**
+     * The head of the DrawEntity linked list
+     */
+    var drawEntityHead: DrawEntity? = null
+
     protected inline fun performingMeasure(
         constraints: Constraints,
         block: () -> Placeable
@@ -214,6 +220,14 @@
     }
 
     /**
+     * An initialization function that is called when the [LayoutNodeWrapper] is initially created,
+     * and also called when the [LayoutNodeWrapper] is re-used.
+     */
+    open fun onInitialize() {
+        layer?.invalidate()
+    }
+
+    /**
      * Places the modified child.
      */
     /*@CallSuper*/
@@ -252,12 +266,23 @@
             val x = position.x.toFloat()
             val y = position.y.toFloat()
             canvas.translate(x, y)
-            performDraw(canvas)
+            drawContainedDrawModifiers(canvas)
             canvas.translate(-x, -y)
         }
     }
 
-    protected abstract fun performDraw(canvas: Canvas)
+    private fun drawContainedDrawModifiers(canvas: Canvas) {
+        val head = drawEntityHead
+        if (head == null) {
+            performDraw(canvas)
+        } else {
+            head.draw(canvas)
+        }
+    }
+
+    open fun performDraw(canvas: Canvas) {
+        wrapped?.draw(canvas)
+    }
 
     open fun onPlaced() {}
 
@@ -266,7 +291,7 @@
     override fun invoke(canvas: Canvas) {
         if (layoutNode.isPlaced) {
             snapshotObserver.observeReads(this, onCommitAffectingLayer) {
-                performDraw(canvas)
+                drawContainedDrawModifiers(canvas)
             }
             lastLayerDrawingWasSkipped = false
         } else {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
index 1bc1644..775bdd3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
@@ -256,6 +256,9 @@
 
     /**
      * Makes sure the passed [layoutNode] and its subtree is remeasured and has the final sizes.
+     *
+     * The node or some of the nodes in its subtree can still be kept unmeasured if they are
+     * not placed and don't affect the parent size. See [requestRemeasure] for details.
      */
     fun forceMeasureTheSubtree(layoutNode: LayoutNode) {
         // if there is nothing in `relayoutNodes` everything is remeasured.
@@ -273,8 +276,13 @@
                 remeasureAndRelayoutIfNeeded(child)
             }
 
-            // run recursively for the subtree.
-            forceMeasureTheSubtree(child)
+            // if the child is still in NeedsRemeasure state then this child remeasure wasn't
+            // needed. it can happen for example when this child is not placed and can't affect
+            // the parent size. we can skip the whole subtree.
+            if (child.layoutState != NeedsRemeasure) {
+                // run recursively for the subtree.
+                forceMeasureTheSubtree(child)
+            }
         }
 
         // if the child was resized during the remeasurement it could request a remeasure on
@@ -283,8 +291,6 @@
         if (layoutNode.layoutState == NeedsRemeasure && relayoutNodes.remove(layoutNode)) {
             remeasureAndRelayoutIfNeeded(layoutNode)
         }
-
-        require(layoutNode.layoutState != NeedsRemeasure)
     }
 
     /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNode.kt
index 8966754..6ab7e29 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNode.kt
@@ -27,7 +27,7 @@
 
     override fun onModifierChanged() {
         super.onModifierChanged()
-        if (isAttached) notifyConsumerOfChanges()
+        notifyConsumerOfChanges()
     }
 
     override fun attach() {
@@ -39,6 +39,10 @@
         get() = onModifierLocalRead(this)
 
     private fun notifyConsumerOfChanges() {
+        // If the node is not attached, we don't notify the consumers.
+        // Ultimately when the node is attached, this function will be called again.
+        if (!isAttached) return
+
         layoutNode.requireOwner().snapshotObserver.observeReads(this, onReadValuesChanged) {
             modifier.onModifierLocalsUpdated(this)
         }
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/ComposeScene.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/ComposeScene.desktop.kt
index 5ecc568..2a64b96 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/ComposeScene.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/ComposeScene.desktop.kt
@@ -47,7 +47,8 @@
     nativeEvent: Any?,
     type: PointerType,
     isMousePressed: Boolean,
-    pointerId: Long
+    pointerId: Long,
+    scrollDelta: Offset
 ): PointerInputEvent {
     return PointerInputEvent(
         eventType,
@@ -59,7 +60,8 @@
                 position,
                 position,
                 isMousePressed,
-                type
+                type,
+                scrollDelta = scrollDelta
             )
         ),
         nativeEvent as MouseEvent?
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeLayer.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeLayer.desktop.kt
index cd9aaf9..08c470d 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeLayer.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/awt/ComposeLayer.desktop.kt
@@ -19,8 +19,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.mouse.MouseScrollOrientation
-import androidx.compose.ui.input.mouse.MouseScrollUnit
 import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.input.pointer.PointerType
 import androidx.compose.ui.platform.PlatformComponent
@@ -267,19 +265,14 @@
 private fun ComposeScene.onMouseWheelEvent(
     density: Float,
     event: MouseWheelEvent
-) = with(event) {
-    sendPointerScrollEvent(
+) {
+    sendPointerEvent(
+        eventType = PointerEventType.Scroll,
         position = Offset(event.x.toFloat(), event.y.toFloat()) * density,
-        delta = if (scrollType == MouseWheelEvent.WHEEL_BLOCK_SCROLL) {
-            MouseScrollUnit.Page((scrollAmount * preciseWheelRotation).toFloat())
+        scrollDelta = if (event.isShiftDown) {
+            Offset(event.preciseWheelRotation.toFloat(), 0f)
         } else {
-            MouseScrollUnit.Line((scrollAmount * preciseWheelRotation).toFloat())
-        },
-        // There are no other way to detect horizontal scrolling in AWT
-        orientation = if (isShiftDown) {
-            MouseScrollOrientation.Horizontal
-        } else {
-            MouseScrollOrientation.Vertical
+            Offset(0f, event.preciseWheelRotation.toFloat())
         },
         timeMillis = event.`when`,
         type = PointerType.Mouse,
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.desktop.kt
index 309be44..2c74cda 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.desktop.kt
@@ -46,7 +46,10 @@
     internal actual constructor(
         changes: List<PointerInputChange>,
         internalPointerEvent: InternalPointerEvent?
-    ) : this(changes, internalPointerEvent?.mouseEvent) {
+    ) : this(
+        changes,
+        internalPointerEvent?.mouseEvent
+    ) {
         this.type = internalPointerEvent?.type ?: PointerEventType.Unknown
     }
 
@@ -57,7 +60,10 @@
     /**
      * @param changes The changes.
      */
-    actual constructor(changes: List<PointerInputChange>) : this(changes, mouseEvent = null)
+    actual constructor(changes: List<PointerInputChange>) : this(
+        changes,
+        mouseEvent = null
+    )
 
     actual var type: PointerEventType = PointerEventType.Unknown
         internal set
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
index 4eb942b..fc04147 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
@@ -24,6 +24,8 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.input.mouse.MouseScrollEvent
+import androidx.compose.ui.input.mouse.MouseScrollOrientation
+import androidx.compose.ui.input.mouse.MouseScrollUnit
 import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.node.RootForTest
 import androidx.compose.ui.unit.Constraints
@@ -34,7 +36,11 @@
 import org.jetbrains.skia.Surface
 import org.jetbrains.skiko.FrameDispatcher
 import java.awt.Component
+import java.awt.event.MouseWheelEvent
 import kotlin.coroutines.CoroutineContext
+import kotlin.math.abs
+import kotlin.math.roundToInt
+import kotlin.math.sign
 
 /**
  * A virtual window for testing purposes.
@@ -115,10 +121,36 @@
      */
     @OptIn(ExperimentalComposeUiApi::class)
     fun onMouseScroll(x: Int, y: Int, event: MouseScrollEvent) {
-        scene.sendPointerScrollEvent(
+        val delta = when (event.delta) {
+            is MouseScrollUnit.Line -> event.delta.value
+            is MouseScrollUnit.Page -> event.delta.value
+        }
+        val wheelRotation = sign(delta)
+        scene.sendPointerEvent(
+            eventType = PointerEventType.Scroll,
             position = Offset(x.toFloat(), y.toFloat()),
-            delta = event.delta,
-            orientation = event.orientation
+            scrollDelta = if (event.orientation == MouseScrollOrientation.Vertical) {
+                Offset(0f, wheelRotation)
+            } else {
+                Offset(wheelRotation, 0f)
+            },
+            nativeEvent = MouseWheelEvent(
+                EventComponent,
+                MouseWheelEvent.MOUSE_WHEEL,
+                0,
+                0,
+                0,
+                0,
+                0,
+                false,
+                if (event.delta is MouseScrollUnit.Line) {
+                    MouseWheelEvent.WHEEL_UNIT_SCROLL
+                } else {
+                    MouseWheelEvent.WHEEL_BLOCK_SCROLL
+                },
+                abs(delta.roundToInt()),
+                wheelRotation.roundToInt()
+            )
         )
     }
 
diff --git a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/ComposeScene.skiko.kt b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/ComposeScene.skiko.kt
index f3a83bd..c358016 100644
--- a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/ComposeScene.skiko.kt
+++ b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/ComposeScene.skiko.kt
@@ -28,9 +28,6 @@
 import androidx.compose.runtime.withFrameNanos
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.key.KeyEvent as ComposeKeyEvent
-import androidx.compose.ui.input.mouse.MouseScrollEvent
-import androidx.compose.ui.input.mouse.MouseScrollOrientation
-import androidx.compose.ui.input.mouse.MouseScrollUnit
 import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.input.pointer.PointerInputEvent
 import androidx.compose.ui.input.pointer.PointerType
@@ -346,6 +343,7 @@
      *
      * @param eventType Indicates the primary reason that the event was sent.
      * @param position The [Offset] of the current pointer event, relative to the content.
+     * @param scrollDelta scroll delta for the PointerEventType.Scroll event
      * @param timeMillis The time of the current pointer event, in milliseconds. The start (`0`) time
      * is platform-dependent.
      * @param type The device type that produced the event, such as [mouse][PointerType.Mouse],
@@ -356,6 +354,7 @@
     fun sendPointerEvent(
         eventType: PointerEventType,
         position: Offset,
+        scrollDelta: Offset = Offset(0f, 0f),
         timeMillis: Long = System.nanoTime() / 1_000_000L,
         type: PointerType = PointerType.Mouse,
         nativeEvent: Any? = null,
@@ -369,7 +368,14 @@
             PointerEventType.Release -> isMousePressed = false
         }
         val event = pointerInputEvent(
-            eventType, position, timeMillis, nativeEvent, type, isMousePressed, pointerId
+            eventType,
+            position,
+            timeMillis,
+            nativeEvent,
+            type,
+            isMousePressed,
+            pointerId,
+            scrollDelta
         )
         when (eventType) {
             PointerEventType.Press -> onMousePressed(event)
@@ -380,56 +386,10 @@
             }
             PointerEventType.Enter -> hoveredOwner?.processPointerInput(event)
             PointerEventType.Exit -> hoveredOwner?.processPointerInput(event)
+            PointerEventType.Scroll -> hoveredOwner?.processPointerInput(event)
         }
     }
 
-    // TODO(demin): remove/change when we will have scroll event support in the common code
-    // TODO(demin): return Boolean (when it is consumed).
-    //  see ComposeLayer todo about AWTDebounceEventQueue
-    /**
-     * Send pointer scroll event to the content.
-     *
-     * @param position The [Offset] of the current pointer event, relative to the content
-     * @param delta Change of mouse scroll.
-     * Positive if scrolling down, negative if scrolling up.
-     * @param orientation Orientation in which scrolling event occurs.
-     * Up/down wheel scrolling causes events in vertical orientation.
-     * Left/right wheel scrolling causes events in horizontal orientation.
-     * @param timeMillis The time of the current pointer event, in milliseconds. The start (`0`) time
-     * is platform-dependent.
-     * @param type The device type that produced the event, such as [mouse][PointerType.Mouse],
-     * or [touch][PointerType.Touch].
-     * @param nativeEvent The original native event
-     */
-    @OptIn(ExperimentalComposeUiApi::class)
-    @Suppress("UNUSED_PARAMETER")
-    @ExperimentalComposeUiApi // it is more experimental than ComposeScene itself
-    fun sendPointerScrollEvent(
-        position: Offset,
-        delta: MouseScrollUnit,
-        orientation: MouseScrollOrientation = MouseScrollOrientation.Vertical,
-        timeMillis: Long = System.nanoTime() / 1_000_000L,
-        type: PointerType = PointerType.Mouse,
-        nativeEvent: Any? = null,
-//        buttons: PointerButtons? = null,
-//        keyboardModifiers: PointerKeyboardModifiers? = null,
-    ): Unit = postponeInvalidation {
-        check(!isDisposed) { "ComposeScene is disposed" }
-        hoveredOwner?.onMouseScroll(
-            position,
-            MouseScrollEvent(delta, orientation),
-            pointerInputEvent = pointerInputEvent(
-                PointerEventType.Unknown,
-                position,
-                timeMillis,
-                nativeEvent,
-                type,
-                isMousePressed,
-                pointerId
-            )
-        )
-    }
-
     private fun onMousePressed(event: PointerInputEvent) {
         val currentOwner = hoveredOwner
         if (currentOwner != null) {
@@ -471,5 +431,6 @@
     nativeEvent: Any?,
     type: PointerType,
     isMousePressed: Boolean,
-    pointerId: Long
+    pointerId: Long,
+    scrollDelta: Offset
 ): PointerInputEvent
diff --git a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilter.skiko.kt b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilter.skiko.kt
index 4cce567..cf9d2a0 100644
--- a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilter.skiko.kt
+++ b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/input/mouse/MouseScrollFilter.skiko.kt
@@ -18,15 +18,14 @@
 
 package androidx.compose.ui.input.mouse
 
-import androidx.compose.runtime.remember
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.input.pointer.PointerInputModifier
-import androidx.compose.ui.input.pointer.PointerEvent
-import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.PointerInputFilter
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.PointerType
+import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.unit.IntSize
+import java.awt.event.MouseWheelEvent
 
 /**
  * Indicates distance by which we should scroll some container.
@@ -78,6 +77,10 @@
     val orientation: MouseScrollOrientation
 )
 
+// TODO(demin): how easy-to-use scroll API should look like?
+//  maybe something like Modifier.pointerScroll { delta: Offset -> } ?
+//  or Modifier.pointerInput(Unit) { scroll { delta: Offset ->  } }
+//  ?
 /**
  * Adding this [modifier][Modifier] to the [modifier][Modifier] parameter of a component will
  * allow it to intercept scroll events from mouse wheel and touchpad.
@@ -100,31 +103,40 @@
          */
         bounds: IntSize
     ) -> Boolean
-): Modifier = composed {
-    val filter = remember(::MouseScrollEventFilter)
-    filter.onMouseScroll = onMouseScroll
-    MousePointerInputModifierImpl(filter)
-}
-
-internal class MouseScrollEventFilter : PointerInputFilter() {
-    lateinit var onMouseScroll: (MouseScrollEvent, IntSize) -> Boolean
-
-    override fun onPointerEvent(
-        pointerEvent: PointerEvent,
-        pass: PointerEventPass,
-        bounds: IntSize
-    ) = Unit
-
-    override fun onCancel() = Unit
-
-    fun onMouseScroll(event: MouseScrollEvent): Boolean {
-        return isAttached && onMouseScroll(event, size)
+): Modifier = pointerInput(onMouseScroll) {
+    awaitPointerEventScope {
+        while (true) {
+            val event = awaitPointerEvent()
+            val mouseEvent = (event.mouseEvent as? MouseWheelEvent) ?: continue
+            val mouseChange = event.changes.find { it.type == PointerType.Mouse }
+            val isScroll = event.type == PointerEventType.Scroll
+            if (isScroll && mouseChange != null && !mouseChange.isConsumed) {
+                val legacyEvent = mouseEvent.toLegacyEvent(mouseChange.scrollDelta)
+                if (onMouseScroll(legacyEvent, size)) {
+                    mouseChange.consume()
+                }
+            }
+        }
     }
 }
 
-private data class MousePointerInputModifierImpl(
-    override val pointerInputFilter: PointerInputFilter
-) : PointerInputModifier
+private fun MouseWheelEvent.toLegacyEvent(scrollDelta: Offset): MouseScrollEvent {
+    val value = if (scrollDelta.x != 0f) scrollDelta.x else scrollDelta.y
+    return MouseScrollEvent(
+        delta = if (scrollType == MouseWheelEvent.WHEEL_BLOCK_SCROLL) {
+            MouseScrollUnit.Page(value * scrollAmount)
+        } else {
+            MouseScrollUnit.Line(value * scrollAmount)
+        },
+
+        // There are no other way to detect horizontal scrolling in AWT
+        orientation = if (isShiftDown || scrollDelta.x != 0f) {
+            MouseScrollOrientation.Horizontal
+        } else {
+            MouseScrollOrientation.Vertical
+        }
+    )
+}
 
 @ExperimentalComposeUiApi
 enum class MouseScrollOrientation {
diff --git a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
index a3d80e6..9f68c30 100644
--- a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
+++ b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
@@ -47,20 +47,16 @@
 import androidx.compose.ui.input.key.isShiftPressed
 import androidx.compose.ui.input.key.key
 import androidx.compose.ui.input.key.type
-import androidx.compose.ui.input.mouse.MouseScrollEvent
-import androidx.compose.ui.input.mouse.MouseScrollEventFilter
 import androidx.compose.ui.input.pointer.PointerEventType
 import androidx.compose.ui.input.pointer.PointerIcon
 import androidx.compose.ui.input.pointer.PointerIconDefaults
 import androidx.compose.ui.input.pointer.PointerIconService
 import androidx.compose.ui.input.pointer.PointerInputEvent
 import androidx.compose.ui.input.pointer.PointerInputEventProcessor
-import androidx.compose.ui.input.pointer.PointerInputFilter
 import androidx.compose.ui.input.pointer.PositionCalculator
 import androidx.compose.ui.input.pointer.ProcessResult
 import androidx.compose.ui.input.pointer.TestPointerInputEventData
 import androidx.compose.ui.layout.RootMeasurePolicy
-import androidx.compose.ui.node.HitTestResult
 import androidx.compose.ui.node.InternalCoreApi
 import androidx.compose.ui.node.LayoutNode
 import androidx.compose.ui.node.LayoutNodeDrawScope
@@ -405,31 +401,6 @@
         )
     }
 
-    // TODO(demin): This is likely temporary. After PointerInputEvent can handle mouse events
-    //  (scroll in particular), we can replace it with processPointerInput. see b/166105940
-    internal fun onMouseScroll(
-        position: Offset,
-        event: MouseScrollEvent,
-        pointerInputEvent: PointerInputEvent
-    ) {
-        measureAndLayout()
-        sendSyntheticEvents()
-        lastPointerEvent = pointerInputEvent
-
-        val inputFilters = HitTestResult<PointerInputFilter>()
-        root.hitTest(position, inputFilters)
-
-        for (
-            filter in inputFilters
-                .asReversed()
-                .asSequence()
-                .filterIsInstance<MouseScrollEventFilter>()
-        ) {
-            val isConsumed = filter.onMouseScroll(event)
-            if (isConsumed) break
-        }
-    }
-
     override val pointerIconService: PointerIconService =
         object : PointerIconService {
             override var current: PointerIcon
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/focus/FocusManagerTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/focus/FocusManagerTest.kt
index 0ee1040..07b9430 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/focus/FocusManagerTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/focus/FocusManagerTest.kt
@@ -30,7 +30,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
-import kotlin.jvm.JvmStatic
 
 @RunWith(Parameterized::class)
 class FocusManagerTest(private val initialFocusState: FocusState) {
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
index 353cc36..d2ca364 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/PointerInputTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.ui.input.pointer
 
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.geometry.Offset
 import com.google.common.truth.FailureMetadata
 import com.google.common.truth.Subject
@@ -347,6 +348,16 @@
         assertThat(pointerInputChange.anyChangeConsumed()).isFalse()
     }
 
+    @OptIn(ExperimentalComposeUiApi::class)
+    @Test
+    fun consume_noChanges_returnsTrue() {
+        val pointerInputChange =
+            createPointerInputChange(8f, 16f, true, 8f, 16f, true, 0f, 0f, false)
+        pointerInputChange.consume()
+        assertThat(pointerInputChange.isConsumed).isTrue()
+        assertThat(pointerInputChange.anyChangeConsumed()).isTrue()
+    }
+
     @Test
     fun anyChangeConsumed_downConsumed_returnsTrue() {
         val pointerInputChange =
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index 7475387..6c5a986 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -681,8 +681,8 @@
     @Test
     fun coordinatesAttachedWhenLayoutNodeAttached() {
         val layoutNode = LayoutNode()
-        val drawModifier = Modifier.drawBehind { }
-        layoutNode.modifier = drawModifier
+        val layoutModifier = Modifier.graphicsLayer { }
+        layoutNode.modifier = layoutModifier
         assertFalse(layoutNode.coordinates.isAttached)
         assertFalse(layoutNode.coordinates.isAttached)
         layoutNode.attach(MockOwner())
@@ -697,16 +697,16 @@
     @Test
     fun layoutNodeWrapperSameWithReplacementModifier() {
         val layoutNode = LayoutNode()
-        val drawModifier = Modifier.drawBehind { }
+        val layoutModifier = Modifier.graphicsLayer { }
 
-        layoutNode.modifier = drawModifier
+        layoutNode.modifier = layoutModifier
         val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertFalse(oldLayoutNodeWrapper.isAttached)
 
         layoutNode.attach(MockOwner())
         assertTrue(oldLayoutNodeWrapper.isAttached)
 
-        layoutNode.modifier = Modifier.drawBehind { }
+        layoutNode.modifier = Modifier.graphicsLayer { }
         val newLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertSame(newLayoutNodeWrapper, oldLayoutNodeWrapper)
     }
@@ -741,9 +741,9 @@
     @Test
     fun layoutNodeWrapperAttachedWhenLayoutNodeAttached() {
         val layoutNode = LayoutNode()
-        val drawModifier = Modifier.drawBehind { }
+        val layoutModifier = Modifier.graphicsLayer { }
 
-        layoutNode.modifier = drawModifier
+        layoutNode.modifier = layoutModifier
         val oldLayoutNodeWrapper = layoutNode.outerLayoutNodeWrapper
         assertFalse(oldLayoutNodeWrapper.isAttached)
 
@@ -760,8 +760,8 @@
     fun layoutNodeWrapperParentLayoutCoordinates() {
         val layoutNode = LayoutNode()
         val layoutNode2 = LayoutNode()
-        val drawModifier = Modifier.drawBehind { }
-        layoutNode.modifier = drawModifier
+        val layoutModifier = Modifier.graphicsLayer { }
+        layoutNode.modifier = layoutModifier
         layoutNode2.insertAt(0, layoutNode)
         layoutNode2.attach(MockOwner())
 
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNodeTest.kt
new file mode 100644
index 0000000..4cc4663
--- /dev/null
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerNodeTest.kt
@@ -0,0 +1,358 @@
+/*
+ * 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.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.autofill.Autofill
+import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.focus.FocusManager
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Canvas
+import androidx.compose.ui.hapticfeedback.HapticFeedback
+import androidx.compose.ui.input.InputModeManager
+import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.input.pointer.PointerIconService
+import androidx.compose.ui.modifier.modifierLocalConsumer
+import androidx.compose.ui.modifier.modifierLocalOf
+import androidx.compose.ui.modifier.modifierLocalProvider
+import androidx.compose.ui.platform.AccessibilityManager
+import androidx.compose.ui.platform.ClipboardManager
+import androidx.compose.ui.platform.TextToolbar
+import androidx.compose.ui.platform.ViewConfiguration
+import androidx.compose.ui.platform.WindowInfo
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.input.TextInputService
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalComposeUiApi::class)
+@RunWith(JUnit4::class)
+class ModifierLocalConsumerNodeTest {
+
+    private val default = "Default"
+    private val ModifierLocalString = modifierLocalOf { "Default" }
+
+    private val owner = FakeOwner()
+    private val layoutNode = LayoutNode()
+
+    @Test
+    fun `unattached modifier local consumer does not invoke lambda`() {
+        // Arrange.
+        var receivedValue = ""
+        TestBox(Modifier.modifierLocalConsumer { receivedValue = ModifierLocalString.current })
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    @Test
+    fun `attached modifier local consumer with no provider reads default value`() {
+        // Arrange.
+        lateinit var receivedValue: String
+        TestBox(Modifier.modifierLocalConsumer { receivedValue = ModifierLocalString.current })
+
+        // Act.
+        attach()
+
+        // Assert.
+        assertThat(receivedValue).isEqualTo(default)
+    }
+
+    @Test
+    fun `changing the consumer modifier with no provider reads default value`() {
+        // Arrange.
+        lateinit var receivedValue: String
+        TestBox(Modifier.modifierLocalConsumer { receivedValue = ModifierLocalString.current })
+        attach()
+        receivedValue = ""
+
+        // Act.
+        changeModifier(Modifier.modifierLocalConsumer {
+            receivedValue = ModifierLocalString.current
+        })
+
+        // Assert.
+        assertThat(receivedValue).isEqualTo(default)
+    }
+
+    @Test
+    fun `detached modifier local consumer with no provider does not invoke lambda`() {
+        // Arrange.
+        lateinit var receivedValue: String
+        TestBox(Modifier.modifierLocalConsumer { receivedValue = ModifierLocalString.current })
+        attach()
+        receivedValue = ""
+
+        // Act.
+        detach()
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    @Test
+    fun `unattached modifier local consumer with provider does not invoke lambda`() {
+        // Arrange.
+        var receivedValue = ""
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { "Initial Value" }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    @Test
+    fun `attached modifier local consumer with provider reads provided value`() {
+        // Arrange.
+        val providedValue = "Provided Value"
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { providedValue }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        // Act.
+        attach()
+
+        // Assert.
+        assertThat(receivedValue).isEqualTo(providedValue)
+    }
+
+    @Test
+    fun `changing provided value causes consumer to receive new provided value`() {
+        // Arrange.
+        val initialValue = "Initial Value"
+        val finalValue = "Final Value"
+        var providedValue by mutableStateOf(initialValue)
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { providedValue }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        attach()
+
+        // Act.
+        Snapshot.withMutableSnapshot {
+            providedValue = finalValue
+        }
+
+        // Assert.
+        assertThat(receivedValue).isEqualTo(finalValue)
+    }
+
+    @Test
+    fun `changing provided value after detaching modifier does not invoke consumer lambda`() {
+        // Arrange.
+        val initialValue = "Initial Value"
+        val finalValue = "Final Value"
+        var providedValue by mutableStateOf(initialValue)
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { providedValue }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        attach()
+        detach()
+        receivedValue = ""
+
+        // Act.
+        Snapshot.withMutableSnapshot {
+            providedValue = finalValue
+        }
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    @Test
+    fun `changing modifiers after detaching modifier does not invoke consumer lambda`() {
+        // Arrange.
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { "Provided Value" }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        attach()
+        detach()
+        receivedValue = ""
+
+        // Act.
+        changeModifier(Modifier.modifierLocalConsumer {
+            receivedValue = ModifierLocalString.current
+        })
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    @Test
+    fun `changing the consumer modifier with provider reads provided value`() {
+        // Arrange.
+        val providedValue = "Provided Value"
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { providedValue }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        attach()
+        receivedValue = ""
+
+        // Act.
+        changeModifier(
+            Modifier
+                .modifierLocalProvider(ModifierLocalString) { providedValue }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+
+        // Assert.
+        assertThat(receivedValue).isEqualTo(providedValue)
+    }
+
+    @Test
+    fun `detached modifier local consumer with provider does not invoke lambda`() {
+        // Arrange.
+        lateinit var receivedValue: String
+        TestBox(
+            modifier = Modifier
+                .modifierLocalProvider(ModifierLocalString) { "Provided Value" }
+                .modifierLocalConsumer { receivedValue = ModifierLocalString.current }
+        )
+        attach()
+        receivedValue = ""
+
+        // Act.
+        detach()
+
+        // Assert.
+        assertThat(receivedValue).isEmpty()
+    }
+
+    private fun TestBox(modifier: Modifier = Modifier) {
+        owner.snapshotObserver.startObserving()
+        layoutNode.modifier = modifier
+    }
+
+    private fun attach() {
+        layoutNode.attach(owner)
+    }
+
+    private fun detach() {
+        layoutNode.detach()
+    }
+
+    private fun changeModifier(modifier: Modifier) {
+        with(layoutNode) {
+            if (isAttached) { forEachLayoutNodeWrapper { it.detach() } }
+            this.modifier = modifier
+            if (isAttached) { forEachLayoutNodeWrapper { it.attach() } }
+        }
+    }
+
+    @OptIn(ExperimentalComposeUiApi::class)
+    private class FakeOwner : Owner {
+        @OptIn(InternalCoreApi::class)
+        override var showLayoutBounds: Boolean = false
+        override val snapshotObserver: OwnerSnapshotObserver = OwnerSnapshotObserver { it.invoke() }
+        override fun onRequestMeasure(layoutNode: LayoutNode) {}
+        override fun onAttach(node: LayoutNode) = node.forEachLayoutNodeWrapper { it.attach() }
+        override fun onDetach(node: LayoutNode) = node.forEachLayoutNodeWrapper { it.detach() }
+
+        override val root: LayoutNode
+            get() = TODO("Not yet implemented")
+        override val sharedDrawScope: LayoutNodeDrawScope
+            get() = TODO("Not yet implemented")
+        override val rootForTest: RootForTest
+            get() = TODO("Not yet implemented")
+        override val hapticFeedBack: HapticFeedback
+            get() = TODO("Not yet implemented")
+        override val inputModeManager: InputModeManager
+            get() = TODO("Not yet implemented")
+        override val clipboardManager: ClipboardManager
+            get() = TODO("Not yet implemented")
+        override val accessibilityManager: AccessibilityManager
+            get() = TODO("Not yet implemented")
+        override val textToolbar: TextToolbar
+            get() = TODO("Not yet implemented")
+        override val density: Density
+            get() = TODO("Not yet implemented")
+        override val textInputService: TextInputService
+            get() = TODO("Not yet implemented")
+        override val pointerIconService: PointerIconService
+            get() = TODO("Not yet implemented")
+        override val focusManager: FocusManager
+            get() = TODO("Not yet implemented")
+        override val windowInfo: WindowInfo
+            get() = TODO("Not yet implemented")
+        override val fontLoader: Font.ResourceLoader
+            get() = TODO("Not yet implemented")
+        override val layoutDirection: LayoutDirection
+            get() = TODO("Not yet implemented")
+        override val measureIteration: Long
+            get() = TODO("Not yet implemented")
+        override val viewConfiguration: ViewConfiguration
+            get() = TODO("Not yet implemented")
+        override val autofillTree: AutofillTree
+            get() = TODO("Not yet implemented")
+        override val autofill: Autofill
+            get() = TODO("Not yet implemented")
+
+        override fun createLayer(drawBlock: (Canvas) -> Unit, invalidateParentLayer: () -> Unit) =
+            TODO("Not yet implemented")
+        override fun onRequestRelayout(layoutNode: LayoutNode) =
+            TODO("Not yet implemented")
+        override fun calculatePositionInWindow(localPosition: Offset) =
+            TODO("Not yet implemented")
+        override fun calculateLocalPosition(positionInWindow: Offset) =
+            TODO("Not yet implemented")
+        override fun requestFocus() =
+            TODO("Not yet implemented")
+        override fun measureAndLayout(sendPointerUpdate: Boolean) =
+            TODO("Not yet implemented")
+        override fun forceMeasureTheSubtree(layoutNode: LayoutNode) =
+            TODO("Not yet implemented")
+        override fun onSemanticsChange() =
+            TODO("Not yet implemented")
+        override fun onLayoutChange(layoutNode: LayoutNode) =
+            TODO("Not yet implemented")
+        override fun getFocusDirection(keyEvent: KeyEvent) =
+            TODO("Not yet implemented")
+    }
+}
+
+private fun LayoutNode.forEachLayoutNodeWrapper(action: (LayoutNodeWrapper) -> Unit) {
+    var layoutNodeWrapper: LayoutNodeWrapper? = outerLayoutNodeWrapper
+    while (layoutNodeWrapper != null) {
+        action.invoke(layoutNodeWrapper)
+        layoutNodeWrapper = layoutNodeWrapper.wrapped
+    }
+}
diff --git a/coordinatorlayout/coordinatorlayout/build.gradle b/coordinatorlayout/coordinatorlayout/build.gradle
index 569b8bf..e883702 100644
--- a/coordinatorlayout/coordinatorlayout/build.gradle
+++ b/coordinatorlayout/coordinatorlayout/build.gradle
@@ -8,7 +8,7 @@
 
 dependencies {
     api("androidx.annotation:annotation:1.1.0")
-    api("androidx.core:core:1.3.0-beta01")
+    api("androidx.core:core:1.3.0")
     implementation("androidx.collection:collection:1.0.0")
     api("androidx.customview:customview:1.0.0")
 
diff --git a/core/OWNERS b/core/OWNERS
index cb02012..3a3ca6d 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -16,5 +16,5 @@
 siyamed@google.com
 
 # For shortcut related files
-mett@google.com
+sunnygoyal@google.com
 pinyaoting@google.com
diff --git a/core/core-google-shortcuts/build.gradle b/core/core-google-shortcuts/build.gradle
index e27488b..1931126 100644
--- a/core/core-google-shortcuts/build.gradle
+++ b/core/core-google-shortcuts/build.gradle
@@ -31,10 +31,12 @@
 }
 
 dependencies {
-    api("androidx.core:core:1.6.0-rc01")
+    api("androidx.core:core:1.7.0")
 
     implementation("com.google.firebase:firebase-appindexing:20.0.0")
     implementation("com.google.crypto.tink:tink-android:1.5.0")
+    implementation project(":appsearch:appsearch")
+    implementation project(":appsearch:appsearch-builtin-types")
 
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
@@ -46,6 +48,7 @@
     androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
     androidTestImplementation(libs.truth)
     androidTestImplementation(libs.multidex)
+    androidTestImplementation("junit:junit:4.13")
 }
 
 androidx {
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImplTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImplTest.java
index 63d6a76..70c3bf5 100644
--- a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImplTest.java
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImplTest.java
@@ -30,6 +30,7 @@
 import androidx.core.google.shortcuts.builders.CapabilityBuilder;
 import androidx.core.google.shortcuts.builders.ParameterBuilder;
 import androidx.core.google.shortcuts.builders.ShortcutBuilder;
+import androidx.core.google.shortcuts.utils.ShortcutUtils;
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/TrampolineActivityTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/TrampolineActivityTest.java
index 8705d6f..b14761a 100644
--- a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/TrampolineActivityTest.java
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/TrampolineActivityTest.java
@@ -16,8 +16,8 @@
 
 package androidx.core.google.shortcuts;
 
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_TAG_KEY;
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_URL_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_TAG_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_URL_KEY;
 import static androidx.test.espresso.intent.Intents.intended;
 import static androidx.test.espresso.intent.Intents.times;
 import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
@@ -31,6 +31,7 @@
 import android.content.pm.ResolveInfo;
 
 import androidx.core.google.shortcuts.test.TestActivity;
+import androidx.core.google.shortcuts.utils.ShortcutUtils;
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.espresso.intent.Intents;
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactoryTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactoryTest.java
new file mode 100644
index 0000000..b11e60c
--- /dev/null
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactoryTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class AppSearchDocumentConverterFactoryTest {
+    @Test
+    @SmallTest
+    public void testGetConverter_registeredConverter_returnsRegisteredConverter() {
+        AppSearchDocumentConverter converter = AppSearchDocumentConverterFactory
+                .getConverter("Timer");
+
+        assertThat(converter).isNotNull();
+        assertThat(converter).isInstanceOf(TimerConverter.class);
+    }
+
+    @Test
+    @SmallTest
+    public void testGetConverter_defaultConverter_returnsDefaultConverter() {
+        AppSearchDocumentConverter converter =
+                AppSearchDocumentConverterFactory.getConverter("NotRegisteredType");
+
+        assertThat(converter).isNotNull();
+        assertThat(converter).isInstanceOf(GenericDocumentConverter.class);
+    }
+}
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/GenericDocumentConverterTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/GenericDocumentConverterTest.java
new file mode 100644
index 0000000..d6b73b17
--- /dev/null
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/GenericDocumentConverterTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.appsearch.app.GenericDocument;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.firebase.appindexing.Indexable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class GenericDocumentConverterTest {
+    private final GenericDocumentConverter mConverter = new GenericDocumentConverter();
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Test
+    @SmallTest
+    public void testConvertGenericDocument_returnsIndexable() throws Exception {
+        GenericDocument childDocument1 = new GenericDocument.Builder<>(
+                "namespace1",
+                "child1",
+                "childSchema")
+                .setCreationTimestampMillis(1)
+                .build();
+        GenericDocument childDocument2 = new GenericDocument.Builder<>(
+                "namespace1",
+                "child2",
+                "childSchema")
+                .setCreationTimestampMillis(1)
+                .build();
+        GenericDocument genericDocument = new GenericDocument.Builder<>(
+                "namespace2",
+                "id1",
+                "schema")
+                .setScore(1)
+                .setTtlMillis(1000)
+                .setCreationTimestampMillis(1)
+                .setPropertyString("stringArrayProperty", "s1", "s2")
+                .setPropertyLong("longArrayProperty", 1L, 2L)
+                .setPropertyBoolean("booleanArrayProperty", true, false)
+                .setPropertyDocument("documentArrayProperty", childDocument1, childDocument2)
+                .setPropertyString("stringProperty", "s3")
+                .setPropertyLong("longProperty", 3L)
+                .setPropertyBoolean("booleanProperty", true)
+                .setPropertyDocument("documentProperty", childDocument1)
+                .setPropertyString("emptyProperty")
+                .build();
+
+        Indexable indexable = mConverter.convertGenericDocument(mContext, genericDocument).build();
+
+        Indexable expectedChild1 = new Indexable.Builder("childSchema")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(0))
+                .setName("namespace1")
+                .setId("child1")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=child1;end")
+                .put(IndexableKeys.NAMESPACE, "namespace1")
+                .put(IndexableKeys.TTL_MILLIS, 0)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .build();
+        Indexable expectedChild2 = new Indexable.Builder("childSchema")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(0))
+                .setName("namespace1")
+                .setId("child2")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=child2;end")
+                .put(IndexableKeys.NAMESPACE, "namespace1")
+                .put(IndexableKeys.TTL_MILLIS, 0)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .build();
+        Indexable expectedIndexable = new Indexable.Builder("schema")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(1))
+                .setName("namespace2")
+                .setId("id1")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=id1;end")
+                .put(IndexableKeys.NAMESPACE, "namespace2")
+                .put(IndexableKeys.TTL_MILLIS, 1000)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .put("stringArrayProperty", "s1", "s2")
+                .put("longArrayProperty", 1L, 2L)
+                .put("booleanArrayProperty", true, false)
+                .put("stringProperty", "s3")
+                .put("longProperty", 3L)
+                .put("booleanProperty", true)
+                .put("documentArrayProperty", expectedChild1, expectedChild2)
+                .put("documentProperty", expectedChild1)
+                .build();
+
+        assertThat(indexable).isEqualTo(expectedIndexable);
+    }
+}
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/TimerConverterTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/TimerConverterTest.java
new file mode 100644
index 0000000..22b8a02
--- /dev/null
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/converters/TimerConverterTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.AlarmClock;
+
+import androidx.appsearch.app.GenericDocument;
+import androidx.appsearch.builtintypes.Timer;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.firebase.appindexing.Indexable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.TimeZone;
+
+@RunWith(AndroidJUnit4.class)
+public class TimerConverterTest {
+    private final TimerConverter mTimerConverter = new TimerConverter();
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Test
+    @SmallTest
+    public void testConvert_returnsIndexable() throws Exception {
+        // Expire time is timezone sensitive. Force the default timezone to be GMT here.
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+        Timer timer = new Timer.Builder("namespace", "id")
+                .setDurationMillis(1000)
+                .setTimerStatus(Timer.STATUS_STARTED)
+                .setExpireTimeMillis(3000)
+                .setName("my timer")
+                .setRemainingTimeMillis(500)
+                .setRingtone(AlarmClock.VALUE_RINGTONE_SILENT)
+                .setScore(10)
+                .setTtlMillis(60000)
+                .setVibrate(true)
+                .build();
+
+        Indexable result = mTimerConverter.convertGenericDocument(mContext,
+                GenericDocument.fromDocumentClass(timer))
+                // Override creation timestamp to a constant instead of System.currentTimeMillis.
+                // TODO: add creation timestamp to timer.
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .build();
+        Indexable expectedResult = new Indexable.Builder("Timer")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(10))
+                .setId("id")
+                .setName("namespace")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=id;end")
+                .put(IndexableKeys.NAMESPACE, "namespace")
+                .put(IndexableKeys.TTL_MILLIS, 60000)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .put("length", 1000)
+                .put("timerStatus", "Started")
+                .put("expireTime", "1970-01-01T00:00:03+0000")
+                .put("message", "my timer")
+                .put("remainingTime", 500)
+                .put("ringtone", "silent")
+                .put("vibrate", true)
+                .build();
+        assertThat(result).isEqualTo(expectedResult);
+    }
+
+    @Test
+    @SmallTest
+    public void testConvert_withoutOptionalFields_returnsIndexable() throws Exception {
+        Timer timer = new Timer.Builder("namespace", "id")
+                .build();
+
+        Indexable result = mTimerConverter.convertGenericDocument(mContext,
+                GenericDocument.fromDocumentClass(timer))
+                // Override creation timestamp to a constant instead of System.currentTimeMillis.
+                // TODO: add creation timestamp to timer.
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .build();
+        Indexable expectedResult = new Indexable.Builder("Timer")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(0))
+                .setId("id")
+                .setName("namespace")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=id;end")
+                .put(IndexableKeys.NAMESPACE, "namespace")
+                .put(IndexableKeys.TTL_MILLIS, 0)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1)
+                .put("length", 0)
+                .put("timerStatus", "Unknown")
+                .put("remainingTime", 0)
+                .put("vibrate", false)
+                .build();
+        assertThat(result).isEqualTo(expectedResult);
+    }
+}
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ConverterUtilsTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ConverterUtilsTest.java
new file mode 100644
index 0000000..e5cc3b4
--- /dev/null
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ConverterUtilsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.google.shortcuts.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.appsearch.app.GenericDocument;
+import androidx.core.google.shortcuts.converters.IndexableKeys;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.firebase.appindexing.Indexable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class ConverterUtilsTest {
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Test
+    @SmallTest
+    public void testBuildBaseIndexableFromGenericDocument_returnsIndexable() {
+        GenericDocument genericDocument = new GenericDocument.Builder<>(
+                "namespace", "id", "schema")
+                .setScore(1)
+                .setCreationTimestampMillis(1)
+                .build();
+
+        Indexable.Builder expectedIndexableBuilder = new Indexable.Builder("schema")
+                .setMetadata(new Indexable.Metadata.Builder().setScore(1))
+                .setId("id")
+                .setName("namespace")
+                .setUrl("intent:#Intent;action=androidx.core.content.pm.SHORTCUT_LISTENER;"
+                        + "component=androidx.core.google.shortcuts.test/androidx.core.google."
+                        + "shortcuts.TrampolineActivity;S.id=id;end")
+                .put(IndexableKeys.NAMESPACE, "namespace")
+                .put(IndexableKeys.TTL_MILLIS, 0)
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS, 1);
+        assertThat(ConverterUtils.buildBaseIndexableFromGenericDocument(
+                mContext, genericDocument).build()).isEqualTo(expectedIndexableBuilder.build());
+    }
+}
diff --git a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutUtilsTest.java b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ShortcutUtilsTest.java
similarity index 93%
rename from core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutUtilsTest.java
rename to core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ShortcutUtilsTest.java
index f30f720..3add5f7 100644
--- a/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/ShortcutUtilsTest.java
+++ b/core/core-google-shortcuts/src/androidTest/java/androidx/core/google/shortcuts/utils/ShortcutUtilsTest.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.core.google.shortcuts;
+package androidx.core.google.shortcuts.utils;
 
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_LISTENER_INTENT_FILTER_ACTION;
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_TAG_KEY;
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_URL_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_LISTENER_INTENT_FILTER_ACTION;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_TAG_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_URL_KEY;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImpl.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImpl.java
index 5c5afd7..4196b1e 100644
--- a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImpl.java
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutInfoChangeListenerImpl.java
@@ -18,7 +18,7 @@
 
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
-import static androidx.core.google.shortcuts.ShortcutUtils.CAPABILITY_PARAM_SEPARATOR;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.CAPABILITY_PARAM_SEPARATOR;
 
 import android.content.Context;
 import android.os.Build;
@@ -34,6 +34,7 @@
 import androidx.core.google.shortcuts.builders.CapabilityBuilder;
 import androidx.core.google.shortcuts.builders.ParameterBuilder;
 import androidx.core.google.shortcuts.builders.ShortcutBuilder;
+import androidx.core.google.shortcuts.utils.ShortcutUtils;
 import androidx.core.graphics.drawable.IconCompat;
 
 import com.google.crypto.tink.KeysetHandle;
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/TrampolineActivity.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/TrampolineActivity.java
index adf51d0..9f5b265 100644
--- a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/TrampolineActivity.java
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/TrampolineActivity.java
@@ -17,8 +17,8 @@
 package androidx.core.google.shortcuts;
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_TAG_KEY;
-import static androidx.core.google.shortcuts.ShortcutUtils.SHORTCUT_URL_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_TAG_KEY;
+import static androidx.core.google.shortcuts.utils.ShortcutUtils.SHORTCUT_URL_KEY;
 
 import android.app.Activity;
 import android.content.Intent;
@@ -28,6 +28,7 @@
 
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.core.google.shortcuts.utils.ShortcutUtils;
 
 import com.google.crypto.tink.KeysetHandle;
 import com.google.crypto.tink.Mac;
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverter.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverter.java
new file mode 100644
index 0000000..54a1464
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.appsearch.app.GenericDocument;
+
+import com.google.firebase.appindexing.Indexable;
+
+/**
+ * Interface for a converter that will convert an AppSearch Document into {@link Indexable}.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public interface AppSearchDocumentConverter {
+    /** Converts a @{@link GenericDocument} into a {@link Indexable.Builder}. */
+    @NonNull
+    Indexable.Builder convertGenericDocument(@NonNull Context context,
+            @NonNull GenericDocument genericDocument);
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactory.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactory.java
new file mode 100644
index 0000000..c4136ad
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/AppSearchDocumentConverterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.core.util.Preconditions;
+
+/**
+ * A factory for {@link AppSearchDocumentConverter}. Given a schema type, if the schema type has
+ * a supported converter, then return that converter. Otherwise a default
+ * {@link GenericDocumentConverter} will be returned.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public class AppSearchDocumentConverterFactory {
+    private static final String TAG = "AppSearchDocumentConver"; // NOTYPO
+
+    /**
+     * Returns a {@link AppSearchDocumentConverter} given a schema type. If the schema type is not
+     * supported, then the {@link GenericDocumentConverter} will be returned.
+     */
+    @NonNull
+    public static AppSearchDocumentConverter getConverter(@NonNull String schemaType) {
+        Preconditions.checkNotNull(schemaType);
+
+        if ("Timer".equals(schemaType)) {
+            return new TimerConverter();
+        }
+
+        Log.w(TAG, "schema type " + schemaType + " does not have a Typed Converter registered. "
+                + "Returning the default GenericDocument converter.");
+        return new GenericDocumentConverter();
+    }
+
+    private AppSearchDocumentConverterFactory() {}
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/GenericDocumentConverter.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/GenericDocumentConverter.java
new file mode 100644
index 0000000..0e15087
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/GenericDocumentConverter.java
@@ -0,0 +1,92 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.appsearch.app.GenericDocument;
+import androidx.core.google.shortcuts.utils.ConverterUtils;
+import androidx.core.util.Preconditions;
+
+import com.google.firebase.appindexing.FirebaseAppIndexingInvalidArgumentException;
+import com.google.firebase.appindexing.Indexable;
+
+/**
+ * Default converter for all {@link GenericDocument}. This converter will map each property into
+ * its respective {@link Indexable} field. If a schema type is not registered with a specific
+ * converter, then this should be used as fallback.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public class GenericDocumentConverter implements AppSearchDocumentConverter {
+    private static final String TAG = "GenericDocumentConverte"; // NOTYPO
+
+    @NonNull
+    @Override
+    public Indexable.Builder convertGenericDocument(
+            @NonNull Context context,
+            @NonNull GenericDocument genericDocument) {
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(genericDocument);
+
+        Indexable.Builder indexableBuilder = ConverterUtils.buildBaseIndexableFromGenericDocument(
+                context, genericDocument);
+
+        for (String property : genericDocument.getPropertyNames()) {
+            Object rawProperty = genericDocument.getProperty(property);
+            if (rawProperty instanceof String[]) {
+                indexableBuilder.put(property, (String[]) rawProperty);
+            } else if (rawProperty instanceof long[]) {
+                indexableBuilder.put(property, (long[]) rawProperty);
+            } else if (rawProperty instanceof double[]) {
+                // TODO (b/205890624): add conversion for double once it's supported in Indexable.
+                Log.w(TAG, "Property type double for " + property + " is not supported.");
+            } else if (rawProperty instanceof boolean[]) {
+                indexableBuilder.put(property, (boolean[]) rawProperty);
+            } else if (rawProperty instanceof byte[][]) {
+                // TODO (b/205890624): add conversion for byte[] once it's supported in Indexable.
+                Log.w(TAG, "Property type byte[] for " + property + " is not supported.");
+            } else if (rawProperty instanceof GenericDocument[]) {
+                try {
+                    indexableBuilder.put(property,
+                            convertGenericDocuments(context, (GenericDocument[]) rawProperty));
+                } catch (FirebaseAppIndexingInvalidArgumentException e) {
+                    Log.e(TAG, "Cannot convert GenericDocument for property " + property);
+                }
+            } else {
+                Log.e(TAG, "Undefined property type from " + property);
+            }
+        }
+        return indexableBuilder;
+    }
+
+    private Indexable[] convertGenericDocuments(Context context,
+            GenericDocument[] genericDocuments) {
+        Indexable[] indexables = new Indexable[genericDocuments.length];
+        for (int i = 0; i < genericDocuments.length; i++) {
+            indexables[i] = convertGenericDocument(context, genericDocuments[i]).build();
+        }
+
+        return indexables;
+    }
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/IndexableKeys.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/IndexableKeys.java
new file mode 100644
index 0000000..e34a460
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/IndexableKeys.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.google.shortcuts.converters;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import androidx.annotation.RestrictTo;
+
+/**
+ * Constants for the keys for common {@link com.google.firebase.appindexing.Indexable} fields.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public class IndexableKeys {
+    // General
+    public static final String NAMESPACE = "_namespace";
+    public static final String TTL_MILLIS = "_ttlMillis";
+    public static final String CREATION_TIMESTAMP_MILLIS = "_creationTimestampMillis";
+
+    private IndexableKeys() {}
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/TimerConverter.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/TimerConverter.java
new file mode 100644
index 0000000..b09f04a
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/converters/TimerConverter.java
@@ -0,0 +1,130 @@
+/*
+ * 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.core.google.shortcuts.converters;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.appsearch.app.GenericDocument;
+import androidx.appsearch.builtintypes.Timer;
+import androidx.core.google.shortcuts.utils.ConverterUtils;
+import androidx.core.util.Preconditions;
+
+import com.google.firebase.appindexing.Indexable;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * Convert for the {@link Timer} built-in type.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public class TimerConverter implements AppSearchDocumentConverter {
+    private static final String TAG = "TimerConverter";
+
+    // Keys from the AppSearch document
+    private static final String NAME_KEY = "name";
+    private static final String DURATION_MILLIS_KEY = "durationMillis";
+    private static final String REMAINING_TIME_MILLIS_KEY = "remainingTimeMillis";
+    private static final String RINGTONE_KEY = "ringtone";
+    private static final String VIBRATE_KEY = "vibrate";
+    private static final String TIMER_STATUS_KEY = "timerStatus";
+    private static final String EXPIRE_TIME_MILLIS_KEY = "expireTimeMillis";
+
+    // Keys for Indexables
+    private static final String MESSAGE_KEY = "message";
+    private static final String LENGTH_KEY = "length";
+    private static final String REMAINING_TIME_KEY = "remainingTime";
+    private static final String EXPIRE_TIME_KEY = "expireTime";
+
+    // Enums for TimerStatus
+    private static final String STARTED = "Started";
+    private static final String PAUSED = "Paused";
+    private static final String EXPIRED = "Expired";
+    private static final String MISSED = "Missed";
+    private static final String RESET = "Reset";
+    private static final String UNKNOWN = "Unknown";
+
+    private static final ThreadLocal<DateFormat> ISO8601_DATE_TIME_FORMAT =
+            new ThreadLocal<DateFormat>() {
+        @Override
+        public DateFormat initialValue() {
+            return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
+        }
+    };
+
+    @Override
+    @NonNull
+    public Indexable.Builder convertGenericDocument(@NonNull Context context,
+            @NonNull GenericDocument timer) {
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(timer);
+
+        Indexable.Builder indexableBuilder = ConverterUtils.buildBaseIndexableFromGenericDocument(
+                    context, timer);
+
+        indexableBuilder
+                .put(MESSAGE_KEY, timer.getPropertyString(NAME_KEY))
+                .put(LENGTH_KEY, timer.getPropertyLong(DURATION_MILLIS_KEY))
+                .put(REMAINING_TIME_KEY, timer.getPropertyLong(REMAINING_TIME_MILLIS_KEY))
+                .put(RINGTONE_KEY, timer.getPropertyString(RINGTONE_KEY))
+                .put(VIBRATE_KEY, timer.getPropertyBoolean(VIBRATE_KEY));
+
+        int timerStatus = (int) timer.getPropertyLong(TIMER_STATUS_KEY);
+        switch (timerStatus) {
+            case Timer.STATUS_UNKNOWN:
+                indexableBuilder.put(TIMER_STATUS_KEY, UNKNOWN);
+                break;
+            case Timer.STATUS_STARTED:
+                indexableBuilder.put(TIMER_STATUS_KEY, STARTED);
+                break;
+            case Timer.STATUS_PAUSED:
+                indexableBuilder.put(TIMER_STATUS_KEY, PAUSED);
+                break;
+            case Timer.STATUS_EXPIRED:
+                indexableBuilder.put(TIMER_STATUS_KEY, EXPIRED);
+                break;
+            case Timer.STATUS_MISSED:
+                indexableBuilder.put(TIMER_STATUS_KEY, MISSED);
+                break;
+            case Timer.STATUS_RESET:
+                indexableBuilder.put(TIMER_STATUS_KEY, RESET);
+                break;
+            default:
+                indexableBuilder.put(TIMER_STATUS_KEY, UNKNOWN);
+                Log.w(TAG, "Invalud time status: " + timerStatus + ", defaulting to "
+                        + "Timer.STATUS_UNKNOWN");
+        }
+
+        // 0 means never expire.
+        long expireTime = timer.getPropertyLong(EXPIRE_TIME_MILLIS_KEY);
+        if (expireTime > 0) {
+            Date date = new Date(expireTime);
+            indexableBuilder.put(EXPIRE_TIME_KEY,
+                    Preconditions.checkNotNull(ISO8601_DATE_TIME_FORMAT.get()).format(date));
+        }
+        return indexableBuilder;
+    }
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ConverterUtils.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ConverterUtils.java
new file mode 100644
index 0000000..35a05d9
--- /dev/null
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ConverterUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.google.shortcuts.utils;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.appsearch.app.GenericDocument;
+import androidx.core.google.shortcuts.converters.AppSearchDocumentConverter;
+import androidx.core.google.shortcuts.converters.IndexableKeys;
+import androidx.core.util.Preconditions;
+
+import com.google.firebase.appindexing.Indexable;
+
+/**
+ * Utility methods for {@link AppSearchDocumentConverter}.
+ *
+ * @hide
+ */
+@RestrictTo(LIBRARY)
+public class ConverterUtils {
+    /** Creates an {@link Indexable.Builder} from {@link GenericDocument} with common fields set. */
+    @NonNull
+    public static Indexable.Builder buildBaseIndexableFromGenericDocument(
+            @NonNull Context context,
+            @NonNull GenericDocument genericDocument) {
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(genericDocument);
+
+        return new Indexable.Builder(genericDocument.getSchemaType())
+                .setId(genericDocument.getId())
+                // TODO (b/206020715): remove name when it's no longer a required field.
+                .setName(genericDocument.getNamespace())
+                .setMetadata(new Indexable.Metadata.Builder().setScore(genericDocument.getScore()))
+                .setUrl(ShortcutUtils.getIndexableUrl(context, genericDocument.getId()))
+                .put(IndexableKeys.NAMESPACE, genericDocument.getNamespace())
+                .put(IndexableKeys.CREATION_TIMESTAMP_MILLIS,
+                        genericDocument.getCreationTimestampMillis())
+                .put(IndexableKeys.TTL_MILLIS, genericDocument.getTtlMillis());
+    }
+
+    private ConverterUtils() {}
+}
diff --git a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutUtils.java b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ShortcutUtils.java
similarity index 94%
rename from core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutUtils.java
rename to core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ShortcutUtils.java
index 7f457d9..d6b8393 100644
--- a/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/ShortcutUtils.java
+++ b/core/core-google-shortcuts/src/main/java/androidx/core/google/shortcuts/utils/ShortcutUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.core.google.shortcuts;
+package androidx.core.google.shortcuts.utils;
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
 
@@ -26,6 +26,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
+import androidx.core.google.shortcuts.TrampolineActivity;
 
 import com.google.crypto.tink.KeysetHandle;
 import com.google.crypto.tink.Mac;
@@ -43,7 +44,7 @@
  * @hide
  */
 @RestrictTo(LIBRARY)
-class ShortcutUtils {
+public class ShortcutUtils {
     public static final String ID_KEY = "id";
     public static final String SHORTCUT_URL_KEY = "shortcutUrl";
     public static final String CAPABILITY_PARAM_SEPARATOR = "/";
@@ -66,6 +67,7 @@
      * @param shortcutId the shortcut id used to generate the url.
      * @return the indexable url.
      */
+    @NonNull
     public static String getIndexableUrl(@NonNull Context context, @NonNull String shortcutId) {
         Intent intent = new Intent(context, TrampolineActivity.class);
         intent.setAction(SHORTCUT_LISTENER_INTENT_FILTER_ACTION);
@@ -84,6 +86,7 @@
      * @return the shortcut url wrapped inside an intent that opens the Trampoline Activity if
      * the shortcut can be signed. Otherwise return just the shortcut url.
      */
+    @NonNull
     public static String getIndexableShortcutUrl(@NonNull Context context,
             @NonNull Intent shortcutIntent, @Nullable KeysetHandle keysetHandle) {
         String shortcutUrl = shortcutIntent.toUri(Intent.URI_INTENT_SCHEME);
@@ -119,10 +122,12 @@
         }
     }
 
+    /** Returns whether or not the capability is a App Actions BII. */
     public static boolean isAppActionCapability(@NonNull final String capability) {
         return capability.startsWith(APP_ACTION_CAPABILITY_PREFIX);
     }
 
+    /** Creates the {@link KeysetHandle} used to compute security MAC for Shortcut Urls. */
     @Nullable
     public static KeysetHandle getOrCreateShortcutKeysetHandle(@NonNull Context context) {
         try {
diff --git a/core/core-ktx/api/current.txt b/core/core-ktx/api/current.txt
index fee3502..86d91a7 100644
--- a/core/core-ktx/api/current.txt
+++ b/core/core-ktx/api/current.txt
@@ -451,8 +451,10 @@
   public final class SizeKt {
     method @RequiresApi(21) public static inline operator int component1(android.util.Size);
     method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+    method public static inline operator float component1(androidx.core.util.SizeFCompat);
     method @RequiresApi(21) public static inline operator int component2(android.util.Size);
     method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+    method public static inline operator float component2(androidx.core.util.SizeFCompat);
   }
 
   public final class SparseArrayKt {
diff --git a/core/core-ktx/api/public_plus_experimental_current.txt b/core/core-ktx/api/public_plus_experimental_current.txt
index fee3502..86d91a7 100644
--- a/core/core-ktx/api/public_plus_experimental_current.txt
+++ b/core/core-ktx/api/public_plus_experimental_current.txt
@@ -451,8 +451,10 @@
   public final class SizeKt {
     method @RequiresApi(21) public static inline operator int component1(android.util.Size);
     method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+    method public static inline operator float component1(androidx.core.util.SizeFCompat);
     method @RequiresApi(21) public static inline operator int component2(android.util.Size);
     method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+    method public static inline operator float component2(androidx.core.util.SizeFCompat);
   }
 
   public final class SparseArrayKt {
diff --git a/core/core-ktx/api/restricted_current.txt b/core/core-ktx/api/restricted_current.txt
index fee3502..86d91a7 100644
--- a/core/core-ktx/api/restricted_current.txt
+++ b/core/core-ktx/api/restricted_current.txt
@@ -451,8 +451,10 @@
   public final class SizeKt {
     method @RequiresApi(21) public static inline operator int component1(android.util.Size);
     method @RequiresApi(21) public static inline operator float component1(android.util.SizeF);
+    method public static inline operator float component1(androidx.core.util.SizeFCompat);
     method @RequiresApi(21) public static inline operator int component2(android.util.Size);
     method @RequiresApi(21) public static inline operator float component2(android.util.SizeF);
+    method public static inline operator float component2(androidx.core.util.SizeFCompat);
   }
 
   public final class SparseArrayKt {
diff --git a/core/core-ktx/src/androidTest/java/androidx/core/util/SizeTest.kt b/core/core-ktx/src/androidTest/java/androidx/core/util/SizeTest.kt
index 5cd063b..07aa580 100644
--- a/core/core-ktx/src/androidTest/java/androidx/core/util/SizeTest.kt
+++ b/core/core-ktx/src/androidTest/java/androidx/core/util/SizeTest.kt
@@ -23,18 +23,25 @@
 import org.junit.Assert.assertEquals
 import org.junit.Test
 
-@SdkSuppress(minSdkVersion = 21)
 @SmallTest
 class SizeTest {
+    @SdkSuppress(minSdkVersion = 21)
     @Test fun destructuringSize() {
         val (w, h) = Size(320, 240)
         assertEquals(320, w)
         assertEquals(240, h)
     }
 
+    @SdkSuppress(minSdkVersion = 21)
     @Test fun destructuringSizeF() {
         val (w, h) = SizeF(1920.0f, 1080.0f)
         assertEquals(1920.0f, w)
         assertEquals(1080.0f, h)
     }
+
+    @Test fun destructuringSizeFCompat() {
+        val (w, h) = SizeFCompat(1920.0f, 1080.0f)
+        assertEquals(1920.0f, w)
+        assertEquals(1080.0f, h)
+    }
 }
diff --git a/core/core-ktx/src/main/java/androidx/core/util/Size.kt b/core/core-ktx/src/main/java/androidx/core/util/Size.kt
index ab2d80a..5cb85db 100644
--- a/core/core-ktx/src/main/java/androidx/core/util/Size.kt
+++ b/core/core-ktx/src/main/java/androidx/core/util/Size.kt
@@ -71,3 +71,25 @@
  */
 @RequiresApi(21)
 public inline operator fun SizeF.component2(): Float = height
+
+/**
+ * Returns "width", the first component of this [SizeFCompat].
+ *
+ * This method allows to use destructuring declarations when working with
+ * sizes, for example:
+ * ```
+ * val (w, h) = mySize
+ * ```
+ */
+public inline operator fun SizeFCompat.component1(): Float = width
+
+/**
+ * Returns "height", the second component of this [SizeFCompat].
+ *
+ * This method allows to use destructuring declarations when working with
+ * sizes, for example:
+ * ```
+ * val (w, h) = mySize
+ * ```
+ */
+public inline operator fun SizeFCompat.component2(): Float = height
diff --git a/core/core-performance/build.gradle b/core/core-performance/build.gradle
index 576a8d8..efefe4d 100644
--- a/core/core-performance/build.gradle
+++ b/core/core-performance/build.gradle
@@ -26,16 +26,18 @@
 
 dependencies {
     api(libs.kotlinStdlib)
+
+    testImplementation(libs.testCore)
     testImplementation(libs.kotlinStdlib)
     testImplementation(libs.junit)
     testImplementation(libs.truth)
-    testImplementation(libs.robolectric)
+    testImplementation("org.robolectric:robolectric:4.7") // TODO(b/206673076): use libs.robolectric
 }
 
 androidx {
     name = "androidx.core:core-performance"
     type = LibraryType.PUBLISHED_LIBRARY
-    mavenVersion = LibraryVersions.CORE
+    mavenVersion = LibraryVersions.CORE_PERFORMANCE
     mavenGroup = LibraryGroups.CORE
     inceptionYear = "2021"
     description = "This libraray makes it easy for developers to make UI and feature choices based on Android Performance Class level for GMS devices."
diff --git a/core/core-performance/samples/build.gradle b/core/core-performance/samples/build.gradle
new file mode 100644
index 0000000..1158249
--- /dev/null
+++ b/core/core-performance/samples/build.gradle
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 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.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryType
+import androidx.build.LibraryVersions
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    api(libs.kotlinStdlib)
+    // Add dependencies here
+}
+
+androidx {
+    name = "Core Performance Samples"
+    type = LibraryType.SAMPLES
+    mavenVersion = LibraryVersions.CORE_PERFORMANCE
+    mavenGroup = LibraryGroups.CORE
+    inceptionYear = "2021"
+    description = "Samples for AndroidX Core Performance Library"
+}
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/core/core-performance/samples/src/androidTest/AndroidManifest.xml
similarity index 73%
copy from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
copy to core/core-performance/samples/src/androidTest/AndroidManifest.xml
index 987c157..badc86c 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/core/core-performance/samples/src/androidTest/AndroidManifest.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   Copyright 2021 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.core.performance.samples.test">
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+</manifest>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/core/core-performance/samples/src/main/AndroidManifest.xml
similarity index 73%
copy from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
copy to core/core-performance/samples/src/main/AndroidManifest.xml
index 987c157..de93147 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/core/core-performance/samples/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   Copyright 2021 The Android Open Source Project
 
   Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +14,7 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.core.performance.samples">
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+</manifest>
\ No newline at end of file
diff --git a/core/core-performance/samples/src/main/androidx/core/androidx-core-core-performance-samples-documentation.md b/core/core-performance/samples/src/main/androidx/core/androidx-core-core-performance-samples-documentation.md
new file mode 100644
index 0000000..1e79883
--- /dev/null
+++ b/core/core-performance/samples/src/main/androidx/core/androidx-core-core-performance-samples-documentation.md
@@ -0,0 +1,7 @@
+# Module root
+
+<GROUPID> <ARTIFACTID>
+
+# Package androidx.core.performance.samples
+
+Insert package level documentation here
diff --git a/core/core-performance/src/main/kotlin/androidx/core/performance/PerformanceClass.kt b/core/core-performance/src/main/kotlin/androidx/core/performance/PerformanceClass.kt
index afe7ad1..538277e 100644
--- a/core/core-performance/src/main/kotlin/androidx/core/performance/PerformanceClass.kt
+++ b/core/core-performance/src/main/kotlin/androidx/core/performance/PerformanceClass.kt
@@ -16,29 +16,53 @@
 
 package androidx.core.performance
 
+import android.content.Context
 import android.os.Build
 
 /**
  * Reports the media performance class of the device.
  */
-class PerformanceClass {
+interface PerformanceClass {
 
     /**
      * The media performance class of the device or 0 if none.
      * <p>
      * If this value is not <code>0</code>, the device conforms to the media performance class
-     * definition of the SDK version of this value. This value never changes while a device is
-     * booted, but it may increase when the hardware manufacturer provides an OTA update.
+     * definition of the SDK version of this value. This value is stable for the duration of
+     * the process.
      * <p>
      * Possible non-zero values are defined in {@link Build.VERSION_CODES} starting with
      * {@link Build.VERSION_CODES#R}.
      * <p>
      * Defaults to {@link Build.MEDIA_PERFORMANCE_CLASS}
      */
-    fun getPerformanceClass(): Int {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
-            return Build.VERSION.MEDIA_PERFORMANCE_CLASS
+    val mediaPerformanceClass: Int
+
+    companion object {
+        /**
+         * Create PerformanceClass from the context.
+         * @param context The ApplicationContext.
+         */
+        fun create(
+            // Other implementations will require a context
+            @Suppress("UNUSED_PARAMETER") context: Context
+        ): PerformanceClass = DefaultPerformanceClassImpl()
+    }
+}
+
+/**
+ * Reports the media performance class of the device.
+ */
+private class DefaultPerformanceClassImpl : PerformanceClass {
+
+    override val mediaPerformanceClass: Int = calculateMediaPerformanceClass()
+
+    companion object {
+        fun calculateMediaPerformanceClass(): Int {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                return Build.VERSION.MEDIA_PERFORMANCE_CLASS
+            }
+            return 0
         }
-        return 0
     }
 }
diff --git a/core/core-performance/src/test/kotlin/androidx/core/performance/PerformanceClassTest.kt b/core/core-performance/src/test/kotlin/androidx/core/performance/PerformanceClassTest.kt
index 23bcaf6..01b920b 100644
--- a/core/core-performance/src/test/kotlin/androidx/core/performance/PerformanceClassTest.kt
+++ b/core/core-performance/src/test/kotlin/androidx/core/performance/PerformanceClassTest.kt
@@ -16,35 +16,49 @@
 
 package androidx.core.performance
 
+import android.app.Application
 import android.os.Build.VERSION_CODES.R
 import android.os.Build.VERSION_CODES.S
+import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
 import org.robolectric.annotation.Config
+import org.robolectric.shadows.ShadowBuild
 import org.robolectric.shadows.ShadowSystemProperties
 
 /** Unit tests for [PerformanceClass]. */
 @RunWith(RobolectricTestRunner::class)
 class PerformanceClassTest {
 
-    private val pc = PerformanceClass()
-
     @Test
     @Config(maxSdk = R)
-    fun getPerformanceClass_sdk30() {
-        assertThat(pc.getPerformanceClass()).isEqualTo(0)
+    fun getMediaPerformanceClass_sdk30() {
+        val pc = createPerformanceClass()
+        assertThat(pc.mediaPerformanceClass).isEqualTo(0)
     }
 
     @Test
-    // Note this test is not actually running because robolectric does not support sdk31 yet
-    @Ignore("b/206673076")
     @Config(minSdk = S)
-    fun getPerformanceClass_sdk31() {
+    fun getMediaPerformanceClass_sdk31_declared30() {
         // TODO(b/205732671): Use ShadowBuild.setMediaPerformanceClass when available
-        ShadowSystemProperties.override("ro.odm.build.media_performance_class", "31")
-        assertThat(pc.getPerformanceClass()).isEqualTo(31)
+        ShadowSystemProperties.override("ro.odm.build.media_performance_class", "30")
+        ShadowBuild.reset()
+        val pc = createPerformanceClass()
+        assertThat(pc.mediaPerformanceClass).isEqualTo(30)
+    }
+
+    @Test
+    @Config(minSdk = S)
+    fun getMediaPerformanceClass_sdk31_notDeclared() {
+        // TODO(b/205732671): Use ShadowBuild.setMediaPerformanceClass when available
+        ShadowBuild.reset()
+        val pc = createPerformanceClass()
+        assertThat(pc.mediaPerformanceClass).isEqualTo(0)
+    }
+
+    private fun createPerformanceClass(): PerformanceClass {
+        return PerformanceClass.create(ApplicationProvider.getApplicationContext<Application>())
     }
 }
\ No newline at end of file
diff --git a/core/core-remoteviews/api/current.txt b/core/core-remoteviews/api/current.txt
index 2115270..58dee29 100644
--- a/core/core-remoteviews/api/current.txt
+++ b/core/core-remoteviews/api/current.txt
@@ -1,6 +1,13 @@
 // Signature format: 4.0
 package androidx.core.widget {
 
+  public final class AppWidgetManagerCompat {
+    method public static android.widget.RemoteViews createExactSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static android.widget.RemoteViews createResponsiveSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+  }
+
   public final class RemoteViewsCompat {
     method public static void setChronometerBase(android.widget.RemoteViews, @IdRes int viewId, long base);
     method public static void setChronometerFormat(android.widget.RemoteViews, @IdRes int viewId, String? format);
diff --git a/core/core-remoteviews/api/public_plus_experimental_current.txt b/core/core-remoteviews/api/public_plus_experimental_current.txt
index 2115270..58dee29 100644
--- a/core/core-remoteviews/api/public_plus_experimental_current.txt
+++ b/core/core-remoteviews/api/public_plus_experimental_current.txt
@@ -1,6 +1,13 @@
 // Signature format: 4.0
 package androidx.core.widget {
 
+  public final class AppWidgetManagerCompat {
+    method public static android.widget.RemoteViews createExactSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static android.widget.RemoteViews createResponsiveSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+  }
+
   public final class RemoteViewsCompat {
     method public static void setChronometerBase(android.widget.RemoteViews, @IdRes int viewId, long base);
     method public static void setChronometerFormat(android.widget.RemoteViews, @IdRes int viewId, String? format);
diff --git a/core/core-remoteviews/api/restricted_current.txt b/core/core-remoteviews/api/restricted_current.txt
index 8d9e929..479f021 100644
--- a/core/core-remoteviews/api/restricted_current.txt
+++ b/core/core-remoteviews/api/restricted_current.txt
@@ -1,6 +1,13 @@
 // Signature format: 4.0
 package androidx.core.widget {
 
+  public final class AppWidgetManagerCompat {
+    method public static android.widget.RemoteViews createExactSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static android.widget.RemoteViews createResponsiveSizeAppWidget(android.appwidget.AppWidgetManager appWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+    method public static void updateAppWidget(android.appwidget.AppWidgetManager, int appWidgetId, java.util.Collection<androidx.core.util.SizeFCompat> dpSizes, kotlin.jvm.functions.Function1<? super androidx.core.util.SizeFCompat,? extends android.widget.RemoteViews> factory);
+  }
+
   public final class RemoteViewsCompat {
     method public static void setChronometerBase(android.widget.RemoteViews, @IdRes int viewId, long base);
     method public static void setChronometerFormat(android.widget.RemoteViews, @IdRes int viewId, String? format);
diff --git a/core/core-remoteviews/build.gradle b/core/core-remoteviews/build.gradle
index 6b2cd78..55ff527 100644
--- a/core/core-remoteviews/build.gradle
+++ b/core/core-remoteviews/build.gradle
@@ -30,8 +30,10 @@
 dependencies {
     api(libs.kotlinStdlib)
     api("androidx.annotation:annotation:1.2.0")
-    implementation("androidx.core:core:1.7.0")
+    implementation project(":core:core")
 
+    androidTestImplementation project(":core:core")
+    androidTestImplementation project(":core:core-ktx")
     androidTestImplementation(libs.kotlinStdlib)
     androidTestImplementation(libs.kotlinTest)
     androidTestImplementation(libs.testExtJunit)
@@ -40,6 +42,8 @@
     androidTestImplementation(libs.testRules)
     androidTestImplementation(libs.truth)
 
+    testImplementation project(":core:core")
+    testImplementation project(":core:core-ktx")
     testImplementation(libs.testCore)
     testImplementation(libs.testRunner)
     testImplementation(libs.junit)
diff --git a/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetHostTestActivity.kt b/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetHostTestActivity.kt
index c5124cb..c270f6b 100644
--- a/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetHostTestActivity.kt
+++ b/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetHostTestActivity.kt
@@ -16,18 +16,27 @@
 
 package androidx.core.widget
 
+import android.annotation.TargetApi
 import android.app.Activity
 import android.appwidget.AppWidgetHost
 import android.appwidget.AppWidgetHostView
 import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_SIZES
 import android.content.ComponentName
+import android.os.Build
 import android.os.Bundle
+import android.util.SizeF
 import android.view.WindowManager
 import android.widget.FrameLayout
 import androidx.core.remoteviews.test.R
 import org.junit.Assert.fail
 
 /** Test activity that contains an [AppWidgetHost].  */
+@TargetApi(29)
 public class AppWidgetHostTestActivity : Activity() {
     private var mHost: AppWidgetHost? = null
 
@@ -69,6 +78,30 @@
             )
         )
 
+        fun pxToDp(px: Int): Int {
+            val density = resources.displayMetrics.density
+            return (px / density).toInt()
+        }
+
+        val width = pxToDp(contentFrame.width)
+        val height = pxToDp(contentFrame.height)
+        val optionsBundle = Bundle()
+        optionsBundle.putInt(OPTION_APPWIDGET_MIN_WIDTH, width)
+        optionsBundle.putInt(OPTION_APPWIDGET_MAX_WIDTH, width)
+        optionsBundle.putInt(OPTION_APPWIDGET_MIN_HEIGHT, height)
+        optionsBundle.putInt(OPTION_APPWIDGET_MAX_HEIGHT, height)
+        if (Build.VERSION.SDK_INT >= 31) {
+            optionsBundle.putParcelableArrayList(
+                OPTION_APPWIDGET_SIZES,
+                arrayListOf(SizeF(width.toFloat(), height.toFloat()))
+            )
+        }
+
+        appWidgetManager.updateAppWidgetOptions(
+            appWidgetId,
+            optionsBundle
+        )
+
         return hostView
     }
 }
diff --git a/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetManagerDeviceTest.kt b/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetManagerDeviceTest.kt
new file mode 100644
index 0000000..7a1573a
--- /dev/null
+++ b/core/core-remoteviews/src/androidTest/java/androidx/core/widget/AppWidgetManagerDeviceTest.kt
@@ -0,0 +1,193 @@
+/*
+ * 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.core.widget
+
+import android.Manifest
+import android.app.UiAutomation
+import android.appwidget.AppWidgetHostView
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_SIZES
+import android.content.Context
+import android.os.Build
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.SizeF
+import android.view.ViewTreeObserver
+import android.widget.RemoteViews
+import android.widget.TextView
+import androidx.core.remoteviews.test.R
+import androidx.core.util.SizeFCompat
+import androidx.core.util.component1
+import androidx.core.util.component2
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.test.fail
+
+@SdkSuppress(minSdkVersion = 29)
+@MediumTest
+class AppWidgetManagerDeviceTest {
+    private val mContext = ApplicationProvider.getApplicationContext<Context>()
+    private val mPackageName = mContext.packageName
+    private val mAppWidgetManager = AppWidgetManager.getInstance(mContext)
+
+    @Rule
+    @JvmField
+    public val mActivityTestRule: ActivityScenarioRule<AppWidgetHostTestActivity> =
+        ActivityScenarioRule(AppWidgetHostTestActivity::class.java)
+
+    private lateinit var mRemoteViews: RemoteViews
+    private lateinit var mHostView: AppWidgetHostView
+    private var mAppWidgetId = 0
+
+    private val mUiAutomation: UiAutomation
+        get() = InstrumentationRegistry.getInstrumentation().uiAutomation
+
+    private val mTextView: TextView
+        get() = mHostView.getChildAt(0) as TextView
+
+    @Before
+    public fun setUp() {
+        mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.BIND_APPWIDGET)
+
+        mActivityTestRule.scenario.onActivity { activity ->
+            mHostView = activity.bindAppWidget()
+        }
+
+        mAppWidgetId = mHostView.appWidgetId
+        mRemoteViews = RemoteViews(mPackageName, R.layout.remote_views_text)
+        mAppWidgetManager.updateAppWidget(mAppWidgetId, mRemoteViews)
+
+        // Wait until the remote views has been added to the host view.
+        observeDrawUntil { mHostView.childCount > 0 }
+    }
+
+    @After
+    public fun tearDown() {
+        mUiAutomation.dropShellPermissionIdentity()
+    }
+
+    @Test
+    public fun exact_shouldUseActualWidgetSize() {
+        mAppWidgetManager.updateAppWidget(mAppWidgetId) { (widthDp, heightDp) ->
+            RemoteViews(mPackageName, R.layout.remote_views_text).apply {
+                setTextViewText(R.id.text, "$widthDp x $heightDp")
+            }
+        }
+
+        val (width, height) = getSingleWidgetSize()
+        observeTextUntilEquals("$width x $height")
+    }
+
+    @Test
+    public fun responsive_shouldUseBestFittingProvidedWidgetSizes() {
+        val (width, height) = getSingleWidgetSize()
+        mAppWidgetManager.updateAppWidget(
+            mAppWidgetId,
+            listOf(width - 2 x height - 2, width + 2 x height + 2)
+        ) { (widthDp, heightDp) ->
+            RemoteViews(mPackageName, R.layout.remote_views_text).apply {
+                setTextViewText(R.id.text, "$widthDp x $heightDp")
+            }
+        }
+
+        observeTextUntilEquals("${width - 2} x ${height - 2}")
+    }
+
+    private fun observeTextUntilEquals(expectedText: String) {
+        if (mTextView.text.toString() == expectedText) return
+
+        val latch = CountDownLatch(1)
+        val textWatcher = object : TextWatcher {
+            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
+
+            override fun onTextChanged(text: CharSequence?, p1: Int, p2: Int, p3: Int) {
+                if (text.toString() == expectedText) latch.countDown()
+            }
+
+            override fun afterTextChanged(text: Editable?) {}
+        }
+
+        mActivityTestRule.scenario.onActivity {
+            mTextView.addTextChangedListener(textWatcher)
+        }
+
+        val countedDown = latch.await(5, TimeUnit.SECONDS)
+
+        mActivityTestRule.scenario.onActivity {
+            mTextView.removeTextChangedListener(textWatcher)
+        }
+
+        if (!countedDown && mTextView.text.toString() != expectedText) {
+            fail("Expected text to be \"$expectedText\" within 5 seconds")
+        }
+    }
+
+    private fun observeDrawUntil(test: () -> Boolean) {
+        val latch = CountDownLatch(1)
+        val onDrawListener = ViewTreeObserver.OnDrawListener {
+            if (test()) latch.countDown()
+        }
+
+        mActivityTestRule.scenario.onActivity {
+            mHostView.viewTreeObserver.addOnDrawListener(onDrawListener)
+        }
+
+        val countedDown = latch.await(5, TimeUnit.SECONDS)
+
+        mActivityTestRule.scenario.onActivity {
+            mHostView.viewTreeObserver.removeOnDrawListener(onDrawListener)
+        }
+
+        if (!countedDown && !test()) {
+            fail("Expected condition to be met within 5 seconds")
+        }
+    }
+
+    private fun getSingleWidgetSize(): SizeFCompat {
+        val options = mAppWidgetManager.getAppWidgetOptions(mAppWidgetId)
+        return if (Build.VERSION.SDK_INT >= 31) {
+            options
+                .getParcelableArrayList<SizeF>(OPTION_APPWIDGET_SIZES)!!
+                .single()
+                .let { it.width x it.height }
+        } else {
+            val minWidth = options.getInt(OPTION_APPWIDGET_MIN_WIDTH)
+            val maxWidth = options.getInt(OPTION_APPWIDGET_MAX_WIDTH)
+            val minHeight = options.getInt(OPTION_APPWIDGET_MIN_HEIGHT)
+            val maxHeight = options.getInt(OPTION_APPWIDGET_MAX_HEIGHT)
+            assertThat(minWidth).isEqualTo(maxWidth)
+            assertThat(minHeight).isEqualTo(maxHeight)
+            minWidth x minHeight
+        }
+    }
+
+    private infix fun Number.x(other: Number) = SizeFCompat(this.toFloat(), other.toFloat())
+}
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/core/core-remoteviews/src/androidTest/res/layout/remote_views_text.xml
similarity index 77%
copy from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
copy to core/core-remoteviews/src/androidTest/res/layout/remote_views_text.xml
index 987c157..2753a1b 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/core/core-remoteviews/src/androidTest/res/layout/remote_views_text.xml
@@ -14,6 +14,7 @@
   limitations under the License.
   -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/text"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/core/core-remoteviews/src/main/java/androidx/core/widget/AppWidgetManagerCompat.kt b/core/core-remoteviews/src/main/java/androidx/core/widget/AppWidgetManagerCompat.kt
new file mode 100644
index 0000000..a7135f2
--- /dev/null
+++ b/core/core-remoteviews/src/main/java/androidx/core/widget/AppWidgetManagerCompat.kt
@@ -0,0 +1,334 @@
+@file:JvmName("AppWidgetManagerCompat")
+
+/*
+ * 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.core.widget
+
+import android.appwidget.AppWidgetManager
+import android.content.res.Resources
+import android.os.Build.VERSION.SDK_INT
+import android.util.Log
+import android.util.SizeF
+import android.widget.RemoteViews
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
+import androidx.core.util.SizeFCompat
+import kotlin.math.ceil
+
+/** Returns whether this size is approximately at least as big as [other] in all dimensions. */
+internal infix fun SizeFCompat.approxDominates(other: SizeFCompat): Boolean {
+    return ceil(width) + 1 >= other.width && ceil(height) + 1 >= other.height
+}
+
+internal val SizeFCompat.area: Float
+    get() = width * height
+
+/**
+ * Updates the app widget with [appWidgetId], creating a [RemoteViews] for each size assigned to
+ * the app widget by [AppWidgetManager], invoking [factory] to create each alternative view.
+ *
+ * This provides ["exact" sizing](https://developer.android.com/guide/topics/appwidgets/layouts#provide-exact-layouts)
+ * , which allows you to tailor your app widget appearance to the exact size at which it is
+ * displayed. If you are only concerned with a small number of size thresholds, it is preferable
+ * to use "responsive" sizing by providing a fixed set of sizes that your app widget supports.
+ *
+ * As your [factory] may be invoked multiple times, if there is expensive computation of state that
+ * is shared among each size, it is recommended to perform that computation before calling this
+ * and cache the results as necessary.
+ *
+ * To handle resizing of your app widget, it is necessary to call this function during both
+ * [android.appwidget.AppWidgetProvider.onUpdate] and
+ * [android.appwidget.AppWidgetProvider.onAppWidgetOptionsChanged].
+ *
+ * @param appWidgetId the id of the app widget
+ * @param factory a function to create a [RemoteViews] for a given width and height (in dp)
+ */
+public fun AppWidgetManager.updateAppWidget(
+    appWidgetId: Int,
+    factory: (SizeFCompat) -> RemoteViews
+) {
+    updateAppWidget(appWidgetId, createExactSizeAppWidget(this, appWidgetId, factory))
+}
+
+/**
+ * Creates a [RemoteViews] associated with each size assigned to the app widget by
+ * [AppWidgetManager], invoking [factory] to create each alternative view.
+ *
+ * This provides ["exact" sizing](https://developer.android.com/guide/topics/appwidgets/layouts#provide-exact-layouts)
+ * , which allows you to tailor your app widget appearance to the exact size at which it is
+ * displayed. If you are only concerned with a small number of size thresholds, it is preferable
+ * to use "responsive" sizing by providing a fixed set of sizes that your app widget supports.
+ *
+ * As your [factory] may be invoked multiple times, if there is expensive computation of state that
+ * is shared among each size, it is recommended to perform that computation before calling this
+ * and cache the results as necessary.
+ *
+ * To handle resizing of your app widget, it is necessary to call [AppWidgetManager.updateAppWidget]
+ * during both [android.appwidget.AppWidgetProvider.onUpdate] and
+ * [android.appwidget.AppWidgetProvider.onAppWidgetOptionsChanged].
+ *
+ * @param appWidgetManager the [AppWidgetManager] to provide information about [appWidgetId]
+ * @param appWidgetId the id of the app widget
+ * @param factory a function to create a [RemoteViews] for a given width and height (in dp)
+ */
+public fun createExactSizeAppWidget(
+    appWidgetManager: AppWidgetManager,
+    appWidgetId: Int,
+    factory: (SizeFCompat) -> RemoteViews
+): RemoteViews {
+    appWidgetManager.requireValidAppWidgetId(appWidgetId)
+    return when {
+        SDK_INT >= 31 -> {
+            AppWidgetManagerApi31Impl.createExactSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                factory
+            )
+        }
+        SDK_INT >= 16 -> {
+            AppWidgetManagerApi16Impl.createExactSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                factory
+            )
+        }
+        else -> createAppWidgetFromProviderInfo(appWidgetManager, appWidgetId, factory)
+    }
+}
+
+/**
+ * Updates the app widget with [appWidgetId], creating a [RemoteViews] for each size provided in
+ * [dpSizes].
+ *
+ * This provides ["responsive" sizing](https://developer.android.com/guide/topics/appwidgets/layouts#provide-responsive-layouts)
+ * , which allows for smoother resizing and a more consistent experience across different host
+ * configurations.
+ *
+ * As your [factory] may be invoked multiple times, if there is expensive computation of state that
+ * is shared among each size, it is recommended to perform that computation before calling this
+ * and cache the results as necessary.
+ *
+ * To handle resizing of your app widget, it is necessary to call this function during both
+ * [android.appwidget.AppWidgetProvider.onUpdate] and
+ * [android.appwidget.AppWidgetProvider.onAppWidgetOptionsChanged]. If your app's minSdk is 31 or
+ * higher, it is only necessary to call this function during `onUpdate`.
+ *
+ * @param appWidgetId the id of the app widget
+ * @param dpSizes a collection of sizes (in dp) that your app widget supports. Must not be empty or
+ * contain more than 16 elements.
+ * @param factory a function to create a [RemoteViews] for a given width and height (in dp). It is
+ * guaranteed that [factory] will only ever be called with the values provided in [dpSizes].
+ */
+public fun AppWidgetManager.updateAppWidget(
+    appWidgetId: Int,
+    dpSizes: Collection<SizeFCompat>,
+    factory: (SizeFCompat) -> RemoteViews
+) {
+    updateAppWidget(appWidgetId, createResponsiveSizeAppWidget(this, appWidgetId, dpSizes, factory))
+}
+
+/**
+ * Creating a [RemoteViews] associated with each size provided in [dpSizes].
+ *
+ * This provides ["responsive" sizing](https://developer.android.com/guide/topics/appwidgets/layouts#provide-responsive-layouts)
+ * , which allows for smoother resizing and a more consistent experience across different host
+ * configurations.
+ *
+ * As your [factory] may be invoked multiple times, if there is expensive computation of state that
+ * is shared among each size, it is recommended to perform that computation before calling this
+ * and cache the results as necessary.
+ *
+ * To handle resizing of your app widget, it is necessary to call [AppWidgetManager.updateAppWidget]
+ * during both [android.appwidget.AppWidgetProvider.onUpdate] and
+ * [android.appwidget.AppWidgetProvider.onAppWidgetOptionsChanged]. If your app's minSdk is 31 or
+ * higher, it is only necessary to call `updateAppWidget` during `onUpdate`.
+ *
+ * @param appWidgetManager the [AppWidgetManager] to provide information about [appWidgetId]
+ * @param appWidgetId the id of the app widget
+ * @param dpSizes a collection of sizes (in dp) that your app widget supports. Must not be empty or
+ * contain more than 16 elements.
+ * @param factory a function to create a [RemoteViews] for a given width and height (in dp). It is
+ * guaranteed that [factory] will only ever be called with the values provided in [dpSizes].
+ */
+public fun createResponsiveSizeAppWidget(
+    appWidgetManager: AppWidgetManager,
+    appWidgetId: Int,
+    dpSizes: Collection<SizeFCompat>,
+    factory: (SizeFCompat) -> RemoteViews
+): RemoteViews {
+    appWidgetManager.requireValidAppWidgetId(appWidgetId)
+    require(dpSizes.isNotEmpty()) { "Sizes cannot be empty" }
+    require(dpSizes.size <= 16) { "At most 16 sizes may be provided" }
+    return when {
+        SDK_INT >= 31 -> AppWidgetManagerApi31Impl.createResponsiveSizeAppWidget(dpSizes, factory)
+        SDK_INT >= 16 -> {
+            AppWidgetManagerApi16Impl.createResponsiveSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                dpSizes,
+                factory
+            )
+        }
+        else -> createAppWidgetFromProviderInfo(appWidgetManager, appWidgetId, factory)
+    }
+}
+
+private fun AppWidgetManager.requireValidAppWidgetId(appWidgetId: Int) {
+    requireNotNull(getAppWidgetInfo(appWidgetId)) { "Invalid app widget id: $appWidgetId" }
+}
+
+@RequiresApi(31)
+private object AppWidgetManagerApi31Impl {
+    @DoNotInline
+    fun createExactSizeAppWidget(
+        appWidgetManager: AppWidgetManager,
+        appWidgetId: Int,
+        factory: (SizeFCompat) -> RemoteViews
+    ): RemoteViews {
+        val options = appWidgetManager.getAppWidgetOptions(appWidgetId)
+        val sizes = options.getParcelableArrayList<SizeF>(AppWidgetManager.OPTION_APPWIDGET_SIZES)
+        if (sizes.isNullOrEmpty()) {
+            Log.w(
+                LogTag,
+                "App widget SizeF sizes not found in the options bundle, falling back to the " +
+                    "min/max sizes"
+            )
+            return AppWidgetManagerApi16Impl.createExactSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                factory
+            )
+        }
+        return RemoteViews(sizes.associateWith { factory(it.toSizeFCompat()) })
+    }
+
+    @DoNotInline
+    fun createResponsiveSizeAppWidget(
+        dpSizes: Collection<SizeFCompat>,
+        factory: (SizeFCompat) -> RemoteViews
+    ): RemoteViews {
+        return RemoteViews(dpSizes.associate { it.toSizeF() to factory(it) })
+    }
+
+    private fun SizeF.toSizeFCompat() = SizeFCompat.createFromSizeF(this)
+}
+
+@RequiresApi(16)
+private object AppWidgetManagerApi16Impl {
+    @DoNotInline
+    fun createExactSizeAppWidget(
+        appWidgetManager: AppWidgetManager,
+        appWidgetId: Int,
+        factory: (SizeFCompat) -> RemoteViews
+    ): RemoteViews {
+        val (landscapeSize, portraitSize) =
+            getSizesFromOptionsBundle(appWidgetManager, appWidgetId)
+                ?: run {
+                    Log.w(
+                        LogTag,
+                        "App widget sizes not found in the options bundle, falling back to the " +
+                            "provider size"
+                    )
+                    return createAppWidgetFromProviderInfo(appWidgetManager, appWidgetId, factory)
+                }
+        return createAppWidget(landscapeSize = landscapeSize, portraitSize = portraitSize, factory)
+    }
+
+    @DoNotInline
+    fun createResponsiveSizeAppWidget(
+        appWidgetManager: AppWidgetManager,
+        appWidgetId: Int,
+        sizes: Collection<SizeFCompat>,
+        factory: (SizeFCompat) -> RemoteViews
+    ): RemoteViews {
+        val minSize = sizes.minByOrNull { it.area } ?: error("Sizes cannot be empty")
+        val (landscapeSize, portraitSize) =
+            getSizesFromOptionsBundle(appWidgetManager, appWidgetId)
+                ?: run {
+                    Log.w(
+                        LogTag,
+                        "App widget sizes not found in the options bundle, falling back to the " +
+                            "smallest supported size ($minSize)"
+                    )
+                    LandscapePortraitSizes(minSize, minSize)
+                }
+        val effectiveLandscapeSize =
+            sizes.filter { landscapeSize approxDominates it }.maxByOrNull { it.area } ?: minSize
+        val effectivePortraitSize =
+            sizes.filter { portraitSize approxDominates it }.maxByOrNull { it.area } ?: minSize
+        return createAppWidget(
+            landscapeSize = effectiveLandscapeSize,
+            portraitSize = effectivePortraitSize,
+            factory
+        )
+    }
+
+    private fun createAppWidget(
+        landscapeSize: SizeFCompat,
+        portraitSize: SizeFCompat,
+        factory: (SizeFCompat) -> RemoteViews
+    ): RemoteViews {
+        return if (landscapeSize == portraitSize) {
+            factory(landscapeSize)
+        } else {
+            RemoteViews(
+                /* landscape= */ factory(landscapeSize),
+                /* portrait= */ factory(portraitSize)
+            )
+        }
+    }
+
+    private fun getSizesFromOptionsBundle(
+        appWidgetManager: AppWidgetManager,
+        appWidgetId: Int
+    ): LandscapePortraitSizes? {
+        val options = appWidgetManager.getAppWidgetOptions(appWidgetId)
+
+        val portWidthDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, -1)
+        val portHeightDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, -1)
+        if (portWidthDp < 0 || portHeightDp < 0) return null
+
+        val landWidthDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, -1)
+        val landHeightDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, -1)
+        if (landWidthDp < 0 || landHeightDp < 0) return null
+
+        return LandscapePortraitSizes(
+            landscape = SizeFCompat(landWidthDp.toFloat(), landHeightDp.toFloat()),
+            portrait = SizeFCompat(portWidthDp.toFloat(), portHeightDp.toFloat())
+        )
+    }
+}
+
+internal fun createAppWidgetFromProviderInfo(
+    appWidgetManager: AppWidgetManager,
+    appWidgetId: Int,
+    factory: (SizeFCompat) -> RemoteViews
+): RemoteViews {
+    return factory(appWidgetManager.getSizeFromProviderInfo(appWidgetId))
+}
+
+internal fun AppWidgetManager.getSizeFromProviderInfo(appWidgetId: Int): SizeFCompat {
+    val providerInfo = getAppWidgetInfo(appWidgetId)
+    fun pxToDp(value: Int) = (value / Resources.getSystem().displayMetrics.density)
+    val width = pxToDp(providerInfo.minWidth)
+    val height = pxToDp(providerInfo.minHeight)
+    return SizeFCompat(width, height)
+}
+
+internal data class LandscapePortraitSizes(val landscape: SizeFCompat, val portrait: SizeFCompat)
+
+private const val LogTag = "AppWidgetManagerCompat"
diff --git a/core/core-remoteviews/src/test/java/androidx/core/widget/AppWidgetManagerCompatTest.kt b/core/core-remoteviews/src/test/java/androidx/core/widget/AppWidgetManagerCompatTest.kt
new file mode 100644
index 0000000..9b160b0
--- /dev/null
+++ b/core/core-remoteviews/src/test/java/androidx/core/widget/AppWidgetManagerCompatTest.kt
@@ -0,0 +1,283 @@
+/*
+ * 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.core.widget
+
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
+import android.appwidget.AppWidgetProviderInfo
+import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Configuration.ORIENTATION_LANDSCAPE
+import android.content.res.Configuration.ORIENTATION_PORTRAIT
+import android.os.Bundle
+import android.widget.FrameLayout
+import android.widget.RemoteViews
+import android.widget.TextView
+import androidx.annotation.RequiresApi
+import androidx.core.remoteviews.test.R
+import androidx.core.util.SizeFCompat
+import androidx.core.util.component1
+import androidx.core.util.component2
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.Shadows.shadowOf
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.util.ReflectionHelpers
+import kotlin.test.assertFailsWith
+
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(sdk = [17])
+@RequiresApi(17)
+class AppWidgetManagerCompatTest {
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+    private val packageName = context.packageName
+    private val appWidgetManager = AppWidgetManager.getInstance(context)
+    private val appWidgetId = 1
+    private val landscapeContext = configurationContext { orientation = ORIENTATION_LANDSCAPE }
+    private val portraitContext = configurationContext { orientation = ORIENTATION_PORTRAIT }
+
+    @Test
+    fun exact_oneSize_shouldUpdateRemoteViewsWithoutLandPort() {
+        setWidgetSize(100 x 200)
+
+        val rv = createExactSizeAppWidget(appWidgetManager, appWidgetId) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        assertThat(rv.landscape).isNull()
+        assertThat(rv.portrait).isNull()
+    }
+
+    @Test
+    fun exact_multipleSizes_shouldUpdateRemoteViewsWithLandPort() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        val rv = createExactSizeAppWidget(appWidgetManager, appWidgetId) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        assertThat(rv.landscape).isNotNull()
+        assertThat(rv.portrait).isNotNull()
+    }
+
+    @Test
+    fun exact_multipleSizes_shouldUseLandscapeSizeForLandscapeView() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        val rv = createExactSizeAppWidget(appWidgetManager, appWidgetId) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        val view = rv.apply(landscapeContext, FrameLayout(landscapeContext))
+        assertThat(view.findViewById<TextView>(R.id.text).text.toString())
+            .isEqualTo("200.0 x 100.0")
+    }
+
+    @Test
+    fun exact_multipleSizes_shouldUsePortraitSizeForPortraitView() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        val rv = createExactSizeAppWidget(appWidgetManager, appWidgetId) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        val view = rv.apply(portraitContext, FrameLayout(portraitContext))
+        assertThat(view.findViewById<TextView>(R.id.text).text.toString())
+            .isEqualTo("110.0 x 190.0")
+    }
+
+    @Test
+    fun exact_invalidWidget_shouldThrow() {
+        assertFailsWith<IllegalArgumentException> {
+            createExactSizeAppWidget(appWidgetManager, appWidgetId) { (width, height) ->
+                remoteViews {
+                    setTextViewText(R.id.text, "$width x $height")
+                }
+            }
+        }
+    }
+
+    @Test
+    fun responsive_singleSizeFromLauncher_shouldChooseBestFitAsSingleRemoteViews() {
+        setWidgetSize(100 x 200)
+
+        val rv = createResponsiveSizeAppWidget(
+            appWidgetManager,
+            appWidgetId,
+            listOf(50 x 50, 75 x 75, 120 x 140)
+        ) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        assertThat(rv.landscape).isNull()
+        assertThat(rv.portrait).isNull()
+        val view = rv.apply(context, FrameLayout(context))
+        assertThat(view.findViewById<TextView>(R.id.text).text.toString())
+            .isEqualTo("75.0 x 75.0")
+    }
+
+    @Test
+    fun responsive_multipleSizesFromLauncher_bestFitIsSameForBoth_shouldChooseBestFitAsSingle() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        val rv = createResponsiveSizeAppWidget(
+            appWidgetManager,
+            appWidgetId,
+            listOf(50 x 50, 75 x 75, 120 x 140)
+        ) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        assertThat(rv.landscape).isNull()
+        assertThat(rv.portrait).isNull()
+        val view = rv.apply(context, FrameLayout(context))
+        assertThat(view.findViewById<TextView>(R.id.text).text.toString()).isEqualTo("75.0 x 75.0")
+    }
+
+    @Test
+    fun responsive_multipleSizesFromLauncher_bestFitIsDifferent_shouldChooseBestFitsAsLandPort() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        val rv = createResponsiveSizeAppWidget(
+            appWidgetManager,
+            appWidgetId,
+            listOf(50 x 50, 75 x 75, 120 x 100)
+        ) { (width, height) ->
+            remoteViews {
+                setTextViewText(R.id.text, "$width x $height")
+            }
+        }
+
+        assertThat(rv.landscape).isNotNull()
+        assertThat(rv.portrait).isNotNull()
+        val landView = rv.apply(landscapeContext, FrameLayout(landscapeContext))
+        assertThat(landView.findViewById<TextView>(R.id.text).text.toString())
+            .isEqualTo("120.0 x 100.0")
+        val portView = rv.apply(portraitContext, FrameLayout(portraitContext))
+        assertThat(portView.findViewById<TextView>(R.id.text).text.toString())
+            .isEqualTo("75.0 x 75.0")
+    }
+
+    @Test
+    fun responsive_noSizes_shouldThrow() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        assertFailsWith<IllegalArgumentException> {
+            createResponsiveSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                emptyList()
+            ) { (width, height) ->
+                remoteViews {
+                    setTextViewText(R.id.text, "$width x $height")
+                }
+            }
+        }
+    }
+
+    @Test
+    fun responsive_tooManySizes_shouldThrow() {
+        setWidgetSize(landscape = 200 x 100, portrait = 110 x 190)
+
+        assertFailsWith<IllegalArgumentException> {
+            createResponsiveSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                (1..17).map { it x it }
+            ) { (width, height) ->
+                remoteViews {
+                    setTextViewText(R.id.text, "$width x $height")
+                }
+            }
+        }
+    }
+
+    @Test
+    fun responsive_invalidWidget_shouldThrow() {
+        assertFailsWith<IllegalArgumentException> {
+            createResponsiveSizeAppWidget(
+                appWidgetManager,
+                appWidgetId,
+                listOf(100 x 100)
+            ) { (width, height) ->
+                remoteViews {
+                    setTextViewText(R.id.text, "$width x $height")
+                }
+            }
+        }
+    }
+
+    private fun setWidgetSize(landscape: SizeFCompat, portrait: SizeFCompat? = null) {
+        shadowOf(appWidgetManager).addBoundWidget(appWidgetId, AppWidgetProviderInfo())
+        appWidgetManager.updateAppWidgetOptions(
+            appWidgetId,
+            Bundle().apply {
+                putInt(OPTION_APPWIDGET_MAX_WIDTH, landscape.width.toInt())
+                putInt(OPTION_APPWIDGET_MIN_HEIGHT, landscape.height.toInt())
+
+                putInt(
+                    OPTION_APPWIDGET_MIN_WIDTH,
+                    portrait?.width?.toInt() ?: landscape.width.toInt()
+                )
+                putInt(
+                    OPTION_APPWIDGET_MAX_HEIGHT,
+                    portrait?.height?.toInt() ?: landscape.height.toInt()
+                )
+            }
+        )
+    }
+
+    private infix fun Int.x(other: Int) = SizeFCompat(this.toFloat(), other.toFloat())
+
+    private fun remoteViews(modifier: RemoteViews.() -> Unit = {}): RemoteViews {
+        return RemoteViews(packageName, R.layout.remote_views).apply(modifier)
+    }
+
+    private val RemoteViews.landscape: RemoteViews?
+        get() = ReflectionHelpers.getField(this, "mLandscape")
+
+    private val RemoteViews.portrait: RemoteViews?
+        get() = ReflectionHelpers.getField(this, "mPortrait")
+
+    @RequiresApi(17)
+    private fun configurationContext(modifier: Configuration.() -> Unit): Context {
+        val configuration = Configuration()
+        configuration.apply(modifier)
+        return context.createConfigurationContext(configuration)
+    }
+}
\ No newline at end of file
diff --git a/core/core-splashscreen/src/main/java/androidx/core/splashscreen/SplashScreen.kt b/core/core-splashscreen/src/main/java/androidx/core/splashscreen/SplashScreen.kt
index 57fef19..46694db 100644
--- a/core/core-splashscreen/src/main/java/androidx/core/splashscreen/SplashScreen.kt
+++ b/core/core-splashscreen/src/main/java/androidx/core/splashscreen/SplashScreen.kt
@@ -65,7 +65,7 @@
          * This needs to be called before [Activity.setContentView] or other view operation on
          * the root view (e.g setting flags).
          *
-         * Alternatively, if a [SplashScreen] instance is not required, the them can manually be
+         * Alternatively, if a [SplashScreen] instance is not required, the theme can manually be
          * set using [Activity.setTheme].
          */
         @JvmStatic
@@ -343,4 +343,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index e2580ac..399b948 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1106,9 +1106,11 @@
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
+    method public boolean isExcludedFrom(int);
     method public boolean isImmutable();
     method public boolean isPinned();
     method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+    field public static final int SURFACE_LAUNCHER = 1; // 0x1
   }
 
   public static class ShortcutInfoCompat.Builder {
@@ -1120,12 +1122,12 @@
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedSurfaces(int);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
-    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsHiddenFromLauncher(boolean);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
     method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
@@ -2030,6 +2032,14 @@
     method public boolean test(T!);
   }
 
+  public final class SizeFCompat {
+    ctor public SizeFCompat(float, float);
+    method @RequiresApi(21) public static androidx.core.util.SizeFCompat createFromSizeF(android.util.SizeF);
+    method public float getHeight();
+    method public float getWidth();
+    method @RequiresApi(21) public android.util.SizeF toSizeF();
+  }
+
   public interface Supplier<T> {
     method public T! get();
   }
@@ -2040,29 +2050,29 @@
 
   public class AccessibilityDelegateCompat {
     ctor public AccessibilityDelegateCompat();
-    method public boolean dispatchPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat! getAccessibilityNodeProvider(android.view.View!);
-    method public void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public void onInitializeAccessibilityNodeInfo(android.view.View!, androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
-    method public void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean performAccessibilityAction(android.view.View!, int, android.os.Bundle!);
-    method public void sendAccessibilityEvent(android.view.View!, int);
-    method public void sendAccessibilityEventUnchecked(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+    method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+    method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle);
+    method public void sendAccessibilityEvent(android.view.View, int);
+    method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
   }
 
   public abstract class ActionProvider {
-    ctor public ActionProvider(android.content.Context!);
-    method public android.content.Context! getContext();
+    ctor public ActionProvider(android.content.Context);
+    method public android.content.Context getContext();
     method public boolean hasSubMenu();
     method public boolean isVisible();
-    method public abstract android.view.View! onCreateActionView();
-    method public android.view.View! onCreateActionView(android.view.MenuItem!);
+    method public abstract android.view.View onCreateActionView();
+    method public android.view.View onCreateActionView(android.view.MenuItem);
     method public boolean onPerformDefaultAction();
-    method public void onPrepareSubMenu(android.view.SubMenu!);
+    method public void onPrepareSubMenu(android.view.SubMenu);
     method public boolean overridesItemVisibility();
     method public void refreshVisibility();
-    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener!);
+    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
   }
 
   public static interface ActionProvider.VisibilityListener {
@@ -2112,7 +2122,7 @@
   }
 
   public final class DisplayCutoutCompat {
-    ctor public DisplayCutoutCompat(android.graphics.Rect!, java.util.List<android.graphics.Rect!>!);
+    ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
     ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
     method public java.util.List<android.graphics.Rect!> getBoundingRects();
     method public int getSafeInsetBottom();
@@ -2127,16 +2137,16 @@
   }
 
   public class DragStartHelper {
-    ctor public DragStartHelper(android.view.View!, androidx.core.view.DragStartHelper.OnDragStartListener!);
+    ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
     method public void attach();
     method public void detach();
-    method public void getTouchPosition(android.graphics.Point!);
-    method public boolean onLongClick(android.view.View!);
-    method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+    method public void getTouchPosition(android.graphics.Point);
+    method public boolean onLongClick(android.view.View);
+    method public boolean onTouch(android.view.View, android.view.MotionEvent);
   }
 
   public static interface DragStartHelper.OnDragStartListener {
-    method public boolean onDragStart(android.view.View!, androidx.core.view.DragStartHelper!);
+    method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
   }
 
   public final class GestureDetectorCompat {
@@ -3431,9 +3441,9 @@
 package androidx.core.view.animation {
 
   public final class PathInterpolatorCompat {
-    method public static android.view.animation.Interpolator! create(android.graphics.Path!);
-    method public static android.view.animation.Interpolator! create(float, float);
-    method public static android.view.animation.Interpolator! create(float, float, float, float);
+    method public static android.view.animation.Interpolator create(android.graphics.Path);
+    method public static android.view.animation.Interpolator create(float, float);
+    method public static android.view.animation.Interpolator create(float, float, float, float);
   }
 
 }
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index 98fa24a..03bbcc0 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -1106,9 +1106,11 @@
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
+    method public boolean isExcludedFrom(int);
     method public boolean isImmutable();
     method public boolean isPinned();
     method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+    field public static final int SURFACE_LAUNCHER = 1; // 0x1
   }
 
   public static class ShortcutInfoCompat.Builder {
@@ -1120,12 +1122,12 @@
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedSurfaces(int);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
-    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsHiddenFromLauncher(boolean);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
     method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
@@ -2034,6 +2036,14 @@
     method public boolean test(T!);
   }
 
+  public final class SizeFCompat {
+    ctor public SizeFCompat(float, float);
+    method @RequiresApi(21) public static androidx.core.util.SizeFCompat createFromSizeF(android.util.SizeF);
+    method public float getHeight();
+    method public float getWidth();
+    method @RequiresApi(21) public android.util.SizeF toSizeF();
+  }
+
   public interface Supplier<T> {
     method public T! get();
   }
@@ -2044,29 +2054,29 @@
 
   public class AccessibilityDelegateCompat {
     ctor public AccessibilityDelegateCompat();
-    method public boolean dispatchPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat! getAccessibilityNodeProvider(android.view.View!);
-    method public void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public void onInitializeAccessibilityNodeInfo(android.view.View!, androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
-    method public void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean performAccessibilityAction(android.view.View!, int, android.os.Bundle!);
-    method public void sendAccessibilityEvent(android.view.View!, int);
-    method public void sendAccessibilityEventUnchecked(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+    method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+    method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle);
+    method public void sendAccessibilityEvent(android.view.View, int);
+    method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
   }
 
   public abstract class ActionProvider {
-    ctor public ActionProvider(android.content.Context!);
-    method public android.content.Context! getContext();
+    ctor public ActionProvider(android.content.Context);
+    method public android.content.Context getContext();
     method public boolean hasSubMenu();
     method public boolean isVisible();
-    method public abstract android.view.View! onCreateActionView();
-    method public android.view.View! onCreateActionView(android.view.MenuItem!);
+    method public abstract android.view.View onCreateActionView();
+    method public android.view.View onCreateActionView(android.view.MenuItem);
     method public boolean onPerformDefaultAction();
-    method public void onPrepareSubMenu(android.view.SubMenu!);
+    method public void onPrepareSubMenu(android.view.SubMenu);
     method public boolean overridesItemVisibility();
     method public void refreshVisibility();
-    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener!);
+    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
   }
 
   public static interface ActionProvider.VisibilityListener {
@@ -2116,7 +2126,7 @@
   }
 
   public final class DisplayCutoutCompat {
-    ctor public DisplayCutoutCompat(android.graphics.Rect!, java.util.List<android.graphics.Rect!>!);
+    ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
     ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
     method public java.util.List<android.graphics.Rect!> getBoundingRects();
     method public int getSafeInsetBottom();
@@ -2131,16 +2141,16 @@
   }
 
   public class DragStartHelper {
-    ctor public DragStartHelper(android.view.View!, androidx.core.view.DragStartHelper.OnDragStartListener!);
+    ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
     method public void attach();
     method public void detach();
-    method public void getTouchPosition(android.graphics.Point!);
-    method public boolean onLongClick(android.view.View!);
-    method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+    method public void getTouchPosition(android.graphics.Point);
+    method public boolean onLongClick(android.view.View);
+    method public boolean onTouch(android.view.View, android.view.MotionEvent);
   }
 
   public static interface DragStartHelper.OnDragStartListener {
-    method public boolean onDragStart(android.view.View!, androidx.core.view.DragStartHelper!);
+    method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
   }
 
   public final class GestureDetectorCompat {
@@ -3435,9 +3445,9 @@
 package androidx.core.view.animation {
 
   public final class PathInterpolatorCompat {
-    method public static android.view.animation.Interpolator! create(android.graphics.Path!);
-    method public static android.view.animation.Interpolator! create(float, float);
-    method public static android.view.animation.Interpolator! create(float, float, float, float);
+    method public static android.view.animation.Interpolator create(android.graphics.Path);
+    method public static android.view.animation.Interpolator create(float, float);
+    method public static android.view.animation.Interpolator create(float, float, float, float);
   }
 
 }
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 65f68dd..85539f6 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -1226,9 +1226,11 @@
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
+    method public boolean isExcludedFrom(@androidx.core.content.pm.ShortcutInfoCompat.Surface int);
     method public boolean isImmutable();
     method public boolean isPinned();
     method @RequiresApi(25) public android.content.pm.ShortcutInfo! toShortcutInfo();
+    field public static final int SURFACE_LAUNCHER = 1; // 0x1
   }
 
   public static class ShortcutInfoCompat.Builder {
@@ -1242,12 +1244,12 @@
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setAlwaysBadged();
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setCategories(java.util.Set<java.lang.String!>);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(CharSequence);
+    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExcludedSurfaces(int);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setExtras(android.os.PersistableBundle);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIcon(androidx.core.graphics.drawable.IconCompat!);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent![]);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsConversation();
-    method public androidx.core.content.pm.ShortcutInfoCompat.Builder setIsHiddenFromLauncher(boolean);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLocusId(androidx.core.content.LocusIdCompat?);
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLabel(CharSequence);
     method @Deprecated public androidx.core.content.pm.ShortcutInfoCompat.Builder setLongLived();
@@ -1259,6 +1261,9 @@
     method public androidx.core.content.pm.ShortcutInfoCompat.Builder setSliceUri(android.net.Uri);
   }
 
+  @IntDef({androidx.core.content.pm.ShortcutInfoCompat.SURFACE_LAUNCHER}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ShortcutInfoCompat.Surface {
+  }
+
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class ShortcutInfoCompatSaver<T> {
     ctor public ShortcutInfoCompatSaver();
     method @AnyThread public abstract T! addShortcuts(java.util.List<androidx.core.content.pm.ShortcutInfoCompat!>!);
@@ -2400,6 +2405,7 @@
     method public static void checkArgument(boolean);
     method public static void checkArgument(boolean, Object);
     method public static void checkArgument(boolean, String, java.lang.Object!...);
+    method public static float checkArgumentFinite(float, String);
     method public static int checkArgumentInRange(int, int, int, String);
     method public static long checkArgumentInRange(long, long, long, String);
     method public static float checkArgumentInRange(float, float, float, String);
@@ -2420,6 +2426,14 @@
     method public boolean test(T!);
   }
 
+  public final class SizeFCompat {
+    ctor public SizeFCompat(float, float);
+    method @RequiresApi(21) public static androidx.core.util.SizeFCompat createFromSizeF(android.util.SizeF);
+    method public float getHeight();
+    method public float getWidth();
+    method @RequiresApi(21) public android.util.SizeF toSizeF();
+  }
+
   public interface Supplier<T> {
     method public T! get();
   }
@@ -2438,32 +2452,32 @@
 
   public class AccessibilityDelegateCompat {
     ctor public AccessibilityDelegateCompat();
-    ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public AccessibilityDelegateCompat(android.view.View.AccessibilityDelegate!);
-    method public boolean dispatchPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat! getAccessibilityNodeProvider(android.view.View!);
-    method public void onInitializeAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public void onInitializeAccessibilityNodeInfo(android.view.View!, androidx.core.view.accessibility.AccessibilityNodeInfoCompat!);
-    method public void onPopulateAccessibilityEvent(android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup!, android.view.View!, android.view.accessibility.AccessibilityEvent!);
-    method public boolean performAccessibilityAction(android.view.View!, int, android.os.Bundle!);
-    method public void sendAccessibilityEvent(android.view.View!, int);
-    method public void sendAccessibilityEventUnchecked(android.view.View!, android.view.accessibility.AccessibilityEvent!);
+    ctor @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public AccessibilityDelegateCompat(android.view.View.AccessibilityDelegate);
+    method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public androidx.core.view.accessibility.AccessibilityNodeProviderCompat? getAccessibilityNodeProvider(android.view.View);
+    method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public void onInitializeAccessibilityNodeInfo(android.view.View, androidx.core.view.accessibility.AccessibilityNodeInfoCompat);
+    method public void onPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean onRequestSendAccessibilityEvent(android.view.ViewGroup, android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean performAccessibilityAction(android.view.View, int, android.os.Bundle);
+    method public void sendAccessibilityEvent(android.view.View, int);
+    method public void sendAccessibilityEventUnchecked(android.view.View, android.view.accessibility.AccessibilityEvent);
   }
 
   public abstract class ActionProvider {
-    ctor public ActionProvider(android.content.Context!);
-    method public android.content.Context! getContext();
+    ctor public ActionProvider(android.content.Context);
+    method public android.content.Context getContext();
     method public boolean hasSubMenu();
     method public boolean isVisible();
-    method public abstract android.view.View! onCreateActionView();
-    method public android.view.View! onCreateActionView(android.view.MenuItem!);
+    method public abstract android.view.View onCreateActionView();
+    method public android.view.View onCreateActionView(android.view.MenuItem);
     method public boolean onPerformDefaultAction();
-    method public void onPrepareSubMenu(android.view.SubMenu!);
+    method public void onPrepareSubMenu(android.view.SubMenu);
     method public boolean overridesItemVisibility();
     method public void refreshVisibility();
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void reset();
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSubUiVisibilityListener(androidx.core.view.ActionProvider.SubUiVisibilityListener!);
-    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener!);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void setSubUiVisibilityListener(androidx.core.view.ActionProvider.SubUiVisibilityListener?);
+    method public void setVisibilityListener(androidx.core.view.ActionProvider.VisibilityListener?);
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public void subUiVisibilityChanged(boolean);
   }
 
@@ -2524,7 +2538,7 @@
   }
 
   public final class DisplayCutoutCompat {
-    ctor public DisplayCutoutCompat(android.graphics.Rect!, java.util.List<android.graphics.Rect!>!);
+    ctor public DisplayCutoutCompat(android.graphics.Rect?, java.util.List<android.graphics.Rect!>?);
     ctor public DisplayCutoutCompat(androidx.core.graphics.Insets, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, android.graphics.Rect?, androidx.core.graphics.Insets);
     method public java.util.List<android.graphics.Rect!> getBoundingRects();
     method public int getSafeInsetBottom();
@@ -2536,20 +2550,20 @@
 
   public final class DragAndDropPermissionsCompat {
     method public void release();
-    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.view.DragAndDropPermissionsCompat? request(android.app.Activity!, android.view.DragEvent!);
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.core.view.DragAndDropPermissionsCompat? request(android.app.Activity, android.view.DragEvent);
   }
 
   public class DragStartHelper {
-    ctor public DragStartHelper(android.view.View!, androidx.core.view.DragStartHelper.OnDragStartListener!);
+    ctor public DragStartHelper(android.view.View, androidx.core.view.DragStartHelper.OnDragStartListener);
     method public void attach();
     method public void detach();
-    method public void getTouchPosition(android.graphics.Point!);
-    method public boolean onLongClick(android.view.View!);
-    method public boolean onTouch(android.view.View!, android.view.MotionEvent!);
+    method public void getTouchPosition(android.graphics.Point);
+    method public boolean onLongClick(android.view.View);
+    method public boolean onTouch(android.view.View, android.view.MotionEvent);
   }
 
   public static interface DragStartHelper.OnDragStartListener {
-    method public boolean onDragStart(android.view.View!, androidx.core.view.DragStartHelper!);
+    method public boolean onDragStart(android.view.View, androidx.core.view.DragStartHelper);
   }
 
   public final class GestureDetectorCompat {
@@ -3891,9 +3905,9 @@
 package androidx.core.view.animation {
 
   public final class PathInterpolatorCompat {
-    method public static android.view.animation.Interpolator! create(android.graphics.Path!);
-    method public static android.view.animation.Interpolator! create(float, float);
-    method public static android.view.animation.Interpolator! create(float, float, float, float);
+    method public static android.view.animation.Interpolator create(android.graphics.Path);
+    method public static android.view.animation.Interpolator create(float, float);
+    method public static android.view.animation.Interpolator create(float, float, float, float);
   }
 
 }
diff --git a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutManagerCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutManagerCompatTest.java
index 4bb9442..ecd3d65 100644
--- a/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutManagerCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/pm/ShortcutManagerCompatTest.java
@@ -290,38 +290,39 @@
     @LargeTest
     @Test
     @SdkSuppress(minSdkVersion = 25)
-    public void testHiddenShortcuts() throws Throwable {
+    public void testExcludedShortcuts() throws Throwable {
         final ShortcutManager mockShortcutManager = mock(ShortcutManager.class);
         doReturn(mockShortcutManager).when(mContext).getSystemService(eq(Context.SHORTCUT_SERVICE));
+        when(mockShortcutManager.getMaxShortcutCountPerActivity()).thenReturn(5);
 
-        final ShortcutInfoCompat hiddenShortcut1 = new ShortcutInfoCompat.Builder(
+        final ShortcutInfoCompat excludedShortcut1 = new ShortcutInfoCompat.Builder(
                 mContext, "my-shortcut")
                 .setShortLabel("bitmap")
                 .setIcon(createBitmapIcon())
                 .setIntent(new Intent().setAction(Intent.ACTION_DEFAULT))
-                .setIsHiddenFromLauncher(true)
+                .setExcludedSurfaces(ShortcutInfoCompat.SURFACE_LAUNCHER)
                 .build();
-        final ShortcutInfoCompat hiddenShortcut2 = new ShortcutInfoCompat.Builder(
+        final ShortcutInfoCompat excludedShortcut2 = new ShortcutInfoCompat.Builder(
                 mContext, "my-shortcut-2")
                 .setShortLabel("bitmap")
                 .setIcon(createBitmapIcon())
                 .setIntent(new Intent().setAction(Intent.ACTION_DEFAULT))
-                .setIsHiddenFromLauncher(true)
+                .setExcludedSurfaces(ShortcutInfoCompat.SURFACE_LAUNCHER)
                 .build();
-        final ShortcutInfoCompat hiddenShortcut3 = new ShortcutInfoCompat.Builder(
+        final ShortcutInfoCompat excludedShortcut3 = new ShortcutInfoCompat.Builder(
                 mContext, "my-shortcut-3")
                 .setShortLabel("bitmap")
                 .setIcon(createBitmapIcon())
                 .setIntent(new Intent().setAction(Intent.ACTION_DEFAULT))
-                .setIsHiddenFromLauncher(true)
+                .setExcludedSurfaces(ShortcutInfoCompat.SURFACE_LAUNCHER)
                 .build();
 
-        final List<ShortcutInfoCompat> hiddenShortcuts = new ArrayList<>();
-        hiddenShortcuts.add(hiddenShortcut1);
-        hiddenShortcuts.add(hiddenShortcut2);
-        hiddenShortcuts.add(hiddenShortcut3);
+        final List<ShortcutInfoCompat> excludedShortcuts = new ArrayList<>();
+        excludedShortcuts.add(excludedShortcut1);
+        excludedShortcuts.add(excludedShortcut2);
+        excludedShortcuts.add(excludedShortcut3);
 
-        ShortcutManagerCompat.addDynamicShortcuts(mContext, hiddenShortcuts);
+        ShortcutManagerCompat.addDynamicShortcuts(mContext, excludedShortcuts);
         if (Build.VERSION.SDK_INT > 31) {
             verify(mockShortcutManager).addDynamicShortcuts(
                     ArgumentMatchers.<ShortcutInfo>anyList());
@@ -332,21 +333,25 @@
         reset(mockShortcutManager);
         when(mockShortcutManager.setDynamicShortcuts(ArgumentMatchers.<ShortcutInfo>anyList()))
                 .thenReturn(true);
+        when(mockShortcutManager.getMaxShortcutCountPerActivity()).thenReturn(5);
 
-        ShortcutManagerCompat.setDynamicShortcuts(mContext, hiddenShortcuts);
+        ShortcutManagerCompat.setDynamicShortcuts(mContext, excludedShortcuts);
         if (Build.VERSION.SDK_INT > 31) {
             verify(mockShortcutManager).setDynamicShortcuts(
                     ArgumentMatchers.<ShortcutInfo>anyList());
-        } else if (Build.VERSION.SDK_INT >= 25) {
-            verify(mockShortcutManager).setDynamicShortcuts(Collections.EMPTY_LIST);
+        } else {
+            if (Build.VERSION.SDK_INT >= 25) {
+                verify(mockShortcutManager).setDynamicShortcuts(Collections.EMPTY_LIST);
+            }
+            verify(mShortcutInfoCompatSaver).removeAllShortcuts();
+            verify(mShortcutInfoCompatSaver).addShortcuts(Collections.EMPTY_LIST);
         }
-        verify(mShortcutInfoCompatSaver).removeAllShortcuts();
         verify(mShortcutInfoChangeListener).onAllShortcutsRemoved();
-        verify(mShortcutInfoCompatSaver).addShortcuts(Collections.EMPTY_LIST);
-        verify(mShortcutInfoChangeListener).onShortcutAdded(hiddenShortcuts);
+        verify(mShortcutInfoChangeListener).onShortcutAdded(excludedShortcuts);
 
         reset(mockShortcutManager);
-        ShortcutManagerCompat.pushDynamicShortcut(mContext, hiddenShortcut1);
+        when(mockShortcutManager.getMaxShortcutCountPerActivity()).thenReturn(5);
+        ShortcutManagerCompat.pushDynamicShortcut(mContext, excludedShortcut1);
         if (Build.VERSION.SDK_INT > 31) {
             verify(mockShortcutManager).pushDynamicShortcut(any(ShortcutInfo.class));
         } else if (Build.VERSION.SDK_INT >= 30) {
@@ -357,7 +362,8 @@
         }
 
         reset(mockShortcutManager);
-        ShortcutManagerCompat.updateShortcuts(mContext, hiddenShortcuts);
+        when(mockShortcutManager.getMaxShortcutCountPerActivity()).thenReturn(5);
+        ShortcutManagerCompat.updateShortcuts(mContext, excludedShortcuts);
         if (Build.VERSION.SDK_INT > 31) {
             verify(mockShortcutManager).updateShortcuts(anyList());
         } else if (Build.VERSION.SDK_INT >= 25) {
@@ -365,7 +371,8 @@
         }
 
         reset(mockShortcutManager);
-        ShortcutManagerCompat.enableShortcuts(mContext, hiddenShortcuts);
+        when(mockShortcutManager.getMaxShortcutCountPerActivity()).thenReturn(5);
+        ShortcutManagerCompat.enableShortcuts(mContext, excludedShortcuts);
         if (Build.VERSION.SDK_INT > 31) {
             verify(mockShortcutManager).enableShortcuts(anyList());
         } else if (Build.VERSION.SDK_INT >= 25) {
diff --git a/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
index 3c5ea44..a0c489b 100644
--- a/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/AccessibilityDelegateCompatTest.java
@@ -47,6 +47,8 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.core.view.accessibility.AccessibilityEventCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
@@ -167,27 +169,29 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 27)
-    @FlakyTest(bugId = 187190911)
-    public void testAccessibilityPaneTitle_isntTrackedAsPaneWithoutTitle() {
-        // This test isn't to test the propagation up, just that the event is sent correctly
-        ViewCompat.setAccessibilityLiveRegion(mView,
-                ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE);
-
-        ViewCompat.setAccessibilityPaneTitle(mView, "Sample title");
-
-        ViewCompat.setAccessibilityPaneTitle(mView, null);
-
+    public void testAccessibilityPaneTitle_isntTrackedAsPaneWithoutTitle() throws Throwable {
+        // This test isn't to test the propagation up, just that the event-sending behavior
         final AccessibilityDelegateCompat mockDelegate = mock(
                 AccessibilityDelegateCompat.class);
-        ViewCompat.setAccessibilityDelegate(mView, new BridgingDelegateCompat(mockDelegate));
+        mActivityTestRule.runOnUiThread(() -> {
+            ViewCompat.setAccessibilityLiveRegion(mView,
+                    ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE);
 
-        mView.setVisibility(View.VISIBLE);
+            ViewCompat.setAccessibilityPaneTitle(mView, "Sample title");
 
-        mView.getViewTreeObserver().dispatchOnGlobalLayout();
-        ArgumentCaptor<AccessibilityEvent> argumentCaptor =
-                ArgumentCaptor.forClass(AccessibilityEvent.class);
-        verify(mockDelegate, never()).sendAccessibilityEventUnchecked(
-                eq(mView), argumentCaptor.capture());
+            ViewCompat.setAccessibilityPaneTitle(mView, null);
+
+            ViewCompat.setAccessibilityDelegate(mView, new BridgingDelegateCompat(mockDelegate));
+
+            mView.setVisibility(View.VISIBLE);
+
+            mView.getViewTreeObserver().dispatchOnGlobalLayout();
+
+            ArgumentCaptor<AccessibilityEvent> argumentCaptor =
+                    ArgumentCaptor.forClass(AccessibilityEvent.class);
+            verify(mockDelegate, never()).sendAccessibilityEventUnchecked(
+                    eq(mView), argumentCaptor.capture());
+        });
     }
 
     @Test
@@ -627,48 +631,54 @@
         }
 
         @Override
-        public void sendAccessibilityEvent(View host, int eventType) {
+        public void sendAccessibilityEvent(@NonNull View host, int eventType) {
             mMockCompat.sendAccessibilityEvent(host, eventType);
         }
 
         @Override
-        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
+        public void sendAccessibilityEventUnchecked(@NonNull View host,
+                @NonNull AccessibilityEvent event) {
             mMockCompat.sendAccessibilityEventUnchecked(host, event);
         }
 
         @Override
-        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+        public boolean dispatchPopulateAccessibilityEvent(
+                @NonNull View host, @NonNull AccessibilityEvent event) {
             return mMockCompat.dispatchPopulateAccessibilityEvent(host, event);
         }
 
         @Override
-        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+        public void onPopulateAccessibilityEvent(
+                @NonNull View host, @NonNull AccessibilityEvent event) {
             mMockCompat.onPopulateAccessibilityEvent(host, event);
         }
 
         @Override
-        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+        public void onInitializeAccessibilityEvent(
+                @NonNull View host, @NonNull AccessibilityEvent event) {
             mMockCompat.onInitializeAccessibilityEvent(host, event);
         }
 
         @Override
-        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
+        public void onInitializeAccessibilityNodeInfo(
+                @NonNull View host, @NonNull AccessibilityNodeInfoCompat info) {
             mMockCompat.onInitializeAccessibilityNodeInfo(host, info);
         }
 
         @Override
-        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
-                AccessibilityEvent event) {
+        public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
+                @NonNull AccessibilityEvent event) {
             return mMockCompat.onRequestSendAccessibilityEvent(host, child, event);
         }
 
         @Override
-        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {
+        public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(@NonNull View host) {
             return mMockCompat.getAccessibilityNodeProvider(host);
         }
 
         @Override
-        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+        public boolean performAccessibilityAction(
+                @NonNull View host, int action, @Nullable Bundle args) {
             return mMockCompat.performAccessibilityAction(host, action, args);
         }
     }
diff --git a/core/core/src/androidTest/java/androidx/core/view/DragStartHelperTest.java b/core/core/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
index abd2d15..b32fa94 100644
--- a/core/core/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/DragStartHelperTest.java
@@ -76,7 +76,7 @@
     private DragStartHelper createDragStartHelper(final DragStartListener listener) {
         return new DragStartHelper(mDragSource, new DragStartHelper.OnDragStartListener() {
             @Override
-            public boolean onDragStart(View v, DragStartHelper helper) {
+            public boolean onDragStart(@NonNull View v, @NonNull DragStartHelper helper) {
                 Point touchPosition = new Point();
                 helper.getTouchPosition(touchPosition);
                 return listener.onDragStart(v, helper, touchPosition);
diff --git a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
index 67c796886..e6fd010 100644
--- a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
@@ -31,6 +31,7 @@
 import android.os.UserHandle;
 import android.text.TextUtils;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -41,6 +42,8 @@
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.core.net.UriCompat;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -61,6 +64,17 @@
 
     private static final String EXTRA_SLICE_URI = "extraSliceUri";
 
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+    @IntDef({SURFACE_LAUNCHER})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Surface {}
+
+    /**
+     * Indicates system surfaces managed by a launcher app. e.g. Long-Press Menu.
+     */
+    public static final int SURFACE_LAUNCHER = 1 << 0;
+
     Context mContext;
     String mId;
     String mPackageName;
@@ -97,7 +111,7 @@
     boolean mIsEnabled = true;
     boolean mHasKeyFieldsOnly;
     int mDisabledReason;
-    boolean mIsHiddenFromLauncher;
+    int mExcludedSurfaces;
 
     ShortcutInfoCompat() { }
 
@@ -480,6 +494,13 @@
     }
 
     /**
+     * Return true if the shortcut is excluded from specified surface.
+     */
+    public boolean isExcludedFrom(@Surface final int surface) {
+        return (mExcludedSurfaces & surface) > 0;
+    }
+
+    /**
      * @hide
      */
     @RequiresApi(25)
@@ -546,7 +567,7 @@
             if (shortcutInfo.mExtras != null) {
                 mInfo.mExtras = shortcutInfo.mExtras;
             }
-            mInfo.mIsHiddenFromLauncher = shortcutInfo.mIsHiddenFromLauncher;
+            mInfo.mExcludedSurfaces = shortcutInfo.mExcludedSurfaces;
         }
 
         /**
@@ -788,20 +809,23 @@
         }
 
         /**
-         * Sets if a shortcut is considered hidden from Launcher. If so, shortcuts will be
-         * excluded from the search result of {@link android.content.pm.LauncherApps#getShortcuts(
-         * android.content.pm.LauncherApps.ShortcutQuery, UserHandle)}. This generally means the
-         * shortcut would not be displayed by a launcher app (e.g. in Long-Press menu), while remain
-         * visible in other surfaces such as assistant or on-device-intelligence.
+         * Sets which surfaces a shortcut will be excluded from.
          *
-         * <p>On API <= 31, shortcuts that are hidden from launcher are not actually sent to
-         * {@link ShortcutManager}. These shortcuts might still be made available to other surfaces
-         * via alternative means.
+         * If the shortcut is set to be excluded from {@link #SURFACE_LAUNCHER}, shortcuts will be
+         * excluded from the search result of {@link android.content.pm.LauncherApps#getShortcuts(
+         * android.content.pm.LauncherApps.ShortcutQuery, UserHandle)} and
+         * {@link android.content.pm.ShortcutManager#getShortcuts(int)}. This generally means the
+         * shortcut would not be displayed by a launcher app (e.g. in Long-Press menu), while
+         * remain visible in other surfaces such as assistant or on-device-intelligence.
+         *
+         * <p>On API <= 31, shortcuts that are excluded from {@link #SURFACE_LAUNCHER} are not
+         * actually sent to {@link ShortcutManager}. These shortcuts might still be made
+         * available to other surfaces via alternative means.
          */
         @SuppressWarnings("MissingGetterMatchingBuilder")
         @NonNull
-        public Builder setIsHiddenFromLauncher(boolean isHidden) {
-            mInfo.mIsHiddenFromLauncher = isHidden;
+        public Builder setExcludedSurfaces(final int surfaces) {
+            mInfo.mExcludedSurfaces = surfaces;
             return this;
         }
 
diff --git a/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java b/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
index adcad12..f730e64 100644
--- a/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
+++ b/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
@@ -188,7 +188,8 @@
      */
     public static boolean requestPinShortcut(@NonNull final Context context,
             @NonNull ShortcutInfoCompat shortcut, @Nullable final IntentSender callback) {
-        if (Build.VERSION.SDK_INT <= 31 && shortcut.mIsHiddenFromLauncher) {
+        if (Build.VERSION.SDK_INT <= 31
+                && shortcut.isExcludedFrom(ShortcutInfoCompat.SURFACE_LAUNCHER)) {
             // A shortcut that is not frequently used cannot be pinned to WorkSpace.
             return false;
         }
@@ -307,8 +308,8 @@
     /**
      * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with
      * the same IDs, each mutable shortcut is updated.
-     * <p>On API <= 31 Any shortcuts that are marked as hidden from launcher will not be passed to
-     * the {@link ShortcutManager}, but they might still be available to assistant and other
+     * <p>On API <= 31 Any shortcuts that are marked as excluded from launcher will not be passed
+     * to the {@link ShortcutManager}, but they might still be available to assistant and other
      * surfaces through alternative means.
      *
      * <p>This API will be rate-limited.
@@ -321,7 +322,8 @@
      */
     public static boolean addDynamicShortcuts(@NonNull Context context,
             @NonNull List<ShortcutInfoCompat> shortcutInfoList) {
-        final List<ShortcutInfoCompat> clone = excludesHiddenShortcuts(shortcutInfoList);
+        final List<ShortcutInfoCompat> clone = removeShortcutsExcludedFromSurface(
+                shortcutInfoList, ShortcutInfoCompat.SURFACE_LAUNCHER);
         if (Build.VERSION.SDK_INT <= 29) {
             convertUriIconsToBitmapIcons(context, clone);
         }
@@ -436,8 +438,8 @@
      * Publish the list of shortcuts.  All existing dynamic shortcuts from the caller app
      * will be replaced.  If there are already pinned shortcuts with the same IDs,
      * the mutable pinned shortcuts are updated.
-     * <p>On API <= 31 Any shortcuts that are marked as hidden from launcher will not be passed to
-     * the {@link ShortcutManager}, but they might still be available to assistant and other
+     * <p>On API <= 31 Any shortcuts that are marked as excluded from launcher will not be passed
+     * to the {@link ShortcutManager}, but they might still be available to assistant and other
      * surfaces through alternative means.
      *
      * <p>This API will be rate-limited.
@@ -460,7 +462,8 @@
             @NonNull final List<ShortcutInfoCompat> shortcutInfoList) {
         Preconditions.checkNotNull(context);
         Preconditions.checkNotNull(shortcutInfoList);
-        final List<ShortcutInfoCompat> clone = excludesHiddenShortcuts(shortcutInfoList);
+        final List<ShortcutInfoCompat> clone = removeShortcutsExcludedFromSurface(
+                shortcutInfoList, ShortcutInfoCompat.SURFACE_LAUNCHER);
         if (Build.VERSION.SDK_INT >= 25) {
             List<ShortcutInfo> shortcuts = new ArrayList<>(clone.size());
             for (ShortcutInfoCompat compat : clone) {
@@ -511,8 +514,8 @@
     /**
      * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or
      * dynamic, but they must not be immutable.
-     * <p>On API <= 31 Any shortcuts that are marked as hidden from launcher will not be passed to
-     * the {@link ShortcutManager}, but they might still be available to assistant and other
+     * <p>On API <= 31 Any shortcuts that are marked as excluded from launcher will not be passed
+     * to the {@link ShortcutManager}, but they might still be available to assistant and other
      * surfaces through alternative means.
      *
      * <p>This API will be rate-limited.
@@ -524,7 +527,8 @@
      */
     public static boolean updateShortcuts(@NonNull Context context,
             @NonNull List<ShortcutInfoCompat> shortcutInfoList) {
-        final List<ShortcutInfoCompat> clone = excludesHiddenShortcuts(shortcutInfoList);
+        final List<ShortcutInfoCompat> clone = removeShortcutsExcludedFromSurface(
+                shortcutInfoList, ShortcutInfoCompat.SURFACE_LAUNCHER);
         if (Build.VERSION.SDK_INT <= 29) {
             convertUriIconsToBitmapIcons(context, clone);
         }
@@ -613,7 +617,8 @@
     /**
      * Re-enable pinned shortcuts that were previously disabled.  If the target shortcuts
      * are already enabled, this method does nothing.
-     * <p>In API 31 and below any shortcuts that are marked as hidden from launcher will be ignored.
+     * <p>In API 31 and below any shortcuts that are marked as excluded from launcher will be
+     * ignored.
      *
      * Compatibility behavior:
      * <ul>
@@ -627,7 +632,8 @@
      */
     public static void enableShortcuts(@NonNull final Context context,
             @NonNull final List<ShortcutInfoCompat> shortcutInfoList) {
-        final List<ShortcutInfoCompat> clone = excludesHiddenShortcuts(shortcutInfoList);
+        final List<ShortcutInfoCompat> clone = removeShortcutsExcludedFromSurface(
+                shortcutInfoList, ShortcutInfoCompat.SURFACE_LAUNCHER);
         if (Build.VERSION.SDK_INT >= 25) {
             final ArrayList<String> shortcutIds = new ArrayList<>(shortcutInfoList.size());
             for (ShortcutInfoCompat shortcut : clone) {
@@ -742,7 +748,8 @@
         Preconditions.checkNotNull(context);
         Preconditions.checkNotNull(shortcut);
 
-        if (Build.VERSION.SDK_INT <= 31 && shortcut.mIsHiddenFromLauncher) {
+        if (Build.VERSION.SDK_INT <= 31
+                && shortcut.isExcludedFrom(ShortcutInfoCompat.SURFACE_LAUNCHER)) {
             for (ShortcutInfoChangeListener listener : getShortcutInfoListeners(context)) {
                 listener.onShortcutAdded(Collections.singletonList(shortcut));
             }
@@ -897,13 +904,13 @@
     }
 
     @NonNull
-    private static List<ShortcutInfoCompat> excludesHiddenShortcuts(
-            @NonNull final List<ShortcutInfoCompat> shortcuts) {
+    private static List<ShortcutInfoCompat> removeShortcutsExcludedFromSurface(
+            @NonNull final List<ShortcutInfoCompat> shortcuts, final int surfaces) {
         Objects.requireNonNull(shortcuts);
         if (Build.VERSION.SDK_INT > 31) return shortcuts;
         final List<ShortcutInfoCompat> clone = new ArrayList<>(shortcuts);
         for (ShortcutInfoCompat si: shortcuts) {
-            if (si.mIsHiddenFromLauncher) {
+            if (si.isExcludedFrom(surfaces)) {
                 clone.remove(si);
             }
         }
diff --git a/core/core/src/main/java/androidx/core/util/Preconditions.java b/core/core/src/main/java/androidx/core/util/Preconditions.java
index ce979e0..3461d12 100644
--- a/core/core/src/main/java/androidx/core/util/Preconditions.java
+++ b/core/core/src/main/java/androidx/core/util/Preconditions.java
@@ -336,6 +336,29 @@
         return value;
     }
 
+    /**
+     * Ensures that the argument floating point value is a finite number.
+     *
+     * <p>A finite number is defined to be both representable (that is, not NaN) and
+     * not infinite (that is neither positive or negative infinity).</p>
+     *
+     * @param value a floating point value
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated floating point value
+     *
+     * @throws IllegalArgumentException if {@code value} was not finite
+     */
+    public static float checkArgumentFinite(float value, @NonNull String valueName) {
+        if (Float.isNaN(value)) {
+            throw new IllegalArgumentException(valueName + " must not be NaN");
+        } else if (Float.isInfinite(value)) {
+            throw new IllegalArgumentException(valueName + " must not be infinite");
+        }
+
+        return value;
+    }
+
     private Preconditions() {
     }
 }
diff --git a/core/core/src/main/java/androidx/core/util/SizeFCompat.java b/core/core/src/main/java/androidx/core/util/SizeFCompat.java
new file mode 100644
index 0000000..124a1ec
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/util/SizeFCompat.java
@@ -0,0 +1,106 @@
+/*
+ * 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.core.util;
+
+import android.util.SizeF;
+
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+/**
+ * Immutable class for describing width and height dimensions in some arbitrary unit. Width and
+ * height are finite values stored as a floating point representation.
+ * <p>
+ * This is a backward-compatible version of {@link SizeF}.
+ */
+public final class SizeFCompat {
+
+    private final float mWidth;
+    private final float mHeight;
+
+    public SizeFCompat(float width, float height) {
+        mWidth = Preconditions.checkArgumentFinite(width, "width");
+        mHeight = Preconditions.checkArgumentFinite(height, "height");
+    }
+
+    /**
+     * Get the width of the size (as an arbitrary unit).
+     * @return width
+     */
+    public float getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Get the height of the size (as an arbitrary unit).
+     * @return height
+     */
+    public float getHeight() {
+        return mHeight;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SizeFCompat)) return false;
+        SizeFCompat that = (SizeFCompat) o;
+        return that.mWidth == mWidth && that.mHeight == mHeight;
+    }
+
+    @Override
+    public int hashCode() {
+        return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return mWidth + "x" + mHeight;
+    }
+
+    /** Converts this {@link SizeFCompat} into a {@link SizeF}. */
+    @RequiresApi(21)
+    @NonNull
+    public SizeF toSizeF() {
+        return Api21Impl.toSizeF(this);
+    }
+
+    /** Creates a {@link SizeFCompat} from a {@link SizeF}. */
+    @RequiresApi(21)
+    @NonNull
+    public static SizeFCompat createFromSizeF(@NonNull SizeF size) {
+        return Api21Impl.toSizeFCompat(size);
+    }
+
+    @RequiresApi(21)
+    private static final class Api21Impl {
+        @DoNotInline
+        @NonNull
+        static SizeFCompat toSizeFCompat(@NonNull SizeF size) {
+            Preconditions.checkNotNull(size);
+            return new SizeFCompat(size.getWidth(), size.getHeight());
+        }
+
+        @DoNotInline
+        @NonNull
+        static SizeF toSizeF(@NonNull SizeFCompat size) {
+            Preconditions.checkNotNull(size);
+            return new SizeF(size.getWidth(), size.getHeight());
+        }
+    }
+}
diff --git a/core/core/src/main/java/androidx/core/view/AccessibilityDelegateCompat.java b/core/core/src/main/java/androidx/core/view/AccessibilityDelegateCompat.java
index de873ba..75698dd 100644
--- a/core/core/src/main/java/androidx/core/view/AccessibilityDelegateCompat.java
+++ b/core/core/src/main/java/androidx/core/view/AccessibilityDelegateCompat.java
@@ -18,6 +18,7 @@
 
 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
 
+import android.accessibilityservice.AccessibilityService;
 import android.os.Build;
 import android.os.Bundle;
 import android.text.style.ClickableSpan;
@@ -29,6 +30,9 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.core.R;
@@ -45,14 +49,14 @@
  * Helper for accessing {@link AccessibilityDelegate}.
  * <p>
  * <strong>Note:</strong> On platform versions prior to
- * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
+ * {@link Build.VERSION_CODES#M API 23}, delegate methods on
  * views in the {@code android.widget.*} package are called <i>before</i>
  * host methods. This prevents certain properties such as class name from
  * being modified by overriding
  * {@link AccessibilityDelegateCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)},
  * as any changes will be overwritten by the host class.
  * <p>
- * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
+ * Starting in {@link Build.VERSION_CODES#M API 23}, delegate
  * methods are called <i>after</i> host methods, which all properties to be
  * modified without being overwritten by the host class.
  */
@@ -144,7 +148,7 @@
      * @hide
      */
     @RestrictTo(LIBRARY_GROUP_PREFIX)
-    public AccessibilityDelegateCompat(AccessibilityDelegate originalDelegate) {
+    public AccessibilityDelegateCompat(@NonNull AccessibilityDelegate originalDelegate) {
         mOriginalDelegate = originalDelegate;
         mBridge = new AccessibilityDelegateAdapter(this);
     }
@@ -170,7 +174,7 @@
      *
      * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
      */
-    public void sendAccessibilityEvent(View host, int eventType) {
+    public void sendAccessibilityEvent(@NonNull View host, int eventType) {
         mOriginalDelegate.sendAccessibilityEvent(host, eventType);
     }
 
@@ -192,7 +196,8 @@
      * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
      *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
      */
-    public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
+    public void sendAccessibilityEventUnchecked(@NonNull View host,
+            @NonNull AccessibilityEvent event) {
         mOriginalDelegate.sendAccessibilityEventUnchecked(host, event);
     }
 
@@ -213,7 +218,8 @@
      * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
      *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
      */
-    public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+    public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
+            @NonNull AccessibilityEvent event) {
         return mOriginalDelegate.dispatchPopulateAccessibilityEvent(host, event);
     }
 
@@ -233,7 +239,8 @@
      * @see ViewCompat#onPopulateAccessibilityEvent(View ,AccessibilityEvent)
      *      ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent)
      */
-    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+    public void onPopulateAccessibilityEvent(@NonNull View host,
+            @NonNull AccessibilityEvent event) {
         mOriginalDelegate.onPopulateAccessibilityEvent(host, event);
     }
 
@@ -253,7 +260,8 @@
      * @see ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)
      *      ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)
      */
-    public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+    public void onInitializeAccessibilityEvent(@NonNull View host,
+            @NonNull AccessibilityEvent event) {
         mOriginalDelegate.onInitializeAccessibilityEvent(host, event);
     }
 
@@ -272,7 +280,8 @@
      * @see ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
      *      ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
      */
-    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
+    public void onInitializeAccessibilityNodeInfo(@NonNull View host,
+            @NonNull AccessibilityNodeInfoCompat info) {
         mOriginalDelegate.onInitializeAccessibilityNodeInfo(
                 host, info.unwrap());
     }
@@ -296,14 +305,14 @@
      * @see ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
      *      ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
      */
-    public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
-            AccessibilityEvent event) {
+    public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
+            @NonNull AccessibilityEvent event) {
         return mOriginalDelegate.onRequestSendAccessibilityEvent(host, child, event);
     }
 
     /**
      * Gets the provider for managing a virtual view hierarchy rooted at this View
-     * and reported to {@link android.accessibilityservice.AccessibilityService}s
+     * and reported to {@link AccessibilityService}s
      * that explore the window content.
      * <p>
      * The default implementation behaves as
@@ -315,9 +324,10 @@
      *
      * @see AccessibilityNodeProviderCompat
      */
-    public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {
+    @Nullable
+    public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(@NonNull View host) {
         if (Build.VERSION.SDK_INT >= 16) {
-            Object provider = mOriginalDelegate.getAccessibilityNodeProvider(host);
+            Object provider = Api16Impl.getAccessibilityNodeProvider(mOriginalDelegate, host);
             if (provider != null) {
                 return new AccessibilityNodeProviderCompat(provider);
             }
@@ -335,13 +345,17 @@
      *  no accessibility delegate been set.
      * </p>
      *
+     *
+     * @param host View on which to perform the action.
      * @param action The action to perform.
+     * @param args Optional action arguments.
      * @return Whether the action was performed.
      *
      * @see View#performAccessibilityAction(int, Bundle)
      *      View#performAccessibilityAction(int, Bundle)
      */
-    public boolean performAccessibilityAction(View host, int action, Bundle args) {
+    public boolean performAccessibilityAction(@NonNull View host, int action,
+            @NonNull Bundle args) {
         boolean success = false;
         List<AccessibilityActionCompat> actions = getActionList(host);
         for (int i = 0; i < actions.size(); i++) {
@@ -352,7 +366,7 @@
             }
         }
         if (!success && Build.VERSION.SDK_INT >= 16) {
-            success = mOriginalDelegate.performAccessibilityAction(host, action, args);
+            success = Api16Impl.performAccessibilityAction(mOriginalDelegate, host, action, args);
         }
         if (!success && action == R.id.accessibility_action_clickable_span) {
             success = performClickableSpanAction(
@@ -396,6 +410,25 @@
     static List<AccessibilityActionCompat> getActionList(View view) {
         List<AccessibilityActionCompat> actions = (List<AccessibilityActionCompat>)
                 view.getTag(R.id.tag_accessibility_actions);
-        return actions == null ? Collections.<AccessibilityActionCompat>emptyList() : actions;
+        return actions == null ? Collections.emptyList() : actions;
+    }
+
+    @RequiresApi(16)
+    static class Api16Impl {
+        private Api16Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static AccessibilityNodeProvider getAccessibilityNodeProvider(
+                AccessibilityDelegate accessibilityDelegate, View host) {
+            return accessibilityDelegate.getAccessibilityNodeProvider(host);
+        }
+
+        @DoNotInline
+        static boolean performAccessibilityAction(AccessibilityDelegate accessibilityDelegate,
+                View host, int action, Bundle args) {
+            return accessibilityDelegate.performAccessibilityAction(host, action, args);
+        }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/view/ActionProvider.java b/core/core/src/main/java/androidx/core/view/ActionProvider.java
index 468e67f..dff98c6 100644
--- a/core/core/src/main/java/androidx/core/view/ActionProvider.java
+++ b/core/core/src/main/java/androidx/core/view/ActionProvider.java
@@ -24,6 +24,8 @@
 import android.view.SubMenu;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
 
 /**
@@ -130,13 +132,14 @@
      *
      * @param context Context for accessing resources.
      */
-    public ActionProvider(Context context) {
+    public ActionProvider(@NonNull Context context) {
         mContext = context;
     }
 
     /**
      * Gets the context associated with this action provider.
      */
+    @NonNull
     public Context getContext() {
         return mContext;
     }
@@ -146,6 +149,7 @@
      *
      * @return A new action view.
      */
+    @NonNull
     public abstract View onCreateActionView();
 
     /**
@@ -160,7 +164,9 @@
      * @param forItem MenuItem to create the action view for
      * @return the new action view
      */
-    public View onCreateActionView(MenuItem forItem) {
+    @SuppressWarnings("unused")
+    @NonNull
+    public View onCreateActionView(@NonNull MenuItem forItem) {
         return onCreateActionView();
     }
 
@@ -259,7 +265,8 @@
      *
      * @param subMenu Submenu that will be displayed
      */
-    public void onPrepareSubMenu(SubMenu subMenu) {
+    @SuppressWarnings("unused")
+    public void onPrepareSubMenu(@NonNull SubMenu subMenu) {
     }
 
     /**
@@ -279,7 +286,7 @@
      * @hide Internal use only
      */
     @RestrictTo(LIBRARY_GROUP_PREFIX)
-    public void setSubUiVisibilityListener(SubUiVisibilityListener listener) {
+    public void setSubUiVisibilityListener(@Nullable SubUiVisibilityListener listener) {
         mSubUiVisibilityListener = listener;
     }
 
@@ -289,7 +296,7 @@
      *
      * @param listener listener to set
      */
-    public void setVisibilityListener(VisibilityListener listener) {
+    public void setVisibilityListener(@Nullable VisibilityListener listener) {
         if (mVisibilityListener != null && listener != null) {
             Log.w(TAG, "setVisibilityListener: Setting a new ActionProvider.VisibilityListener " +
                     "when one is already set. Are you reusing this " + getClass().getSimpleName() +
diff --git a/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java b/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
index e29026b..5b02d20 100644
--- a/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
@@ -36,6 +36,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.function.Predicate;
 
 /**
@@ -127,6 +128,7 @@
     /**
      * Flag requesting that the content should be converted to plain text prior to inserting.
      */
+    @SuppressWarnings("PointlessBitwiseExpression")
     public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1 << 0;
 
     /**
@@ -177,7 +179,7 @@
     @RequiresApi(31)
     @NonNull
     public ContentInfo toContentInfo() {
-        return mCompat.getWrapped();
+        return Objects.requireNonNull(mCompat.getWrapped());
     }
 
     @NonNull
@@ -436,6 +438,7 @@
         }
     }
 
+    @RequiresApi(31)
     private static final class Compat31Impl implements Compat {
         @NonNull
         private final ContentInfo mWrapped;
diff --git a/core/core/src/main/java/androidx/core/view/DisplayCompat.java b/core/core/src/main/java/androidx/core/view/DisplayCompat.java
index 7593f36..816d397 100644
--- a/core/core/src/main/java/androidx/core/view/DisplayCompat.java
+++ b/core/core/src/main/java/androidx/core/view/DisplayCompat.java
@@ -27,6 +27,7 @@
 import android.text.TextUtils;
 import android.view.Display;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -167,7 +168,7 @@
 
         // Check the system property for display size.
         String displaySize = getSystemProperty(property);
-        if (TextUtils.isEmpty(displaySize)) {
+        if (TextUtils.isEmpty(displaySize) || displaySize == null) {
             return null;
         }
 
@@ -275,9 +276,9 @@
         static boolean isCurrentModeTheLargestMode(@NonNull Display display) {
             Display.Mode currentMode = display.getMode();
             Display.Mode[] supportedModes = display.getSupportedModes();
-            for (int i = 0; i < supportedModes.length; ++i) {
-                if (currentMode.getPhysicalHeight() < supportedModes[i].getPhysicalHeight()
-                        || currentMode.getPhysicalWidth() < supportedModes[i].getPhysicalWidth()) {
+            for (Display.Mode supportedMode : supportedModes) {
+                if (currentMode.getPhysicalHeight() < supportedMode.getPhysicalHeight()
+                        || currentMode.getPhysicalWidth() < supportedMode.getPhysicalWidth()) {
                     return false;
                 }
             }
@@ -343,7 +344,8 @@
         ModeCompat(@NonNull Display.Mode mode, boolean isNative) {
             Preconditions.checkNotNull(mode, "mode == null, can't wrap a null reference");
             // This simplifies the getPhysicalWidth() / getPhysicalHeight functions below
-            mPhysicalSize = new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight());
+            mPhysicalSize = new Point(Api23Impl.getPhysicalWidth(mode),
+                    Api23Impl.getPhysicalHeight(mode));
             mMode = mode;
             mIsNative = isNative;
         }
@@ -401,6 +403,22 @@
         public Display.Mode toMode() {
             return mMode;
         }
+
+        @RequiresApi(23)
+        static class Api23Impl {
+            private Api23Impl() {
+                // This class is not instantiable.
+            }
+
+            @DoNotInline
+            static int getPhysicalWidth(Display.Mode mode) {
+                return mode.getPhysicalWidth();
+            }
+
+            @DoNotInline
+            static int getPhysicalHeight(Display.Mode mode) {
+                return mode.getPhysicalHeight();
+            }
+        }
     }
 }
-
diff --git a/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java b/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
index 83c3af9..039a8e0 100644
--- a/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
+++ b/core/core/src/main/java/androidx/core/view/DisplayCutoutCompat.java
@@ -22,11 +22,11 @@
 import android.os.Build;
 import android.view.DisplayCutout;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.core.graphics.Insets;
-import androidx.core.os.BuildCompat;
 import androidx.core.util.ObjectsCompat;
 
 import java.util.ArrayList;
@@ -41,7 +41,7 @@
  */
 public final class DisplayCutoutCompat {
 
-    private final Object mDisplayCutout;
+    private final DisplayCutout mDisplayCutout;
 
     /**
      * Creates a DisplayCutout instance.
@@ -52,8 +52,8 @@
      *               {@link #getBoundingRects()} ()}.
      */
     // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
-    public DisplayCutoutCompat(Rect safeInsets, List<Rect> boundingRects) {
-        this(SDK_INT >= 28 ? new DisplayCutout(safeInsets, boundingRects) : null);
+    public DisplayCutoutCompat(@Nullable Rect safeInsets, @Nullable List<Rect> boundingRects) {
+        this(SDK_INT >= 28 ? Api28Impl.createDisplayCutout(safeInsets, boundingRects) : null);
     }
 
     /**
@@ -81,12 +81,12 @@
     private static DisplayCutout constructDisplayCutout(@NonNull Insets safeInsets,
             @Nullable Rect boundLeft, @Nullable Rect boundTop, @Nullable Rect boundRight,
             @Nullable Rect boundBottom, @NonNull Insets waterfallInsets) {
-        if (BuildCompat.isAtLeastR()) {
-            return new DisplayCutout(safeInsets.toPlatformInsets(), boundLeft,
-                    boundTop, boundRight, boundBottom, waterfallInsets.toPlatformInsets());
+        if (SDK_INT >= 30) {
+            return Api30Impl.createDisplayCutout(safeInsets.toPlatformInsets(), boundLeft, boundTop,
+                    boundRight, boundBottom, waterfallInsets.toPlatformInsets());
         } else if (SDK_INT >= Build.VERSION_CODES.Q) {
-            return new DisplayCutout(safeInsets.toPlatformInsets(), boundLeft,
-                    boundTop, boundRight, boundBottom);
+            return Api29Impl.createDisplayCutout(safeInsets.toPlatformInsets(), boundLeft, boundTop,
+                    boundRight, boundBottom);
         } else if (SDK_INT >= Build.VERSION_CODES.P) {
             final Rect safeInsetRect = new Rect(safeInsets.left, safeInsets.top, safeInsets.right,
                     safeInsets.bottom);
@@ -103,20 +103,20 @@
             if (boundBottom != null) {
                 boundingRects.add(boundBottom);
             }
-            return new DisplayCutout(safeInsetRect, boundingRects);
+            return Api28Impl.createDisplayCutout(safeInsetRect, boundingRects);
         } else {
             return null;
         }
     }
 
-    private DisplayCutoutCompat(Object displayCutout) {
+    private DisplayCutoutCompat(DisplayCutout displayCutout) {
         mDisplayCutout = displayCutout;
     }
 
     /** Returns the inset from the top which avoids the display cutout in pixels. */
     public int getSafeInsetTop() {
         if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetTop();
+            return Api28Impl.getSafeInsetTop(mDisplayCutout);
         } else {
             return 0;
         }
@@ -125,7 +125,7 @@
     /** Returns the inset from the bottom which avoids the display cutout in pixels. */
     public int getSafeInsetBottom() {
         if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetBottom();
+            return Api28Impl.getSafeInsetBottom(mDisplayCutout);
         } else {
             return 0;
         }
@@ -134,7 +134,7 @@
     /** Returns the inset from the left which avoids the display cutout in pixels. */
     public int getSafeInsetLeft() {
         if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetLeft();
+            return Api28Impl.getSafeInsetLeft(mDisplayCutout);
         } else {
             return 0;
         }
@@ -143,7 +143,7 @@
     /** Returns the inset from the right which avoids the display cutout in pixels. */
     public int getSafeInsetRight() {
         if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getSafeInsetRight();
+            return Api28Impl.getSafeInsetRight(mDisplayCutout);
         } else {
             return 0;
         }
@@ -161,7 +161,7 @@
     @NonNull
     public List<Rect> getBoundingRects() {
         if (SDK_INT >= 28) {
-            return ((DisplayCutout) mDisplayCutout).getBoundingRects();
+            return Api28Impl.getBoundingRects(mDisplayCutout);
         } else {
             return Collections.emptyList();
         }
@@ -179,8 +179,8 @@
      */
     @NonNull
     public Insets getWaterfallInsets() {
-        if (BuildCompat.isAtLeastR()) {
-            return Insets.toCompatInsets(((DisplayCutout) mDisplayCutout).getWaterfallInsets());
+        if (SDK_INT >= 30) {
+            return Insets.toCompatInsets(Api30Impl.getWaterfallInsets(mDisplayCutout));
         } else {
             return Insets.NONE;
         }
@@ -203,17 +203,88 @@
         return mDisplayCutout == null ? 0 : mDisplayCutout.hashCode();
     }
 
+    @NonNull
     @Override
     public String toString() {
         return "DisplayCutoutCompat{" + mDisplayCutout + "}";
     }
 
-    static DisplayCutoutCompat wrap(Object displayCutout) {
+    static DisplayCutoutCompat wrap(DisplayCutout displayCutout) {
         return displayCutout == null ? null : new DisplayCutoutCompat(displayCutout);
     }
 
-    @RequiresApi(api = 28)
+    @RequiresApi(28)
     DisplayCutout unwrap() {
-        return (DisplayCutout) mDisplayCutout;
+        return mDisplayCutout;
+    }
+
+    @RequiresApi(28)
+    static class Api28Impl {
+        private Api28Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static DisplayCutout createDisplayCutout(Rect safeInsets, List<Rect> boundingRects) {
+            return new DisplayCutout(safeInsets, boundingRects);
+        }
+
+        @DoNotInline
+        static int getSafeInsetTop(DisplayCutout displayCutout) {
+            return displayCutout.getSafeInsetTop();
+        }
+
+        @DoNotInline
+        static int getSafeInsetBottom(DisplayCutout displayCutout) {
+            return displayCutout.getSafeInsetBottom();
+        }
+
+        @DoNotInline
+        static int getSafeInsetLeft(DisplayCutout displayCutout) {
+            return displayCutout.getSafeInsetLeft();
+        }
+
+        @DoNotInline
+        static int getSafeInsetRight(DisplayCutout displayCutout) {
+            return displayCutout.getSafeInsetRight();
+        }
+
+        @DoNotInline
+        static List<Rect> getBoundingRects(DisplayCutout displayCutout) {
+            return displayCutout.getBoundingRects();
+        }
+    }
+
+    @RequiresApi(30)
+    static class Api30Impl {
+        private Api30Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static DisplayCutout createDisplayCutout(android.graphics.Insets safeInsets, Rect boundLeft,
+                Rect boundTop, Rect boundRight, Rect boundBottom,
+                android.graphics.Insets waterfallInsets) {
+            return new DisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom,
+                    waterfallInsets);
+        }
+
+        @DoNotInline
+        static android.graphics.Insets getWaterfallInsets(DisplayCutout displayCutout) {
+            return displayCutout.getWaterfallInsets();
+        }
+    }
+
+    @RequiresApi(29)
+    static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static DisplayCutout createDisplayCutout(android.graphics.Insets safeInsets, Rect boundLeft,
+                Rect boundTop, Rect boundRight, Rect boundBottom) {
+            return new DisplayCutout(safeInsets, boundLeft, boundTop, boundRight, boundBottom);
+        }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java b/core/core/src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java
index 6c3393c..2e6469b 100644
--- a/core/core/src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java
+++ b/core/core/src/main/java/androidx/core/view/DragAndDropPermissionsCompat.java
@@ -23,11 +23,14 @@
 import android.view.DragAndDropPermissions;
 import android.view.DragEvent;
 
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 
 /**
- * Helper for accessing features in {@link android.view.DragAndDropPermissions} a backwards
+ * Helper for accessing features in {@link DragAndDropPermissions} a backwards
  * compatible fashion.
  *
  * <p>
@@ -37,19 +40,20 @@
  * </p>
  */
 public final class DragAndDropPermissionsCompat {
-    private Object mDragAndDropPermissions;
+    private final DragAndDropPermissions mDragAndDropPermissions;
 
-    private DragAndDropPermissionsCompat(Object dragAndDropPermissions) {
+    private DragAndDropPermissionsCompat(DragAndDropPermissions dragAndDropPermissions) {
         mDragAndDropPermissions = dragAndDropPermissions;
     }
 
     /** @hide */
     @RestrictTo(LIBRARY_GROUP_PREFIX)
     @Nullable
-    public static DragAndDropPermissionsCompat request(Activity activity, DragEvent dragEvent) {
+    public static DragAndDropPermissionsCompat request(@NonNull Activity activity,
+            @NonNull DragEvent dragEvent) {
         if (Build.VERSION.SDK_INT >= 24) {
             DragAndDropPermissions dragAndDropPermissions =
-                    activity.requestDragAndDropPermissions(dragEvent);
+                    Api24Impl.requestDragAndDropPermissions(activity, dragEvent);
             if (dragAndDropPermissions != null) {
                 return new DragAndDropPermissionsCompat(dragAndDropPermissions);
             }
@@ -62,7 +66,25 @@
      */
     public void release() {
         if (Build.VERSION.SDK_INT >= 24) {
-            ((DragAndDropPermissions) mDragAndDropPermissions).release();
+            Api24Impl.release(mDragAndDropPermissions);
+        }
+    }
+
+    @RequiresApi(24)
+    static class Api24Impl {
+        private Api24Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static DragAndDropPermissions requestDragAndDropPermissions(Activity activity,
+                DragEvent event) {
+            return activity.requestDragAndDropPermissions(event);
+        }
+
+        @DoNotInline
+        static void release(DragAndDropPermissions dragAndDropPermissions) {
+            dragAndDropPermissions.release();
         }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/view/DragStartHelper.java b/core/core/src/main/java/androidx/core/view/DragStartHelper.java
index 8488846..ed099dc 100644
--- a/core/core/src/main/java/androidx/core/view/DragStartHelper.java
+++ b/core/core/src/main/java/androidx/core/view/DragStartHelper.java
@@ -21,6 +21,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 /**
  * DragStartHelper is a utility class for implementing drag and drop support.
  * <p>
@@ -84,7 +86,7 @@
          * @param helper The DragStartHelper object which detected the gesture.
          * @return True if the listener has started the drag operation, false otherwise.
          */
-        boolean onDragStart(View v, DragStartHelper helper);
+        boolean onDragStart(@NonNull View v, @NonNull DragStartHelper helper);
     }
 
     /**
@@ -93,7 +95,7 @@
      * called explicitly.
      * @param view A View
      */
-    public DragStartHelper(View view, OnDragStartListener listener) {
+    public DragStartHelper(@NonNull View view, @NonNull OnDragStartListener listener) {
         mView = view;
         mListener = listener;
     }
@@ -125,7 +127,7 @@
      *        the event.
      * @return True if the listener has consumed the event, false otherwise.
      */
-    public boolean onTouch(View v, MotionEvent event) {
+    public boolean onTouch(@NonNull View v, @NonNull MotionEvent event) {
         final int x = (int) event.getX();
         final int y = (int) event.getY();
         switch (event.getAction()) {
@@ -166,7 +168,7 @@
      * @param v The view that was clicked and held.
      * @return true if the callback consumed the long click, false otherwise.
      */
-    public boolean onLongClick(View v) {
+    public boolean onLongClick(@NonNull View v) {
         return mListener.onDragStart(v, this);
     }
 
@@ -174,22 +176,13 @@
      * Compute the position of the touch event that started the drag operation.
      * @param point The position of the touch event that started the drag operation.
      */
-    public void getTouchPosition(Point point) {
+    public void getTouchPosition(@NonNull Point point) {
         point.set(mLastTouchX, mLastTouchY);
     }
 
-    private final View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() {
-        @Override
-        public boolean onLongClick(View v) {
-            return DragStartHelper.this.onLongClick(v);
-        }
-    };
+    private final View.OnLongClickListener mLongClickListener =
+            DragStartHelper.this::onLongClick;
 
-    private final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
-        @Override
-        public boolean onTouch(View v, MotionEvent event) {
-            return DragStartHelper.this.onTouch(v, event);
-        }
-    };
+    private final View.OnTouchListener mTouchListener = DragStartHelper.this::onTouch;
 }
 
diff --git a/core/core/src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java b/core/core/src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java
index 5006791..fa1ff26 100644
--- a/core/core/src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java
+++ b/core/core/src/main/java/androidx/core/view/animation/PathInterpolatorCompat.java
@@ -21,6 +21,10 @@
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
 /**
  * Helper for creating path-based {@link Interpolator} instances. On API 21 or newer, the
  * platform implementation will be used and on older platforms a compatible alternative
@@ -44,9 +48,10 @@
      * @param path the {@link Path} to use to make the line representing the {@link Interpolator}
      * @return the {@link Interpolator} representing the {@link Path}
      */
-    public static Interpolator create(Path path) {
+    @NonNull
+    public static Interpolator create(@NonNull Path path) {
         if (Build.VERSION.SDK_INT >= 21) {
-            return new PathInterpolator(path);
+            return Api21Impl.createPathInterpolator(path);
         }
         return new PathInterpolatorApi14(path);
     }
@@ -59,9 +64,10 @@
      * @param controlY the y coordinate of the quadratic Bezier control point
      * @return the {@link Interpolator} representing the quadratic Bezier curve
      */
+    @NonNull
     public static Interpolator create(float controlX, float controlY) {
         if (Build.VERSION.SDK_INT >= 21) {
-            return new PathInterpolator(controlX, controlY);
+            return Api21Impl.createPathInterpolator(controlX, controlY);
         }
         return new PathInterpolatorApi14(controlX, controlY);
     }
@@ -76,11 +82,35 @@
      * @param controlY2 the y coordinate of the second control point of the cubic Bezier
      * @return the {@link Interpolator} representing the cubic Bezier curve
      */
+    @NonNull
     public static Interpolator create(float controlX1, float controlY1,
             float controlX2, float controlY2) {
         if (Build.VERSION.SDK_INT >= 21) {
-            return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);
+            return Api21Impl.createPathInterpolator(controlX1, controlY1, controlX2, controlY2);
         }
         return new PathInterpolatorApi14(controlX1, controlY1, controlX2, controlY2);
     }
+
+    @RequiresApi(21)
+    static class Api21Impl {
+        private Api21Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static PathInterpolator createPathInterpolator(Path path) {
+            return new PathInterpolator(path);
+        }
+
+        @DoNotInline
+        static PathInterpolator createPathInterpolator(float controlX, float controlY) {
+            return new PathInterpolator(controlX, controlY);
+        }
+
+        @DoNotInline
+        static PathInterpolator createPathInterpolator(float controlX1, float controlY1,
+                float controlX2, float controlY2) {
+            return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/view/inputmethod/InputConnectionCompat.java b/core/core/src/main/java/androidx/core/view/inputmethod/InputConnectionCompat.java
index d83e1cb..3e1acef 100644
--- a/core/core/src/main/java/androidx/core/view/inputmethod/InputConnectionCompat.java
+++ b/core/core/src/main/java/androidx/core/view/inputmethod/InputConnectionCompat.java
@@ -21,7 +21,9 @@
 import android.annotation.SuppressLint;
 import android.content.ClipData;
 import android.content.ClipDescription;
+import android.content.ContentProvider;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -29,15 +31,19 @@
 import android.util.Log;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputConnectionWrapper;
 import android.view.inputmethod.InputContentInfo;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.core.util.ObjectsCompat;
 import androidx.core.util.Preconditions;
 import androidx.core.view.ContentInfoCompat;
+import androidx.core.view.OnReceiveContentListener;
 import androidx.core.view.ViewCompat;
 
 /**
@@ -142,7 +148,7 @@
             @NonNull EditorInfo editorInfo, @NonNull InputContentInfoCompat inputContentInfo,
             int flags, @Nullable Bundle opts) {
         if (Build.VERSION.SDK_INT >= 25) {
-            return inputConnection.commitContent(
+            return Api25Impl.commitContent(inputConnection,
                     (InputContentInfo) inputContentInfo.unwrap(), flags, opts);
         } else {
             final int protocol = EditorInfoCompat.getProtocol(editorInfo);
@@ -204,16 +210,16 @@
      * <p>On API &lt;= 24 devices, IME developers need to ensure that the content URI is accessible
      * only from the target application, for example, by generating a URL with a unique name that
      * others cannot guess. IME developers can also rely on the following information of the target
-     * application to do additional access checks in their {@link android.content.ContentProvider}.
+     * application to do additional access checks in their {@link ContentProvider}.
      * </p>
      * <ul>
      *     <li>On API &gt;= 23 {@link EditorInfo#packageName} is guaranteed to not be spoofed, which
-     *     can later be compared with {@link android.content.ContentProvider#getCallingPackage()} in
-     *     the {@link android.content.ContentProvider}.
+     *     can later be compared with {@link ContentProvider#getCallingPackage()} in
+     *     the {@link ContentProvider}.
      *     </li>
-     *     <li>{@link android.view.inputmethod.InputBinding#getUid()} is guaranteed to not be
-     *     spoofed, which can later be compared with {@link android.os.Binder#getCallingUid()} in
-     *     the {@link android.content.ContentProvider}.</li>
+     *     <li>{@link InputBinding#getUid()} is guaranteed to not be
+     *     spoofed, which can later be compared with {@link Binder#getCallingUid()} in
+     *     the {@link ContentProvider}.</li>
      * </ul>
      */
     public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 0x00000001;
@@ -232,7 +238,6 @@
          * request is already handled or still being handled in background. {@code false} to use the
          * default implementation
          */
-        @SuppressWarnings("NullableProblems") // Not useful here
         boolean onCommitContent(@NonNull InputContentInfoCompat inputContentInfo, int flags,
                 @Nullable Bundle opts);
     }
@@ -334,6 +339,7 @@
      *
      * @return A wrapper {@link InputConnection} object that can be returned to the IME.
      */
+    @SuppressWarnings("deprecation")
     @NonNull
     public static InputConnection createWrapper(@NonNull View view,
             @NonNull InputConnection inputConnection, @NonNull EditorInfo editorInfo) {
@@ -345,44 +351,40 @@
     /**
      * Creates an {@link OnCommitContentListener} that uses
      * {@link ViewCompat#performReceiveContent} to insert content. This is useful for widgets
-     * that support content insertion using an {@link androidx.core.view.OnReceiveContentListener}.
+     * that support content insertion using an {@link OnReceiveContentListener}.
      */
     @NonNull
     private static OnCommitContentListener createOnCommitContentListenerUsingPerformReceiveContent(
             @NonNull View view) {
         Preconditions.checkNotNull(view);
-        return new OnCommitContentListener() {
-            @Override
-            public boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags,
-                    Bundle opts) {
-                Bundle extras = opts;
-                if (Build.VERSION.SDK_INT >= 25
-                        && (flags & INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
-                    try {
-                        inputContentInfo.requestPermission();
-                    } catch (Exception e) {
-                        Log.w(LOG_TAG,
-                                "Can't insert content from IME; requestPermission() failed", e);
-                        return false;
-                    }
-                    // Permissions granted above are revoked automatically by the platform when the
-                    // corresponding InputContentInfo object is garbage collected. To prevent
-                    // this from happening prematurely (before the receiving app has had a chance
-                    // to process the content), we set the InputContentInfo object into the
-                    // extras of the payload passed to OnReceiveContentListener.
-                    InputContentInfo inputContentInfoFmk =
-                            (InputContentInfo) inputContentInfo.unwrap();
-                    extras = (opts == null) ? new Bundle() : new Bundle(opts);
-                    extras.putParcelable(EXTRA_INPUT_CONTENT_INFO, inputContentInfoFmk);
+        return (inputContentInfo, flags, opts) -> {
+            Bundle extras = opts;
+            if (Build.VERSION.SDK_INT >= 25
+                    && (flags & INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
+                try {
+                    inputContentInfo.requestPermission();
+                } catch (Exception e) {
+                    Log.w(LOG_TAG,
+                            "Can't insert content from IME; requestPermission() failed", e);
+                    return false;
                 }
-                ClipData clip = new ClipData(inputContentInfo.getDescription(),
-                        new ClipData.Item(inputContentInfo.getContentUri()));
-                ContentInfoCompat payload = new ContentInfoCompat.Builder(clip, SOURCE_INPUT_METHOD)
-                        .setLinkUri(inputContentInfo.getLinkUri())
-                        .setExtras(extras)
-                        .build();
-                return ViewCompat.performReceiveContent(view, payload) == null;
+                // Permissions granted above are revoked automatically by the platform when the
+                // corresponding InputContentInfo object is garbage collected. To prevent
+                // this from happening prematurely (before the receiving app has had a chance
+                // to process the content), we set the InputContentInfo object into the
+                // extras of the payload passed to OnReceiveContentListener.
+                InputContentInfo inputContentInfoFmk =
+                        (InputContentInfo) inputContentInfo.unwrap();
+                extras = (opts == null) ? new Bundle() : new Bundle(opts);
+                extras.putParcelable(EXTRA_INPUT_CONTENT_INFO, inputContentInfoFmk);
             }
+            ClipData clip = new ClipData(inputContentInfo.getDescription(),
+                    new ClipData.Item(inputContentInfo.getContentUri()));
+            ContentInfoCompat payload = new ContentInfoCompat.Builder(clip, SOURCE_INPUT_METHOD)
+                    .setLinkUri(inputContentInfo.getLinkUri())
+                    .setExtras(extras)
+                    .build();
+            return ViewCompat.performReceiveContent(view, payload) == null;
         };
     }
 
@@ -399,4 +401,17 @@
     @Deprecated
     public InputConnectionCompat() {
     }
+
+    @RequiresApi(25)
+    static class Api25Impl {
+        private Api25Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static boolean commitContent(InputConnection inputConnection,
+                InputContentInfo inputContentInfo, int i, Bundle bundle) {
+            return inputConnection.commitContent(inputContentInfo, i, bundle);
+        }
+    }
 }
diff --git a/core/core/src/test/java/androidx/core/util/SizeFCompatTest.java b/core/core/src/test/java/androidx/core/util/SizeFCompatTest.java
new file mode 100644
index 0000000..cde04f1
--- /dev/null
+++ b/core/core/src/test/java/androidx/core/util/SizeFCompatTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.core.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.annotation.TargetApi;
+import android.util.SizeF;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.internal.DoNotInstrument;
+
+@RunWith(RobolectricTestRunner.class)
+@DoNotInstrument
+@Config(sdk = {19, 21})
+public class SizeFCompatTest {
+
+    @Test
+    public void constructor_validSize() {
+        SizeFCompat size = new SizeFCompat(100.4f, 150.2f);
+
+        assertThat(size.getWidth()).isEqualTo(100.4f);
+        assertThat(size.getHeight()).isEqualTo(150.2f);
+    }
+
+    @Test
+    public void constructor_invalidSize() {
+        assertThrows(IllegalArgumentException.class, () -> new SizeFCompat(Float.NaN, 100f));
+        assertThrows(IllegalArgumentException.class, () -> new SizeFCompat(12.5f, Float.NaN));
+    }
+
+    @Test
+    public void equals() {
+        assertThat(new SizeFCompat(100.4f, 150.2f)).isEqualTo(new SizeFCompat(100.4f, 150.2f));
+        assertThat(new SizeFCompat(100.4f, 150.2f)).isNotEqualTo(new SizeFCompat(10.4f, 150.2f));
+        assertThat(new SizeFCompat(100.4f, 150.2f)).isNotEqualTo(new SizeFCompat(100.4f, 15.2f));
+    }
+
+    @Test
+    public void hashCode_sameForEqualSizes() {
+        assertThat(new SizeFCompat(100.4f, 150.2f).hashCode())
+                .isEqualTo(new SizeFCompat(100.4f, 150.2f).hashCode());
+        assertThat(new SizeFCompat(100.4f, 150.2f).hashCode())
+                .isNotEqualTo(new SizeFCompat(10.4f, 150.2f).hashCode());
+        assertThat(new SizeFCompat(100.4f, 150.2f).hashCode())
+                .isNotEqualTo(new SizeFCompat(100.4f, 15.2f).hashCode());
+    }
+
+    @Test
+    public void toString_readable() {
+        assertThat(new SizeFCompat(10.2f, 20.4f).toString()).isEqualTo("10.2x20.4");
+    }
+
+    @TargetApi(21)
+    @Config(sdk = 21)
+    @Test
+    public void toSizeF() {
+        assertThat(new SizeFCompat(10.2f, 20.4f).toSizeF()).isEqualTo(new SizeF(10.2f, 20.4f));
+    }
+
+    @TargetApi(21)
+    @Config(sdk = 21)
+    @Test
+    public void createFromSizeF() {
+        assertThat(SizeFCompat.createFromSizeF(new SizeF(11.2f, 21.4f)))
+                .isEqualTo(new SizeFCompat(11.2f, 21.4f));
+    }
+}
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index ecc237e6..635400e3 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -133,7 +133,6 @@
 \- Support for Scala 3
 For more details see .*
 Daemon will be stopped at the end of the build
-# > Task :buildSrc:build
 # > Configure project :appsearch:appsearch\-local\-backend
 Configuration on demand is an incubating feature\.
 Configuration cache is an incubating feature\.
@@ -177,9 +176,6 @@
 Note: Recompile with \-Xlint:removal for details\.
 Note\: Some input files use unchecked or unsafe operations\.
 Note\: Recompile with \-Xlint\:unchecked for details\.
-# > Task :benchmark:benchmark-junit4:processDebugAndroidTestManifest
-# > Task :benchmark:benchmark-common:processDebugAndroidTestManifest
-# > Task :tracing:tracing:compileDebugAndroidTestJavaWithJavac
 # > Task :ui:ui-tooling:processDebugAndroidTestManifest
 application@android:debuggable was tagged at .*\.xml:[0-9]+ to replace other declarations but no other declaration present
 \$OUT_DIR/androidx/wear/compose/compose\-material\-benchmark/build/intermediates/tmp/manifest/androidTest/release/tempFile[0-9]+ProcessTestManifest[0-9]+\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
@@ -208,7 +204,6 @@
 \$OUT_DIR/androidx/compose/ui/ui\-graphics/ui\-graphics\-benchmark/build/intermediates/tmp/manifest/androidTest/release/tempFile[0-9]+ProcessTestManifest[0-9]+\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 # > Task :compose:foundation:foundation-layout:processDebugAndroidTestManifest
 \$SUPPORT/compose/foundation/foundation\-layout/src/androidAndroidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
-# > Task :compose:navigation:navigation:processDebugAndroidTestManifest
 # > Task :compose:runtime:runtime-saveable:processDebugAndroidTestManifest
 \$SUPPORT/compose/runtime/runtime\-saveable/src/androidAndroidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 # > Task :compose:runtime:runtime:benchmark:processReleaseAndroidTestManifest
@@ -229,8 +224,8 @@
 location\: class PendingIntent
 \$OUT_DIR\/androidx\/docs\-public\/build\/unzippedDocsSources\/androidx\/work\/impl\/utils\/ForceStopRunnable\.java\:[0-9]+\: error\: cannot find symbol
 # > Task :buildOnServer
+[0-9]+ problems were found reusing the configuration cache\.
 [0-9]+ problems were found reusing the configuration cache, [0-9]+ of which seem unique\.
-\- Task `:docs\-tip\-of\-tree:unzipSampleSources` of type `org\.gradle\.api\.tasks\.Sync`: cannot deserialize object of type 'org\.gradle\.api\.Project' as these are not supported with the configuration cache\.
 [0-9]+ actionable tasks: [0-9]+ executed, [0-9]+ up\-to\-date
 Configuration cache entry reused with [0-9]+ problems\.
 See the profiling report at: file://\$GRADLE_USER_HOME/daemon/.*/reports/profile/profile\-[0-9]+\-[0-9]+\-[0-9]+\-[0-9]+\-[0-9]+\-[0-9]+\.html
@@ -245,19 +240,8 @@
 # > Task :lifecycle:lifecycle-common:compileJava
 Note: \$[^ ]+ uses or overrides a deprecated API\.
 Note: Recompile with \-Xlint\:deprecation for details\.
-# > Task :concurrent:concurrent-futures:compileJava
-# > Task :contentpager:contentpager:compileReleaseJavaWithJavac
-# > Task :coordinatorlayout:coordinatorlayout:compileReleaseJavaWithJavac
-# > Task :customview:customview:compileReleaseJavaWithJavac
-# > Task :recommendation:recommendation:compileReleaseJavaWithJavac
-# > Task :textclassifier:textclassifier:compileReleaseJavaWithJavac
 # > Task :publicDocsTask
 [0-9]+ warnings
-# > Task :support-animation-demos:compileDebugJavaWithJavac
-# > Task :lint-demos:lint-demo-appcompat:compileDebugJavaWithJavac
-# > Task :support-transition-demos:compileDebugJavaWithJavac
-# > Task :support-content-demos:compileDebugJavaWithJavac
-# > Task :support-preference-demos:compileDebugJavaWithJavac
 # > Task :startup:integration-tests:first-library:processDebugManifest
 \$SUPPORT/startup/integration\-tests/first\-library/src/main/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 meta\-data\#androidx\.work\.WorkManagerInitializer was tagged at AndroidManifest\.xml\:[0-9]+ to remove other declarations but no other declaration present
@@ -265,23 +249,12 @@
 Note: \$SUPPORT/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SliceBrowser\.java uses unchecked or unsafe operations\.
 # > Task :emoji2:emoji2-benchmark:processReleaseAndroidTestManifest
 \$SUPPORT/emoji[0-9]+/emoji[0-9]+\-benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
-# > Task :gridlayout:gridlayout:compileDebugAndroidTestJavaWithJavac
-# > Task :leanback:leanback-tab:processDebugAndroidTestManifest
-# > Task :lifecycle:lifecycle-extensions:processDebugAndroidTestManifest
 # > Task :leanback:leanback:compileDebugAndroidTestJavaWithJavac
 reason: class file for kotlin\.annotation\.AnnotationTarget not found
 reason: class file for kotlin\.annotation\.AnnotationRetention not found
 warning: unknown enum constant AnnotationTarget\.ANNOTATION_CLASS
-# > Task :navigation:navigation-dynamic-features-runtime:processDebugAndroidTestManifest
-# > Task :mediarouter:mediarouter:compileDebugAndroidTestJavaWithJavac
-# > Task :palette:palette:processDebugAndroidTestManifest
-# > Task :percentlayout:percentlayout:processDebugAndroidTestManifest
-# > Task :preference:preference-ktx:processDebugAndroidTestManifest
 # > Task :recyclerview:recyclerview-benchmark:processReleaseAndroidTestManifest
 \$SUPPORT/recyclerview/recyclerview\-benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
-# > Task :remotecallback:remotecallback:processDebugAndroidTestManifest
-# > Task :recyclerview:recyclerview-selection:compileDebugAndroidTestJavaWithJavac
-# > Task :savedstate:savedstate:processDebugAndroidTestManifest
 # > Task :room:room-benchmark:processReleaseAndroidTestManifest
 \$SUPPORT/room/benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 # > Task :room:room-benchmark:kaptReleaseAndroidTestKotlin
@@ -291,7 +264,6 @@
 \$SUPPORT/room/integration\-tests/noappcompattestapp/src/androidTest/java/androidx/room/integration/noappcompat/BareRelationDatabaseTest\.java:[0-9]+: warning: The return value includes a POJO with a @Relation\. It is usually desired to annotate this method with @Transaction to avoid possibility of inconsistent results between the POJO and its relations\. See https://developer\.android\.com/reference/androidx/room/Transaction\.html for details\.
 UserAndPets getUserWithPets\(long id\);
 List<UserAndPet> getUsersWithPet\(\);
-# > Task :textclassifier:integration-tests:testapp:compileDebugAndroidTestJavaWithJavac
 # > Task :room:integration-tests:room-testapp:compileDebugAndroidTestJavaWithJavac
 Note: \$SUPPORT/room/integration\-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/TestUtil\.java uses unchecked or unsafe operations\.
 # > Task :activity:integration-tests:testapp:processDebugAndroidTestManifest
@@ -312,16 +284,7 @@
 # > Task :compose:material:material:icons:generator:zipHtmlResultsOfTest
 Html results of .* zipped into.*\.zip
 [0-9]+ problems were found storing the configuration cache, [0-9]+ of which seem unique\.
-\- Task `:docs\-tip\-of\-tree:unzipSampleSources` of type `org\.gradle\.api\.tasks\.Sync`: cannot serialize object of type 'org\.gradle\.api\.internal\.artifacts\.configurations\.DefaultConfiguration', a subtype of 'org\.gradle\.api\.artifacts\.Configuration', as these are not supported with the configuration cache\.
 See https://docs\.gradle\.org/[0-9]+\.[0-9]+.*/userguide/configuration_cache\.html\#config_cache:requirements:disallowed_types
-\- Task `:docs\-tip\-of\-tree:unzipSampleSources` of type `org\.gradle\.api\.tasks\.Sync`: cannot deserialize object of type 'org\.gradle\.api\.artifacts\.Configuration' as these are not supported with the configuration cache\.
-\- Task `:docs\-tip\-of\-tree:unzipSampleSources` of type `org\.gradle\.api\.tasks\.Sync`: value 'file collection' is not assignable to 'org\.gradle\.api\.artifacts\.Configuration'
-\- Task `:docs\-tip\-of\-tree:unzipSourcesForDackka` of type `org\.gradle\.api\.tasks\.Sync`: cannot deserialize object of type 'org\.gradle\.api\.Project' as these are not supported with the configuration cache\.
-\- Task `:docs\-tip\-of\-tree:unzipSourcesForDackka` of type `org\.gradle\.api\.tasks\.Sync`: cannot deserialize object of type 'org\.gradle\.api\.artifacts\.Configuration' as these are not supported with the configuration cache\.
-\- Task `:docs\-tip\-of\-tree:unzipSourcesForDackka` of type `org\.gradle\.api\.tasks\.Sync`: value 'file collection' is not assignable to 'org\.gradle\.api\.artifacts\.Configuration'
-\- Task `:docs\-tip\-of\-tree:unzipDocsSources` of type `org\.gradle\.api\.tasks\.Sync`: cannot deserialize object of type 'org\.gradle\.api\.artifacts\.Configuration' as these are not supported with the configuration cache\.
-\- Task `:docs\-tip\-of\-tree:unzipDocsSources` of type `org\.gradle\.api\.tasks\.Sync`: value 'file collection' is not assignable to 'org\.gradle\.api\.artifacts\.Configuration'
-\- Task `:docs\-tip\-of\-tree:unzipSampleSources` of type `org\.gradle\.api\.tasks\.Sync`: cannot serialize object of type 'org\.gradle\.api\.internal\.project\.DefaultProject', a subtype of 'org\.gradle\.api\.Project', as these are not supported with the configuration cache\.
 [0-9]+ problem was found storing the configuration cache.
 \- Task `:listTaskOutputs` of type `androidx\.build\.ListTaskOutputsTask`: invocation of 'Task\.project' at execution time is unsupported\.
 \- Task `[^ ]*checkExternalLicenses` of type `[^ ]*CheckExternalDependencyLicensesTask`: invocation of 'Task\.project' at execution time is unsupported\.
@@ -390,7 +353,6 @@
 w\: \$SUPPORT\/viewpager[0-9]+\/viewpager[0-9]+\/src\/androidTest\/java\/androidx\/viewpager[0-9]+\/widget\/OnApplyWindowInsetsListenerTest\.kt\: \([0-9]+\, [0-9]+\)\: Unnecessary non\-null assertion \(\!\!\) on a non\-null receiver of type WindowInsetsCompat
 w\: \$SUPPORT\/viewpager[0-9]+\/viewpager[0-9]+\/src\/androidTest\/java\/androidx\/viewpager[0-9]+\/widget\/OnApplyWindowInsetsListenerTest\.kt\: \([0-9]+\, [0-9]+\)\: \'consumeStableInsets\(\)\: WindowInsetsCompat\' is deprecated\. Deprecated in Java
 w\: \$SUPPORT\/viewpager[0-9]+\/viewpager[0-9]+\/src\/androidTest\/java\/androidx\/viewpager[0-9]+\/widget\/OnApplyWindowInsetsListenerTest\.kt\: \([0-9]+\, [0-9]+\)\: \'consumeDisplayCutout\(\)\: WindowInsetsCompat\' is deprecated\. Deprecated in Java
-# > Task :contentpager:contentpager:compileDebugAndroidTestJavaWithJavac
 # > Task :docs-public:dokkaKotlinDocs
 No documentation for .*
 Found an unresolved type in androidx\.compose\.runtime\.snapshots\.SnapshotStateList\$add\(androidx\.compose\.runtime\.snapshots\.SnapshotStateList\.T\) \(SnapshotStateList\.kt:[0-9]+\)
@@ -597,39 +559,8 @@
 \$SUPPORT/compose/ui/ui\-tooling/src/androidAndroidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 No issues found.*
 dagger\.lint\.DaggerIssueRegistry in .*/lint\.jar does not specify a vendor; see IssueRegistry#vendor
-# > Task :camera:camera-camera2-pipe:reportLibraryMetrics
-Info: Stripped invalid locals information from [0-9]+ methods\.
-Info: Methods with invalid locals information:
-java\.lang\.Object androidx\.glance\.appwidget\.GlanceAppWidget\.compose\$glance_appwidget_release\(android\.content\.Context\, android\.appwidget\.AppWidgetManager\, int\, java\.lang\.Object\, android\.os\.Bundle\, kotlin\.coroutines\.Continuation\)
-java\.lang\.Object androidx\.glance\.state\.GlanceState\.getDataStore\(android\.content\.Context, androidx\.glance\.state\.GlanceStateDefinition, java\.lang\.String, kotlin\.coroutines\.Continuation\)
-java\.lang\.Object androidx\.wear\.complications\.ComplicationDataSourceInfoRetriever\.retrievePreviewComplicationData\(android\.content\.ComponentName, androidx\.wear\.complications\.data\.ComplicationType, kotlin\.coroutines\.Continuation\)
-java\.lang\.Object androidx\.wear\.watchface\.editor\.BaseEditorSession\.openComplicationDataSourceChooser\$suspendImpl\(androidx\.wear\.watchface\.editor\.BaseEditorSession, int, kotlin\.coroutines\.Continuation\)
-java\.lang\.Object androidx\.compose\.ui\.platform\.GlobalSnapshotManager\$ensureStarted\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
-java\.lang\.Object androidx\.wear\.watchface\.editor\.BaseEditorSession\$fetchComplicationsData\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
-java\.lang\.Object androidx\.camera\.camera[0-9]+\.pipe\.CameraDevicesKt\$find\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
-java\.lang\.Object androidx\.camera\.camera[0-9]+\.pipe\.compat\.VirtualCameraManager\$requestLoop\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
-Information in locals\-table is invalid with respect to the stack map table\. Local refers to non\-present stack map type for register: [0-9]+ with constraint OBJECT\.
-java\.lang\.Object androidx\.camera\.camera[0-9]+\.pipe\.compat\.VirtualCameraManager\.openCameraWithRetry\-RzXb[0-9]+QE\(java\.lang\.String, kotlinx\.coroutines\.CoroutineScope, kotlin\.coroutines\.Continuation\)
-Information in locals\-table is invalid with respect to the stack map table\. Local refers to non\-present stack map type for register: [0-9]+ with constraint INT\.
-Info: Some warnings are typically a sign of using an outdated Java toolchain\. To fix, recompile the source with an updated toolchain\.
-# > Task :paging:paging-samples:reportLibraryMetrics
-java\.lang\.Object androidx\.paging\.samples\.RemoteMediatorSampleKt\$remoteMediatorItemKeyedSample\$ExampleRemoteMediator\.load\(androidx\.paging\.LoadType, androidx\.paging\.PagingState, kotlin\.coroutines\.Continuation\)
-java\.lang\.Object androidx\.paging\.samples\.RemoteMediatorSampleKt\$remoteMediatorPageKeyedSample\$ExampleRemoteMediator\.load\(androidx\.paging\.LoadType, androidx\.paging\.PagingState, kotlin\.coroutines\.Continuation\)
-# > Task :wear:wear-complications-data:reportLibraryMetrics
-Info: Stripped invalid locals information from [0-9]+ method\.
-# > Task :wear:wear-watchface-editor:reportLibraryMetrics
-java\.lang\.Object androidx\.wear\.watchface\.editor\.BaseEditorSession\.getPreviewData\$wear_watchface_editor_release\(androidx\.wear\.complications\.ComplicationDataSourceInfoRetriever, androidx\.wear\.complications\.ComplicationDataSourceInfo, kotlin\.coroutines\.Continuation\)
-# > Task :work:work-runtime-ktx:reportLibraryMetrics
-java\.lang\.Object androidx\.work\.OperationKt\.await\(androidx\.work\.Operation, kotlin\.coroutines\.Continuation\)
-# > Task :compose:material:material:reportLibraryMetrics
-java\.lang\.Object androidx\.compose\.material\.SnackbarHostState\.showSnackbar\(java\.lang\.String, java\.lang\.String, androidx\.compose\.material\.SnackbarDuration, kotlin\.coroutines\.Continuation\)
 # > Task :compose:foundation:foundation:androidReleaseSourcesJar
 Encountered duplicate path "android[a-zA-Z]*/.+" during copy operation configured with DuplicatesStrategy\.WARN
-# > Task :camera:camera-camera2-pipe:reportLibraryMetrics
-java\.lang\.Object androidx\.camera\.camera[0-9]+\.pipe\.compat\.Camera[0-9]+DeviceCache\$getCameras\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
-Type information in locals\-table is inconsistent\. Cannot constrain type: @Nullable androidx\.camera\.camera[0-9]+\.pipe\.core\.Debug \{\} for value: v[0-9]+\(this_\$iv\$iv\) by constraint INT\.
-# > Task :compose:foundation:foundation:integration-tests:foundation-demos:reportLibraryMetrics
-java\.lang\.Object androidx\.compose\.foundation\.demos\.ListDemosKt\$ListHoistedStateDemo\$[0-9]+\$[0-9]+\$[0-9]+\$[0-9]+\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
 # > Task :profileinstaller:profileinstaller-benchmark:processReleaseAndroidTestManifest
 \$SUPPORT/profileinstaller/profileinstaller\-benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
 # > Task :wear:compose:compose-material-benchmark:processReleaseAndroidTestManifest
@@ -675,3 +606,11 @@
 C/C\+\+: (debug|release)\|(x86_64|x86|arm64\-v8a|armeabi\-v7a) :Packaging for\: (amd\-[0-9]+|armhf\-[0-9]+|x86\-[0-9]+)
 C/C\+\+: (debug|release)\|(x86_64|x86|arm64\-v8a|armeabi\-v7a) :  CMakeLists\.txt:[0-9]+ \(PROJECT\)
 C/C\+\+: (debug|release)\|(x86_64|x86|arm64\-v8a|armeabi\-v7a) :Compiling for ARM
+# > Task :glance:glance:reportLibraryMetrics
+Info: Stripped invalid locals information from [0-9]+ method\.
+Info: Methods with invalid locals information:
+java\.lang\.Object androidx\.glance\.state\.GlanceState\.getDataStore\(android\.content\.Context, androidx\.glance\.state\.GlanceStateDefinition, java\.lang\.String, kotlin\.coroutines\.Continuation\)
+Information in locals\-table is invalid with respect to the stack map table\. Local refers to non\-present stack map type for register: [0-9]+ with constraint OBJECT\.
+Info: Some warnings are typically a sign of using an outdated Java toolchain\. To fix, recompile the source with an updated toolchain\.
+# > Task :compose:ui:ui-inspection:buildCMakeRelWithDebInfo[arm64-v8a]
+C/C\+\+: ninja: warning: bad deps log signature or version; starting over
\ No newline at end of file
diff --git a/development/build_log_simplifier/update.sh b/development/build_log_simplifier/update.sh
index ef8ba07..e5b3a20 100755
--- a/development/build_log_simplifier/update.sh
+++ b/development/build_log_simplifier/update.sh
@@ -54,7 +54,12 @@
     else
       logName="gradle.${i}.log"
     fi
-    if fetch_artifact --bid "$buildId" --target "$target" "logs/$logName"; then
+    filepath="logs/$logName"
+    # incremental build uses a subdirectory
+    if [ "$target" == "androidx_incremental" ]; then
+      filepath="incremental/$filepath"
+    fi
+    if fetch_artifact --bid "$buildId" --target "$target" "$filepath"; then
       echo "downloaded log ${i} in build $buildId target $target"
     else
       echo
diff --git a/development/importMaven/build.gradle.kts b/development/importMaven/build.gradle.kts
index d8a863e..5e20af1 100644
--- a/development/importMaven/build.gradle.kts
+++ b/development/importMaven/build.gradle.kts
@@ -461,12 +461,18 @@
                 }
                 withFiles {
                     addFile("${id.name}-${id.version}.pom")
+                    addFile("${id.name}-${id.version}.pom.asc")
                     addFile("${id.name}-${id.version}.module")
+                    addFile("${id.name}-${id.version}.module.asc")
                     addFile("${id.name}-${id.version}.jar")
+                    addFile("${id.name}-${id.version}.jar.asc")
                     addFile("${id.name}-${id.version}.aar")
+                    addFile("${id.name}-${id.version}.aar.asc")
                     addFile("${id.name}-${id.version}-sources.jar")
                     addFile("${id.name}-${id.version}.klib")
+                    addFile("${id.name}-${id.version}.klib.asc")
                     addFile("${id.name}-${id.version}-cinterop-interop.klib")
+                    addFile("${id.name}-${id.version}-cinterop-interop.klib.asc")
                 }
             }
         }
diff --git a/development/project-creator/create_project.py b/development/project-creator/create_project.py
index 7501453..ae4b191 100755
--- a/development/project-creator/create_project.py
+++ b/development/project-creator/create_project.py
@@ -745,6 +745,10 @@
         project_type = ProjectType.KOTLIN
     else:
         project_type = ask_project_type()
+    insert_new_group_id_into_library_versions_kt(
+        args.group_id,
+        args.artifact_id
+    )
     create_directories(
         args.group_id,
         args.artifact_id,
@@ -752,8 +756,6 @@
         is_compose_project(args.group_id, args.artifact_id)
     )
     update_settings_gradle(args.group_id, args.artifact_id)
-    insert_new_group_id_into_library_versions_kt(args.group_id,
-                                                 args.artifact_id)
     update_docs_tip_of_tree_build_grade(args.group_id, args.artifact_id)
     print("Created directories. \nRunning updateApi for the new "
           "library, this may take a minute...", end='')
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index 6b5e28f..162e164 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -31,13 +31,13 @@
     docs("androidx.biometric:biometric-ktx:1.2.0-alpha04")
     samples("androidx.biometric:biometric-ktx-samples:1.2.0-alpha04")
     docs("androidx.browser:browser:1.4.0")
-    docs("androidx.camera:camera-camera2:1.1.0-alpha10")
-    docs("androidx.camera:camera-core:1.1.0-alpha10")
-    docs("androidx.camera:camera-extensions:1.0.0-alpha30")
+    docs("androidx.camera:camera-camera2:1.1.0-alpha11")
+    docs("androidx.camera:camera-core:1.1.0-alpha11")
+    docs("androidx.camera:camera-extensions:1.0.0-alpha31")
     stubs(fileTree(dir: "../camera/camera-extensions-stub", include: ["camera-extensions-stub.jar"]))
-    docs("androidx.camera:camera-lifecycle:1.1.0-alpha10")
-    docs("androidx.camera:camera-video:1.1.0-alpha10")
-    docs("androidx.camera:camera-view:1.0.0-alpha30")
+    docs("androidx.camera:camera-lifecycle:1.1.0-alpha11")
+    docs("androidx.camera:camera-video:1.1.0-alpha11")
+    docs("androidx.camera:camera-view:1.0.0-alpha31")
     docs("androidx.car.app:app:1.2.0-alpha01")
     docs("androidx.car.app:app-automotive:1.2.0-alpha01")
     docs("androidx.car.app:app-projected:1.2.0-alpha01")
@@ -92,7 +92,7 @@
     docs("androidx.concurrent:concurrent-futures:1.1.0")
     docs("androidx.concurrent:concurrent-futures-ktx:1.1.0")
     docs("androidx.contentpager:contentpager:1.0.0")
-    docs("androidx.coordinatorlayout:coordinatorlayout:1.2.0-alpha01")
+    docs("androidx.coordinatorlayout:coordinatorlayout:1.2.0-beta01")
     docs("androidx.core:core-google-shortcuts:1.1.0-alpha02")
     docs("androidx.core:core-role:1.1.0-alpha02")
     docs("androidx.core:core-animation:1.0.0-alpha02")
@@ -227,7 +227,7 @@
     docs("androidx.slice:slice-builders-ktx:1.0.0-alpha08")
     docs("androidx.slice:slice-core:1.1.0-alpha02")
     docs("androidx.slice:slice-view:1.1.0-alpha02")
-    docs("androidx.slidingpanelayout:slidingpanelayout:1.2.0-beta01")
+    docs("androidx.slidingpanelayout:slidingpanelayout:1.2.0-rc01")
     docs("androidx.sqlite:sqlite:2.2.0-beta02")
     docs("androidx.sqlite:sqlite-framework:2.2.0-beta02")
     docs("androidx.sqlite:sqlite-ktx:2.2.0-beta02")
@@ -278,13 +278,13 @@
     samples("androidx.wear:wear-input-samples:1.2.0-alpha01")
     docs("androidx.wear:wear-input-testing:1.2.0-alpha02")
     docs("androidx.webkit:webkit:1.4.0")
-    docs("androidx.window:window:1.0.0-beta03")
+    docs("androidx.window:window:1.0.0-beta04")
     stubs(fileTree(dir: "../window/stubs/", include: ["window-sidecar-release-0.1.0-alpha01.aar"]))
     stubs("androidx.window:window-extensions:1.0.0-alpha01")
-    docs("androidx.window:window-java:1.0.0-beta03")
-    docs("androidx.window:window-rxjava2:1.0.0-beta03")
-    docs("androidx.window:window-rxjava3:1.0.0-beta03")
-    docs("androidx.window:window-testing:1.0.0-beta03")
+    docs("androidx.window:window-java:1.0.0-beta04")
+    docs("androidx.window:window-rxjava2:1.0.0-beta04")
+    docs("androidx.window:window-rxjava3:1.0.0-beta04")
+    docs("androidx.window:window-testing:1.0.0-beta04")
     docs("androidx.work:work-gcm:2.7.1")
     docs("androidx.work:work-multiprocess:2.7.1")
     docs("androidx.work:work-runtime:2.7.1")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index ab90b85..8b81fb7 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -101,6 +101,7 @@
     docs(project(":core:core-google-shortcuts"))
     docs(project(":core:core-ktx"))
     docs(project(":core:core-performance"))
+    samples(project(":core:core-performance:core-performance-samples"))
     docs(project(":core:core-remoteviews"))
     docs(project(":core:core-splashscreen"))
     docs(project(":core:core-role"))
diff --git a/docs/api_guidelines.md b/docs/api_guidelines.md
index 315585a2..bfeeb4e 100644
--- a/docs/api_guidelines.md
+++ b/docs/api_guidelines.md
@@ -53,7 +53,7 @@
 ```
 <feature-name>/
   <feature-name>-<sub-feature>/ [<feature-name>:<feature-name>-<sub-feature>]
-    samples/ [<feature-name>:<feature-name>-<sub-feature>:samples]
+    samples/ [<feature-name>:<feature-name>-<sub-feature>-samples]
   integration-tests/
     testapp/ [<feature-name>:testapp]
     testlib/ [<feature-name>:testlib]
@@ -101,6 +101,8 @@
 *   `-ktx` for an Kotlin artifact that exposes idiomatic Kotlin APIs as an
     extension to a Java-only library (see
     [additional -ktx guidance](#module-ktx))
+*   `-samples` for sample code which can be inlined in documentation (see
+    [Sample code in Kotlin modules](#sample-code-in-kotlin-modules)
 *   `-<third-party>` for an artifact that integrates an optional third-party API
     surface, e.g. `-proto` or `-rxjava2`. Note that a major version is included
     in the sub-feature name for third-party API surfaces where the major version
@@ -151,7 +153,7 @@
 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/src/main/kotlin/androidx/build/LibraryGroups.kt):
+[`LibraryGroups.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/public/src/main/kotlin/androidx/build/LibraryGroups.kt):
 
 ```kotlin
 // Non-atomic library group
@@ -275,13 +277,14 @@
 *   Superclass **must** be `Object`
 *   Class **must** be non-instantiable, i.e. constructor is private no-op
 *   Static fields and static methods **must** match match signatures with
-    `PlatformClass`
+    `<PlatformClass>`
     *   Static fields that can be inlined, ex. integer constants, **must not**
         be shimmed
 *   Public method names **must** match platform method names
-*   Public methods **must** be static and take `PlatformClass` as first
-    parameter
-*   Implementation *may* delegate to `PlatformClass` methods when available
+*   Public methods **must** be static and take `<PlatformClass>` as first
+    parameter (except in the case of static methods on the platform class, as
+    shown below)
+*   Implementation *may* delegate to `<PlatformClass>` methods when available
 
 #### Sample {#static-shim-sample}
 
@@ -457,12 +460,14 @@
   // loading and prevent optimization.
   @RequiresApi(23)
   private static class Api23Impl {
+    @DoNotInline
     @NonNull
     static ModemInfo create() {
       return new ModemInfo();
     }
 
-    static boolean isLteSupported(PlatformClass obj) {
+    @DoNotInline
+    static boolean isLteSupported(ModemInfo obj) {
       return obj.isLteSupported();
     }
   }
@@ -2152,7 +2157,8 @@
 
 The follow demonstrates how to reference sample functions from public API. It is
 also recommended to reuse these samples in unit tests / integration tests / test
-apps / library demos where possible.
+apps / library demos where possible to help ensure that the samples work as
+intended.
 
 **Public API:**
 
@@ -2178,7 +2184,7 @@
 }
 ```
 
-**Generated documentation visible on d.android.com\***
+**Generated documentation visible on d.android.com / within Android Studio**
 
 ```
 fun fancyPrint(str: String)
@@ -2192,16 +2198,37 @@
 <code>
 ```
 
-\**still some improvements to be made to DAC side, such as syntax highlighting*
+Warning: Only the body of the function is used in generated documentation, so
+any other references to elements defined outside the body of the function (such
+as variables defined within the sample file) will not be visible. To ensure that
+samples can be easily copy and pasted without errors, make sure that any
+references are defined within the body of the function.
 
 ### Module configuration
 
-The following module setups should be used for sample functions, and are
-enforced by lint:
+The following module setups should be used for sample functions:
+
+**Per-module samples**
+
+For library groups with relatively independent sub-libraries. This is the
+recommended project setup, and should be used in most cases.
+
+Gradle project name: `:foo-library:foo-module:foo-module-samples`
+
+```
+foo-library/
+  foo-module/
+    samples/
+```
 
 **Group-level samples**
 
-For library groups with strongly related samples that want to share code.
+For library groups with strongly related samples that want to share code and be
+reused across a library group, a singular shared samples library can be created.
+In most cases this is discouraged - samples should be small and show the usage
+of a particular API / small set of APIs, instead of more complicated usage
+combining multiple APIs from across libraries. For these cases a sample
+application is more appropriate.
 
 Gradle project name: `:foo-library:foo-library-samples`
 
@@ -2212,22 +2239,10 @@
   samples/
 ```
 
-**Per-module samples**
-
-For library groups with complex, relatively independent sub-libraries
-
-Gradle project name: `:foo-library:foo-module:foo-module-samples`
-
-```
-foo-library/
-  foo-module/
-    samples/
-```
-
 **Samples module configuration**
 
 Samples modules are published to GMaven so that they are available to Android
-Studio, which displays code in @Sample annotations as hover-over pop-ups.
+Studio, which displays referenced samples as hover-over pop-ups.
 
 To achieve this, samples modules must declare the same MavenGroup and `publish`
 as the library(s) they are samples for.
diff --git a/docs/benchmarking_images/filter_build.png b/docs/benchmarking_images/filter_build.png
deleted file mode 100644
index f4d15d4..0000000
--- a/docs/benchmarking_images/filter_build.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/filter_initial.png b/docs/benchmarking_images/filter_initial.png
index 61bdc30..b538051 100644
--- a/docs/benchmarking_images/filter_initial.png
+++ b/docs/benchmarking_images/filter_initial.png
Binary files differ
diff --git a/docs/benchmarking_images/filter_metric.png b/docs/benchmarking_images/filter_metric.png
new file mode 100644
index 0000000..0e714fd
--- /dev/null
+++ b/docs/benchmarking_images/filter_metric.png
Binary files differ
diff --git a/docs/benchmarking_images/filter_test.png b/docs/benchmarking_images/filter_test.png
index 9a8a0ee..cfc8a28 100644
--- a/docs/benchmarking_images/filter_test.png
+++ b/docs/benchmarking_images/filter_test.png
Binary files differ
diff --git a/docs/benchmarking_images/triage_bug.png b/docs/benchmarking_images/triage_bug.png
deleted file mode 100644
index 816122c..0000000
--- a/docs/benchmarking_images/triage_bug.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_cl_list.png b/docs/benchmarking_images/triage_cl_list.png
deleted file mode 100644
index d65a7e2..0000000
--- a/docs/benchmarking_images/triage_cl_list.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_complete.png b/docs/benchmarking_images/triage_complete.png
deleted file mode 100644
index 3a04763..0000000
--- a/docs/benchmarking_images/triage_complete.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_graph.png b/docs/benchmarking_images/triage_graph.png
deleted file mode 100644
index 90defbc..0000000
--- a/docs/benchmarking_images/triage_graph.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_initial.png b/docs/benchmarking_images/triage_initial.png
deleted file mode 100644
index ea0d033..0000000
--- a/docs/benchmarking_images/triage_initial.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_regression.png b/docs/benchmarking_images/triage_regression.png
deleted file mode 100644
index bed4b5f..0000000
--- a/docs/benchmarking_images/triage_regression.png
+++ /dev/null
Binary files differ
diff --git a/docs/benchmarking_images/triage_word_cloud.png b/docs/benchmarking_images/triage_word_cloud.png
deleted file mode 100644
index 35dbe43..0000000
--- a/docs/benchmarking_images/triage_word_cloud.png
+++ /dev/null
Binary files differ
diff --git a/docs/gradle_enterprise.md b/docs/gradle_enterprise.md
new file mode 100644
index 0000000..49484441b
--- /dev/null
+++ b/docs/gradle_enterprise.md
@@ -0,0 +1,22 @@
+# Gradle Enterprise
+
+<!--*
+# Document freshness: For more information, see go/fresh-source.
+freshness: { owner: 'rahulrav' reviewed: '2021-11-03' }
+*-->
+
+[TOC]
+
+## Introduction
+
+Gradle Enterprise is used to speed up workflows that use GitHub actions for
+[playground](playground.md) projects.
+
+The Gradle Enterprise Server is running on AWS (`us-east-1`). This service is
+running on a Kubernetes cluster and can serve HTTP2 traffic. This service is
+managed by the Gradle team.
+
+The `FQHN` for the service is `hosted-ge-androidx.gradle.com` (port `443`).
+
+Note: The service will always use a `Location` header `ge.androidx.dev`. That is
+the only `hostname` it deems valid for a request origin.
diff --git a/docs/lint_guide.md b/docs/lint_guide.md
index f3557c3..c89e5d0 100644
--- a/docs/lint_guide.md
+++ b/docs/lint_guide.md
@@ -88,7 +88,7 @@
 `CURRENT_API` is defined by the Lint API version against which your project is
 compiled, as defined in the module's `build.gradle` file. Jetpack Lint modules
 should compile using the Lint API version referenced in
-[Dependencies.kt](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt;l=176).
+[Dependencies.kt](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/public/src/main/kotlin/androidx/build/dependencies/Dependencies.kt;l=176).
 
 We guarantee that our Lint checks work with the versions referenced by `minApi`
 and `api` by running our tests with both versions. For newer versions of Android
diff --git a/docs/macrobenchmarking.md b/docs/macrobenchmarking.md
index a68fa46..69e6251 100644
--- a/docs/macrobenchmarking.md
+++ b/docs/macrobenchmarking.md
@@ -18,15 +18,15 @@
         <td>In-process test of CPU work</td>
     </tr>
     <tr>
-        <td>Slow iteration speed (Often several minutes)</td>
+        <td>Slow iteration speed (Often more than a minute)</td>
         <td>Fast iteration speed (Often less than 10 seconds)</td>
     </tr>
     <tr>
         <td>Results come with profiling traces</td>
-        <td>Optional method sampling/tracing</td>
+        <td>Optional stack sampling/method tracing</td>
     </tr>
     <tr>
-        <td>Min API 29</td>
+        <td>Min API 23</td>
         <td>Min API 14</td>
     </tr>
 </table>
@@ -49,8 +49,6 @@
 #### Kotlin {.new-tab}
 
 ```kotlin
-@RunWith(AndroidJUnit4::class)
-class MyStartupBenchmark {
     @get:Rule
     val benchmarkRule = MacrobenchmarkRule()
 
@@ -67,13 +65,31 @@
         intent.setAction("mypackage.myapp.myaction")
         startActivityAndWait(intent)
     }
-}
 ```
 
 #### Java {.new-tab}
 
 ```java
-// TODO: Java APIs are not yet available.
+    @Rule
+    public MacrobenchmarkRule mBenchmarkRule = MacrobenchmarkRule()
+
+    @Test
+    public void startup() {
+        mBenchmarkRule.measureRepeated(
+                "mypackage.myapp",
+                Collections.singletonList(new StartupTimingMetric()),
+                StartupMode.COLD,
+                /* iterations = */ 5,
+                scope -> {
+                    scope.pressHome();
+                    Intent intent = Intent();
+                    intent.setPackage("mypackage.myapp");
+                    intent.setAction("mypackage.myapp.myaction");
+                    scope.startActivityAndWait(intent);
+                    return Unit.INSTANCE;
+                }
+        );
+    }
 ```
 
 </section>
diff --git a/docs/onboarding.md b/docs/onboarding.md
index 3af170e..005a845 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -618,7 +618,7 @@
 topic) with the dependent library code.
 
 Libraries typically reference dependencies using constants defined in
-[`Dependencies.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt),
+[`Dependencies.kt`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/public/src/main/kotlin/androidx/build/dependencies/Dependencies.kt),
 so please update this file to include a constant for the version of the library
 that you have checked in. You will reference this constant in your library's
 `build.gradle` dependencies.
@@ -888,3 +888,22 @@
 
 Make sure the library versions are the same before and after replacement. Then
 you can build the Android platform code with the new `androidx` code.
+
+### How do I measure library size? {#library-size}
+
+Method count and bytecode size are tracked in CI
+[alongside benchmarks](benchmarking.md#monitoring) to detect regressions.
+
+For local measurements, use the `:reportLibraryMetrics` task. For example:
+
+```shell
+./gradlew benchmark:benchmark-macro:reportLibraryMetrics
+cat ../../out/dist/librarymetrics/androidx.benchmark_benchmark-macro.json
+```
+
+Will output something like: `{"method_count":1256,"bytecode_size":178822}`
+
+Note: this only counts the weight of your library's jar/aar, including
+resources. It does not count library dependencies. It does not account for a
+minification step (e.g. with R8), as that is dynamic, and done at app build time
+(and depend on which entrypoints the app uses).
diff --git a/docs/testability.md b/docs/testability.md
index 52d60a9..ea5c3e3 100644
--- a/docs/testability.md
+++ b/docs/testability.md
@@ -41,7 +41,7 @@
 To get started with sample code, see
 [Sample code in Kotlin modules](api_guidelines.md#sample-code-in-kotlin-modules)
 for information on writing samples that can be referenced from API reference
-documentation or [Project directory structure](policies.md#directory-structure)
+documentation or [Project directory structure](api_guidelines.md#module-structure)
 for module naming guidelines if you'd like to create a basic test app.
 
 ### Avoiding side-effects {#side-effects}
diff --git a/docs/testing.md b/docs/testing.md
index 97ed2a9..d6ad752 100644
--- a/docs/testing.md
+++ b/docs/testing.md
@@ -35,7 +35,7 @@
 ### What gets tested, and when
 
 We use the
-[AffectedModuleDetector](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt)
+[AffectedModuleDetector](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt)
 to determine what projects have changed since the last merge.
 
 In presubmit, "affected" modules will run all host and device tests regardless
@@ -153,6 +153,12 @@
 do NOT open the AndroidX project in the "normal" instance of Android Studio;
 instead, open a normal app or create a blank project using the app wizard.
 
+NOTE You can reuse the emulator and system images from a "normal" installation
+of Android Studio by linking the `emulator` and `system_images` directories to a
+standard Android SDK path and restarting Android Studio: `cd
+prebuilts/fullsdk-darwin ln -s ~/Library/Android/sdk/emulator emulator ln -s
+~/Library/Android/sdk/system-images system-images`
+
 ## Debugging with platform SDK sources {#sources}
 
 The platform SDK sources that are checked into the development branch may not
diff --git a/docs/versioning.md b/docs/versioning.md
index 4c45a9b..88250d7 100644
--- a/docs/versioning.md
+++ b/docs/versioning.md
@@ -340,7 +340,7 @@
 ### How to update your version
 
 1.  Update the version listed in
-    `frameworks/support/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt`
+    `frameworks/support/buildSrc/public/src/main/kotlin/androidx/build/LibraryVersions.kt`
 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/enterprise/enterprise-feedback/build.gradle b/enterprise/enterprise-feedback/build.gradle
index df1412f..fd285db 100644
--- a/enterprise/enterprise-feedback/build.gradle
+++ b/enterprise/enterprise-feedback/build.gradle
@@ -23,11 +23,6 @@
     testOptions.unitTests.includeAndroidResources = true
 }
 
-// Robolectric requires more memory than Gradle default
-tasks.withType(Test) { t ->
-    t.maxHeapSize = "1024m"
-}
-
 androidx {
     name = "Enterprise Feedback"
     publish = Publish.SNAPSHOT_AND_RELEASE
diff --git a/fragment/fragment-ktx/build.gradle b/fragment/fragment-ktx/build.gradle
index f48c186..fdc614d 100644
--- a/fragment/fragment-ktx/build.gradle
+++ b/fragment/fragment-ktx/build.gradle
@@ -39,7 +39,7 @@
         because 'Mirror fragment dependency graph for -ktx artifacts'
     }
     api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
-    api("androidx.savedstate:savedstate-ktx:1.1.0") {
+    api(projectOrArtifact(":savedstate:savedstate-ktx")) {
         because 'Mirror fragment dependency graph for -ktx artifacts'
     }
     api(libs.kotlinStdlib)
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index eedd7b9..e273c7d 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -33,7 +33,7 @@
     api("androidx.lifecycle:lifecycle-livedata-core:2.3.1")
     api("androidx.lifecycle:lifecycle-viewmodel:2.3.1")
     api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1")
-    api("androidx.savedstate:savedstate:1.1.0")
+    api(projectOrArtifact(":savedstate:savedstate"))
     api("androidx.annotation:annotation-experimental:1.0.0")
     api(libs.kotlinStdlib)
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
index c544c120..bfffb85 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentSavedStateRegistryTest.kt
@@ -17,16 +17,22 @@
 package androidx.fragment.app
 
 import android.os.Bundle
+import androidx.activity.result.ActivityResultRegistry
+import androidx.activity.result.contract.ActivityResultContract
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.app.ActivityOptionsCompat
+import androidx.fragment.app.test.ViewModelActivity
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.Lifecycle.State.CREATED
 import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.ViewModelProvider
 import androidx.savedstate.SavedStateRegistry
+import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.testutils.RecreatedActivity
-import androidx.testutils.recreate
+import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -34,52 +40,68 @@
 @LargeTest
 class FragmentSavedStateRegistryTest {
 
-    @Suppress("DEPRECATION")
-    @get:Rule
-    var activityRule = androidx.test.rule.ActivityTestRule(FragmentSavedStateActivity::class.java)
-
-    private fun initializeSavedState(testFragment: Fragment = Fragment()) {
-        activityRule.runOnUiThread {
-            val fragmentManager = activityRule.activity.supportFragmentManager
-            fragmentManager.beginTransaction().add(testFragment, FRAGMENT_TAG).commitNow()
-            assertThat(fragmentManager.findFragmentByTag(FRAGMENT_TAG)).isNotNull()
-            assertThat(testFragment.lifecycle.currentState.isAtLeast(CREATED)).isTrue()
-            val registry = testFragment.savedStateRegistry
-            val savedState = registry.consumeRestoredStateForKey(CALLBACK_KEY)
-            assertThat(savedState).isNull()
-            registry.registerSavedStateProvider(CALLBACK_KEY, DefaultProvider())
-        }
+    private fun ActivityScenario<FragmentSavedStateActivity>.initializeSavedState(
+        testFragment: Fragment = Fragment()
+    ) = withActivity {
+        val fragmentManager = supportFragmentManager
+        fragmentManager.beginTransaction().add(testFragment, FRAGMENT_TAG).commitNow()
+        assertThat(fragmentManager.findFragmentByTag(FRAGMENT_TAG)).isNotNull()
+        assertThat(testFragment.lifecycle.currentState.isAtLeast(CREATED)).isTrue()
+        val registry = testFragment.savedStateRegistry
+        val savedState = registry.consumeRestoredStateForKey(CALLBACK_KEY)
+        assertThat(savedState).isNull()
+        registry.registerSavedStateProvider(CALLBACK_KEY, DefaultProvider())
     }
 
     @Test
     fun savedState() {
-        initializeSavedState()
-        val recreated = activityRule.recreate()
-        activityRule.runOnUiThread {
-            assertThat(recreated.fragment().lifecycle.currentState.isAtLeast(CREATED)).isTrue()
-            checkDefaultSavedState(recreated.fragment().savedStateRegistry)
+        with(ActivityScenario.launch(FragmentSavedStateActivity::class.java)) {
+            initializeSavedState()
+            recreate()
+            withActivity {
+                assertThat(fragment.lifecycle.currentState.isAtLeast(CREATED)).isTrue()
+                checkDefaultSavedState(fragment.savedStateRegistry)
+            }
         }
     }
 
     @Test
     fun savedStateLateInit() {
-        initializeSavedState()
-        val recreated = activityRule.recreate()
-        activityRule.runOnUiThread {
-            recreated.fragment().lifecycle.addObserver(
-                LifecycleEventObserver { _, event ->
-                    if (event == Lifecycle.Event.ON_RESUME) {
-                        checkDefaultSavedState(recreated.fragment().savedStateRegistry)
+        with(ActivityScenario.launch(FragmentSavedStateActivity::class.java)) {
+            initializeSavedState()
+            recreate()
+            withActivity {
+                fragment.lifecycle.addObserver(
+                    LifecycleEventObserver { _, event ->
+                        if (event == Lifecycle.Event.ON_RESUME) {
+                            checkDefaultSavedState(fragment.savedStateRegistry)
+                        }
                     }
-                }
-            )
+                )
+            }
         }
     }
 
     @Test
     fun savedStateEarlyRegister() {
-        initializeSavedState(OnCreateCheckingFragment())
-        activityRule.recreate()
+        with(ActivityScenario.launch(FragmentSavedStateActivity::class.java)) {
+            initializeSavedState(OnCreateCheckingFragment())
+            recreate()
+        }
+    }
+
+    @Test
+    fun savedStateOnActivityResult() {
+        with(ActivityScenario.launch(FragmentSavedStateActivity::class.java)) {
+            val registry = withActivity { registry }
+            initializeSavedState(OnActivityResultCheckingFragment(registry))
+            recreate()
+            moveToState(Lifecycle.State.CREATED)
+            withActivity {
+                (fragment as OnActivityResultCheckingFragment).launcher.launch("")
+            }
+            moveToState(Lifecycle.State.RESUMED)
+        }
     }
 }
 
@@ -90,7 +112,32 @@
 }
 
 class FragmentSavedStateActivity : RecreatedActivity() {
-    fun fragment() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)
+    val registry = object : ActivityResultRegistry() {
+        override fun <I : Any?, O : Any?> onLaunch(
+            requestCode: Int,
+            contract: ActivityResultContract<I, O>,
+            input: I,
+            options: ActivityOptionsCompat?
+        ) {
+            if (contract is ActivityResultContracts.GetContent) {
+                dispatchResult(requestCode, null)
+            }
+        }
+    }
+
+    init {
+        supportFragmentManager.fragmentFactory = object : FragmentFactory() {
+            override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
+                return when (loadFragmentClass(classLoader, className)) {
+                    OnActivityResultCheckingFragment::class.java ->
+                        OnActivityResultCheckingFragment(registry)
+                    else -> super.instantiate(classLoader, className)
+                }
+            }
+        }
+    }
+
+    val fragment: Fragment get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)
         ?: throw IllegalStateException("Fragment under test wasn't found")
 }
 
@@ -103,6 +150,23 @@
     }
 }
 
+class OnActivityResultCheckingFragment(
+    activityResultRegistry: ActivityResultRegistry
+) : Fragment() {
+    val viewModel by lazy {
+        ViewModelProvider(this).get(ViewModelActivity.TestSavedStateViewModel::class.java)
+    }
+
+    val launcher = registerForActivityResult(
+        ActivityResultContracts.GetContent(),
+        activityResultRegistry
+    ) {
+        // Accessing the ViewModel is what triggers the startup behavior of
+        // SavedStateRegistryController
+        viewModel
+    }
+}
+
 private class DefaultProvider : SavedStateRegistry.SavedStateProvider {
     override fun saveState() = Bundle().apply { putString(KEY, VALUE) }
 }
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
index 8dc962e..8fcec63 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
@@ -572,6 +572,12 @@
         // The default factory depends on the SavedStateRegistry so it
         // needs to be reset when the SavedStateRegistry is reset
         mDefaultFactory = null;
+        registerOnPreAttachListener(new OnPreAttachedListener() {
+            @Override
+            void onPreAttached() {
+                mSavedStateRegistryController.performAttach();
+            }
+        });
     }
 
     /**
diff --git a/glance/glance-appwidget-proto/build.gradle b/glance/glance-appwidget-proto/build.gradle
index 0e76d43..0346460 100644
--- a/glance/glance-appwidget-proto/build.gradle
+++ b/glance/glance-appwidget-proto/build.gradle
@@ -37,7 +37,7 @@
 dependencies {
     api(libs.kotlinStdlib)
 
-    implementation project(path: ':datastore:datastore-core')
+    implementation("androidx.datastore:datastore-core:1.0.0")
 
     shadowed(libs.protobufLite)
 }
@@ -97,7 +97,6 @@
 androidx {
     name = "Glance AppWidget Protos"
     type = LibraryType.PUBLISHED_LIBRARY
-    publish = Publish.SNAPSHOT_ONLY
     mavenGroup = LibraryGroups.GLANCE
     inceptionYear = "2021"
     runApiTasks = new RunApiTasks.No("No public API required for internal use with app widgets.")
diff --git a/glance/glance-appwidget/api/current.txt b/glance/glance-appwidget/api/current.txt
index b3a2824..4f93a5f 100644
--- a/glance/glance-appwidget/api/current.txt
+++ b/glance/glance-appwidget/api/current.txt
@@ -27,7 +27,7 @@
   }
 
   public final class CheckBoxKt {
-    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(long checkedColor, long uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(optional androidx.glance.unit.ColorProvider? checkedColor, optional androidx.glance.unit.ColorProvider? uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(@ColorRes int checkBoxColor);
@@ -35,9 +35,7 @@
 
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
-    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> getLocalUiKey();
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
-    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> LocalUiKey;
   }
 
   public final class CornerRadiusKt {
@@ -56,12 +54,15 @@
     method @androidx.compose.runtime.Composable public abstract void Content();
     method public androidx.glance.appwidget.SizeMode getSizeMode();
     method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     property public androidx.glance.appwidget.SizeMode sizeMode;
     property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
   }
 
   public final class GlanceAppWidgetKt {
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
   }
 
   public final class GlanceAppWidgetManager {
@@ -89,6 +90,9 @@
   public final class LayoutSelectionKt {
   }
 
+  public final class ListAdapterTrampolineKt {
+  }
+
   public final class NormalizeCompositionTreeKt {
   }
 
@@ -122,7 +126,7 @@
   }
 
   public final class SwitchKt {
-    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(optional androidx.glance.unit.ColorProvider? checkedThumbColor, optional androidx.glance.unit.ColorProvider? uncheckedThumbColor, optional androidx.glance.unit.ColorProvider? checkedTrackColor, optional androidx.glance.unit.ColorProvider? uncheckedTrackColor);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(@ColorRes int thumbColor, optional @ColorRes int trackColor);
   }
@@ -142,7 +146,22 @@
   }
 
   public final class LaunchActivityIntentActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class LaunchBroadcastActionKt {
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionLaunchBroadcastReceiver(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action! actionLaunchBroadcastReceiver();
+  }
+
+  public final class LaunchServiceActionKt {
+    method public static androidx.glance.action.Action actionLaunchService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionLaunchService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionLaunchService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action! actionLaunchService(optional boolean isForegroundService);
   }
 
   public final class RunCallbackActionKt {
@@ -150,6 +169,11 @@
     method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action! actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
   }
 
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
 }
 
 package androidx.glance.appwidget.lazy {
@@ -181,6 +205,17 @@
 
 }
 
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+}
+
 package androidx.glance.appwidget.translators {
 
   public final class CheckBoxTranslatorKt {
diff --git a/glance/glance-appwidget/api/public_plus_experimental_current.txt b/glance/glance-appwidget/api/public_plus_experimental_current.txt
index b3a2824..4f93a5f 100644
--- a/glance/glance-appwidget/api/public_plus_experimental_current.txt
+++ b/glance/glance-appwidget/api/public_plus_experimental_current.txt
@@ -27,7 +27,7 @@
   }
 
   public final class CheckBoxKt {
-    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(long checkedColor, long uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(optional androidx.glance.unit.ColorProvider? checkedColor, optional androidx.glance.unit.ColorProvider? uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(@ColorRes int checkBoxColor);
@@ -35,9 +35,7 @@
 
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
-    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> getLocalUiKey();
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
-    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> LocalUiKey;
   }
 
   public final class CornerRadiusKt {
@@ -56,12 +54,15 @@
     method @androidx.compose.runtime.Composable public abstract void Content();
     method public androidx.glance.appwidget.SizeMode getSizeMode();
     method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     property public androidx.glance.appwidget.SizeMode sizeMode;
     property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
   }
 
   public final class GlanceAppWidgetKt {
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
   }
 
   public final class GlanceAppWidgetManager {
@@ -89,6 +90,9 @@
   public final class LayoutSelectionKt {
   }
 
+  public final class ListAdapterTrampolineKt {
+  }
+
   public final class NormalizeCompositionTreeKt {
   }
 
@@ -122,7 +126,7 @@
   }
 
   public final class SwitchKt {
-    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(optional androidx.glance.unit.ColorProvider? checkedThumbColor, optional androidx.glance.unit.ColorProvider? uncheckedThumbColor, optional androidx.glance.unit.ColorProvider? checkedTrackColor, optional androidx.glance.unit.ColorProvider? uncheckedTrackColor);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(@ColorRes int thumbColor, optional @ColorRes int trackColor);
   }
@@ -142,7 +146,22 @@
   }
 
   public final class LaunchActivityIntentActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class LaunchBroadcastActionKt {
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionLaunchBroadcastReceiver(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action! actionLaunchBroadcastReceiver();
+  }
+
+  public final class LaunchServiceActionKt {
+    method public static androidx.glance.action.Action actionLaunchService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionLaunchService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionLaunchService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action! actionLaunchService(optional boolean isForegroundService);
   }
 
   public final class RunCallbackActionKt {
@@ -150,6 +169,11 @@
     method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action! actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
   }
 
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
 }
 
 package androidx.glance.appwidget.lazy {
@@ -181,6 +205,17 @@
 
 }
 
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+}
+
 package androidx.glance.appwidget.translators {
 
   public final class CheckBoxTranslatorKt {
diff --git a/glance/glance-appwidget/api/restricted_current.txt b/glance/glance-appwidget/api/restricted_current.txt
index b3a2824..4f93a5f 100644
--- a/glance/glance-appwidget/api/restricted_current.txt
+++ b/glance/glance-appwidget/api/restricted_current.txt
@@ -27,7 +27,7 @@
   }
 
   public final class CheckBoxKt {
-    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
+    method @androidx.compose.runtime.Composable public static void CheckBox(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.CheckBoxColors colors);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(long checkedColor, long uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(optional androidx.glance.unit.ColorProvider? checkedColor, optional androidx.glance.unit.ColorProvider? uncheckedColor);
     method public static androidx.glance.appwidget.CheckBoxColors CheckBoxColors(@ColorRes int checkBoxColor);
@@ -35,9 +35,7 @@
 
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> getLocalAppWidgetOptions();
-    method public static androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> getLocalUiKey();
     property public static final androidx.compose.runtime.ProvidableCompositionLocal<android.os.Bundle> LocalAppWidgetOptions;
-    property public static final androidx.compose.runtime.ProvidableCompositionLocal<java.lang.String> LocalUiKey;
   }
 
   public final class CornerRadiusKt {
@@ -56,12 +54,15 @@
     method @androidx.compose.runtime.Composable public abstract void Content();
     method public androidx.glance.appwidget.SizeMode getSizeMode();
     method public androidx.glance.state.GlanceStateDefinition<?>? getStateDefinition();
+    method public suspend Object? onDelete(androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     method public final suspend Object? update(android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
     property public androidx.glance.appwidget.SizeMode sizeMode;
     property public androidx.glance.state.GlanceStateDefinition<?>? stateDefinition;
   }
 
   public final class GlanceAppWidgetKt {
+    method public static suspend Object? updateAll(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public static suspend inline <reified State> void updateIf(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, kotlin.jvm.functions.Function1<? super State,? extends java.lang.Boolean> predicate);
   }
 
   public final class GlanceAppWidgetManager {
@@ -89,6 +90,9 @@
   public final class LayoutSelectionKt {
   }
 
+  public final class ListAdapterTrampolineKt {
+  }
+
   public final class NormalizeCompositionTreeKt {
   }
 
@@ -122,7 +126,7 @@
   }
 
   public final class SwitchKt {
-    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
+    method @androidx.compose.runtime.Composable public static void Switch(boolean checked, androidx.glance.action.Action? onCheckedChange, optional androidx.glance.GlanceModifier modifier, optional String text, optional androidx.glance.text.TextStyle? style, optional androidx.glance.appwidget.SwitchColors colors);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(optional androidx.glance.unit.ColorProvider? checkedThumbColor, optional androidx.glance.unit.ColorProvider? uncheckedThumbColor, optional androidx.glance.unit.ColorProvider? checkedTrackColor, optional androidx.glance.unit.ColorProvider? uncheckedTrackColor);
     method public static androidx.glance.appwidget.SwitchColors SwitchColors(@ColorRes int thumbColor, optional @ColorRes int trackColor);
   }
@@ -142,7 +146,22 @@
   }
 
   public final class LaunchActivityIntentActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.Intent intent, optional androidx.glance.action.ActionParameters parameters);
+  }
+
+  public final class LaunchBroadcastActionKt {
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(String action, optional android.content.ComponentName? componentName);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.Intent intent);
+    method public static androidx.glance.action.Action actionLaunchBroadcastReceiver(android.content.ComponentName componentName);
+    method public static <T extends android.content.BroadcastReceiver> androidx.glance.action.Action actionLaunchBroadcastReceiver(Class<T> receiver);
+    method public static inline <reified T extends android.content.BroadcastReceiver> androidx.glance.action.Action! actionLaunchBroadcastReceiver();
+  }
+
+  public final class LaunchServiceActionKt {
+    method public static androidx.glance.action.Action actionLaunchService(android.content.Intent intent, optional boolean isForegroundService);
+    method public static androidx.glance.action.Action actionLaunchService(android.content.ComponentName componentName, optional boolean isForegroundService);
+    method public static <T extends android.app.Service> androidx.glance.action.Action actionLaunchService(Class<T> service, optional boolean isForegroundService);
+    method public static inline <reified T extends android.app.Service> androidx.glance.action.Action! actionLaunchService(optional boolean isForegroundService);
   }
 
   public final class RunCallbackActionKt {
@@ -150,6 +169,11 @@
     method public static inline <reified T extends androidx.glance.appwidget.action.ActionCallback> androidx.glance.action.Action! actionRunCallback(optional androidx.glance.action.ActionParameters parameters);
   }
 
+  public final class ToggleableKt {
+    method public static androidx.glance.action.ActionParameters.Key<java.lang.Boolean> getToggleableStateKey();
+    property public static final androidx.glance.action.ActionParameters.Key<java.lang.Boolean> ToggleableStateKey;
+  }
+
 }
 
 package androidx.glance.appwidget.lazy {
@@ -181,6 +205,17 @@
 
 }
 
+package androidx.glance.appwidget.state {
+
+  public final class GlanceAppWidgetStateKt {
+    method public static suspend <T> Object? getAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? getAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+    method public static suspend <T> Object? updateAppWidgetState(androidx.glance.appwidget.GlanceAppWidget, android.content.Context context, androidx.glance.GlanceId glanceId, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateState, kotlin.coroutines.Continuation<? super T> p);
+  }
+
+}
+
 package androidx.glance.appwidget.translators {
 
   public final class CheckBoxTranslatorKt {
diff --git a/glance/glance-appwidget/build.gradle b/glance/glance-appwidget/build.gradle
index 79caab8..0567a06 100644
--- a/glance/glance-appwidget/build.gradle
+++ b/glance/glance-appwidget/build.gradle
@@ -40,16 +40,15 @@
     api("androidx.compose.ui:ui-graphics:1.1.0-beta01")
     api("androidx.compose.ui:ui-unit:1.1.0-beta01")
 
-    implementation project(path: ':core:core-remoteviews')
-    implementation project(path: ':core:core-ktx')
-    implementation project(path: ':datastore:datastore-core')
-    implementation project(path: ':datastore:datastore')
+    implementation('androidx.core:core-ktx:1.7.0')
+    implementation("androidx.datastore:datastore:1.0.0")
+    implementation("androidx.datastore:datastore-core:1.0.0")
     implementation("androidx.datastore:datastore-preferences-core:1.0.0")
     implementation("androidx.datastore:datastore-preferences:1.0.0")
+    implementation(project(':core:core-remoteviews'))
     implementation(project(":glance:glance-appwidget-proto"))
     implementation(libs.kotlinStdlib)
 
-    testImplementation(project(":core:core-ktx"))
     testImplementation(libs.junit)
     testImplementation(libs.kotlinCoroutinesTest)
     testImplementation(libs.kotlinTest)
@@ -61,13 +60,14 @@
     testImplementation(libs.testRunner)
     testImplementation(libs.truth)
     testImplementation(libs.kotlinReflect)
+    testImplementation('androidx.core:core-ktx:1.7.0')
     testImplementation("androidx.datastore:datastore-core:1.0.0")
     testImplementation("androidx.datastore:datastore-preferences-core:1.0.0")
     testImplementation("androidx.datastore:datastore-preferences:1.0.0")
 
-    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
     androidTestImplementation(project(":test:screenshot:screenshot"))
-    androidTestImplementation(project(":core:core-ktx"))
+    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
+    androidTestImplementation('androidx.core:core-ktx:1.7.0')
     androidTestImplementation(libs.espressoCore)
     androidTestImplementation(libs.espressoIdlingResource)
     androidTestImplementation(libs.kotlinCoroutinesTest)
@@ -99,7 +99,6 @@
 androidx {
     name = "Glance For App Widgets"
     type = LibraryType.PUBLISHED_LIBRARY
-    publish = Publish.SNAPSHOT_ONLY
     mavenGroup = LibraryGroups.GLANCE
     inceptionYear = "2021"
     description = "Glance-appwidgets allows developers to build layouts for Android AppWidgets " +
diff --git a/glance/glance-appwidget/glance-layout-generator/src/main/kotlin/androidx/glance/appwidget/layoutgenerator/LayoutGenerator.kt b/glance/glance-appwidget/glance-layout-generator/src/main/kotlin/androidx/glance/appwidget/layoutgenerator/LayoutGenerator.kt
index 6a82308..74ce99f 100644
--- a/glance/glance-appwidget/glance-layout-generator/src/main/kotlin/androidx/glance/appwidget/layoutgenerator/LayoutGenerator.kt
+++ b/glance/glance-appwidget/glance-layout-generator/src/main/kotlin/androidx/glance/appwidget/layoutgenerator/LayoutGenerator.kt
@@ -323,6 +323,7 @@
                 setNamedItemNS(androidId("@id/rootView"))
                 setNamedItemNS(androidWidth(width))
                 setNamedItemNS(androidHeight(height))
+                setNamedItemNS(androidAttr("theme", "@style/Glance.AppWidget.Theme"))
             }
             val stub = createElement("ViewStub")
             root.appendChild(stub)
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 0d11ac0..6039b6b 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/AndroidManifest.xml
@@ -34,6 +34,7 @@
         </activity>
 
         <activity android:name=".ActionDemoActivity" />
+        <service android:name=".ActionDemoService" />
 
         <activity android:name=".ListClickDestinationActivity" android:exported="false" />
 
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
index fd7fcd2..c7e91e5 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ActionAppWidget.kt
@@ -16,43 +16,61 @@
 
 package androidx.glance.appwidget.demos
 
-import android.app.Activity
+import android.app.Service
+import android.appwidget.AppWidgetManager
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.os.IBinder
+import android.util.Log
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.intPreferencesKey
 import androidx.glance.Button
 import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
-import androidx.glance.Image
-import androidx.glance.ImageProvider
 import androidx.glance.LocalContext
-import androidx.glance.appwidget.action.ActionCallback
 import androidx.glance.action.ActionParameters
 import androidx.glance.action.actionLaunchActivity
 import androidx.glance.action.actionParametersOf
-import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.action.clickable
+import androidx.glance.action.toParametersKey
 import androidx.glance.appwidget.GlanceAppWidget
 import androidx.glance.appwidget.GlanceAppWidgetReceiver
+import androidx.glance.appwidget.action.ActionCallback
 import androidx.glance.appwidget.action.actionLaunchActivity
+import androidx.glance.appwidget.action.actionLaunchBroadcastReceiver
+import androidx.glance.appwidget.action.actionLaunchService
+import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.appwidget.appWidgetBackground
 import androidx.glance.appwidget.cornerRadius
+import androidx.glance.appwidget.state.updateAppWidgetState
+import androidx.glance.appwidget.unit.ColorProvider
+import androidx.glance.currentState
 import androidx.glance.layout.Alignment
 import androidx.glance.layout.Column
+import androidx.glance.layout.Row
 import androidx.glance.layout.fillMaxSize
+import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
-import androidx.glance.layout.size
+import androidx.glance.state.PreferencesGlanceStateDefinition
 import androidx.glance.text.FontWeight
 import androidx.glance.text.Text
 import androidx.glance.text.TextDecoration
 import androidx.glance.text.TextStyle
-import java.util.concurrent.atomic.AtomicBoolean
 
 class ActionAppWidget : GlanceAppWidget() {
 
+    override val stateDefinition = PreferencesGlanceStateDefinition
+
     @Composable
     override fun Content() {
         Column(
@@ -61,71 +79,185 @@
             verticalAlignment = Alignment.Vertical.CenterVertically,
             horizontalAlignment = Alignment.Horizontal.CenterHorizontally
         ) {
-            Text(
-                text = "Tap to change me",
-                style = TextStyle(
-                    fontSize = 16.sp, fontWeight = FontWeight.Bold,
-                    textDecoration = if (shouldChangeView.get()) {
-                        TextDecoration.Underline
-                    } else {
-                        TextDecoration.None
-                    }
-                ),
-                modifier = GlanceModifier
-                    .padding(8.dp)
-                    .clickable(
-                        actionRunCallback<UpdateAction>(
-                            actionParametersOf(
-                                KEY_USE_UNDERLINE to shouldChangeView.get()
-                            )
-                        )
-                    )
-            )
-            if (shouldChangeView.get()) {
-                Image(
-                    ImageProvider(R.drawable.compose),
-                    "Compose",
-                    modifier = GlanceModifier.size(40.dp)
-                )
+            Row(GlanceModifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
+                SelectableActionItem(label = "Activities", index = 0)
+                SelectableActionItem(label = "Services", index = 1)
+                SelectableActionItem(label = "Broadcasts", index = 2)
             }
-            Button(
-                text = "Intent",
-                onClick = actionLaunchActivity(
-                    Intent(LocalContext.current, ActionDemoActivity::class.java)
-                )
-            )
-            Button(
-                text = "Target class",
-                onClick = actionLaunchActivity<ActionDemoActivity>()
-            )
-            Button(
-                text = "Component name",
-                onClick = actionLaunchActivity(
-                    ComponentName(LocalContext.current, ActionDemoActivity::class.java)
-                )
-            )
+
+            when (currentState<Preferences>()[selectedItemKey] ?: 0) {
+                0 -> LaunchActivityActions()
+                1 -> LaunchServiceActions()
+                2 -> LaunchBroadcastReceiverActions()
+                else -> throw IllegalArgumentException("Wrong index selected")
+            }
         }
     }
 }
 
-private val KEY_USE_UNDERLINE = ActionParameters.Key<Boolean>("underline")
-private var shouldChangeView = AtomicBoolean(false)
+private val selectedItemKey = intPreferencesKey("selectedItemKey")
+private val launchMessageKey = ActionParameters.Key<String>("launchMessageKey")
+
+@Composable
+private fun SelectableActionItem(label: String, index: Int) {
+    val style = if (index == currentState<Preferences>()[selectedItemKey] ?: 0) {
+        TextStyle(
+            fontSize = 16.sp,
+            fontWeight = FontWeight.Bold,
+            textDecoration = TextDecoration.Underline,
+        )
+    } else {
+        TextStyle(
+            fontSize = 16.sp,
+            fontWeight = FontWeight.Normal,
+            textDecoration = TextDecoration.None,
+            color = ColorProvider(
+                Color.Black.copy(alpha = 0.3f),
+                Color.White.copy(alpha = 0.3f)
+            )
+        )
+    }
+    Text(
+        text = label,
+        style = style,
+        modifier = GlanceModifier
+            .padding(8.dp)
+            .clickable(
+                actionRunCallback<UpdateAction>(
+                    actionParametersOf(
+                        selectedItemKey.toParametersKey() to index
+                    )
+                )
+            )
+    )
+}
+
+@Composable
+private fun LaunchActivityActions() {
+    Button(
+        text = "Intent",
+        onClick = actionLaunchActivity(
+            Intent(LocalContext.current, ActionDemoActivity::class.java)
+        )
+    )
+    Button(
+        text = "Target class",
+        onClick = actionLaunchActivity<ActionDemoActivity>(
+            actionParametersOf(
+                launchMessageKey to "Launch activity by target class"
+            )
+        )
+    )
+    Button(
+        text = "Component name",
+        onClick = actionLaunchActivity(
+            ComponentName(LocalContext.current, ActionDemoActivity::class.java)
+        )
+    )
+}
+
+@Composable
+private fun LaunchServiceActions() {
+    Button(
+        text = "Intent",
+        onClick = actionLaunchService(
+            Intent(LocalContext.current, ActionDemoService::class.java)
+        )
+    )
+    Button(
+        text = "Target class",
+        onClick = actionLaunchService<ActionDemoService>()
+    )
+    Button(
+        text = "In foreground",
+        onClick = actionLaunchService<ActionDemoService>(isForegroundService = true)
+    )
+    Button(
+        text = "Component name",
+        onClick = actionLaunchService(
+            ComponentName(LocalContext.current, ActionDemoService::class.java)
+        )
+    )
+}
+
+@Composable
+private fun LaunchBroadcastReceiverActions() {
+    Button(
+        text = "Intent",
+        onClick = actionLaunchBroadcastReceiver(
+            Intent(LocalContext.current, ActionAppWidgetReceiver::class.java)
+        )
+    )
+    Button(
+        text = "Action",
+        onClick = actionLaunchBroadcastReceiver(
+            AppWidgetManager.ACTION_APPWIDGET_UPDATE
+        )
+    )
+    Button(
+        text = "Target class",
+        onClick = actionLaunchBroadcastReceiver<ActionAppWidgetReceiver>()
+    )
+    Button(
+        text = "Component name",
+        onClick = actionLaunchBroadcastReceiver(
+            ComponentName(LocalContext.current, ActionAppWidgetReceiver::class.java)
+        )
+    )
+}
 
 /**
- * Action to update the [shouldChangeView] value whenever users clicks on text
+ * Action to update the [selectedItemKey] value whenever users clicks on text
  */
 class UpdateAction : ActionCallback {
     override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
-        shouldChangeView.set(!parameters.getOrDefault(KEY_USE_UNDERLINE, false))
-        ActionAppWidget().update(context, glanceId)
+        val actionAppWidget = ActionAppWidget()
+        actionAppWidget.updateAppWidgetState<Preferences>(context, glanceId) { prefs ->
+            prefs.toMutablePreferences().apply {
+                this[selectedItemKey] = parameters[selectedItemKey.toParametersKey()] ?: 0
+            }
+        }
+        actionAppWidget.update(context, glanceId)
     }
 }
 
 /**
  * Placeholder activity to launch via [actionLaunchActivity]
  */
-class ActionDemoActivity : Activity()
+class ActionDemoActivity : ComponentActivity() {
+
+    override fun onResume() {
+        super.onResume()
+        setContent {
+            Box(
+                modifier = Modifier.fillMaxSize(),
+                contentAlignment = androidx.compose.ui.Alignment.Center
+            ) {
+                val message = intent.getStringExtra(launchMessageKey.name) ?: "Not found"
+                androidx.compose.material.Text(message)
+            }
+        }
+        Log.d(this::class.simpleName, "Action Demo Activity: ${intent.extras}")
+    }
+}
+
+/**
+ * Placeholder service to launch via [actionLaunchService]
+ */
+class ActionDemoService : Service() {
+    override fun onBind(intent: Intent?): IBinder? = null
+
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+        Log.d(this::class.simpleName, "Action Demo Service: $intent")
+        return super.onStartCommand(intent, flags, startId)
+    }
+}
 
 class ActionAppWidgetReceiver : GlanceAppWidgetReceiver() {
     override val glanceAppWidget: GlanceAppWidget = ActionAppWidget()
+
+    override fun onReceive(context: Context, intent: Intent) {
+        super.onReceive(context, intent)
+        Log.d(this::class.simpleName, "Action Demo Broadcast: $intent")
+    }
 }
\ No newline at end of file
diff --git a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/CompoundButtonAppWidget.kt b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/CompoundButtonAppWidget.kt
index fdb499c..8e83b33 100644
--- a/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/CompoundButtonAppWidget.kt
+++ b/glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/CompoundButtonAppWidget.kt
@@ -19,32 +19,28 @@
 import android.content.Context
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
-import androidx.datastore.core.DataStore
-import androidx.datastore.preferences.core.PreferenceDataStoreFactory
 import androidx.datastore.preferences.core.Preferences
-import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.booleanPreferencesKey
 import androidx.datastore.preferences.core.intPreferencesKey
-import androidx.datastore.preferences.preferencesDataStoreFile
 import androidx.glance.Button
 import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
-import androidx.glance.LocalSize
 import androidx.glance.action.ActionParameters
-import androidx.glance.appwidget.action.ActionCallback
-import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.action.actionParametersOf
 import androidx.glance.appwidget.CheckBox
 import androidx.glance.appwidget.CheckBoxColors
 import androidx.glance.appwidget.GlanceAppWidget
 import androidx.glance.appwidget.GlanceAppWidgetReceiver
-import androidx.glance.appwidget.LocalUiKey
 import androidx.glance.appwidget.SizeMode
 import androidx.glance.appwidget.Switch
 import androidx.glance.appwidget.SwitchColors
+import androidx.glance.appwidget.action.ActionCallback
+import androidx.glance.appwidget.action.actionRunCallback
+import androidx.glance.appwidget.action.ToggleableStateKey
 import androidx.glance.appwidget.appWidgetBackground
 import androidx.glance.appwidget.cornerRadius
+import androidx.glance.appwidget.state.updateAppWidgetState
 import androidx.glance.appwidget.unit.ColorProvider
 import androidx.glance.background
 import androidx.glance.currentState
@@ -54,23 +50,25 @@
 import androidx.glance.layout.fillMaxSize
 import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
-import androidx.glance.state.GlanceState
 import androidx.glance.state.GlanceStateDefinition
+import androidx.glance.state.PreferencesGlanceStateDefinition
 import androidx.glance.text.FontStyle
 import androidx.glance.text.FontWeight
 import androidx.glance.text.Text
 import androidx.glance.text.TextStyle
-import java.io.File
 
 class CompoundButtonAppWidget : GlanceAppWidget() {
 
     override val sizeMode: SizeMode = SizeMode.Exact
-    override var stateDefinition: GlanceStateDefinition<*> = MyStateDefinition
+    override var stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition
+
+    enum class Buttons {
+        CHECK_1, CHECK_2, CHECK_3, SWITCH_1, SWITCH_2;
+        val prefsKey = booleanPreferencesKey(name)
+    }
 
     @Composable
     override fun Content() {
-        val size = LocalSize.current
-        val toggled = size.width >= 150.dp
         Column(
             modifier = GlanceModifier.fillMaxSize().background(Color.LightGray)
                 .padding(R.dimen.external_padding).cornerRadius(R.dimen.corner_radius)
@@ -86,9 +84,25 @@
             )
             val fillModifier = GlanceModifier.fillMaxWidth()
 
-            CheckBox(checked = toggled, text = "Checkbox 1")
+            val prefs = currentState<Preferences>()
+            val checkbox1Checked = prefs[Buttons.CHECK_1.prefsKey] ?: false
+            val checkbox2Checked = prefs[Buttons.CHECK_2.prefsKey] ?: false
+            val checkbox3Checked = prefs[Buttons.CHECK_3.prefsKey] ?: false
+            val switch1Checked = prefs[Buttons.SWITCH_1.prefsKey] ?: false
+            val switch2Checked = prefs[Buttons.SWITCH_2.prefsKey] ?: false
+
             CheckBox(
-                checked = !toggled,
+                checked = checkbox1Checked,
+                onCheckedChange = actionRunCallback<ToggleAction>(
+                    actionParametersOf(eventTargetKey to Buttons.CHECK_1.name)
+                ),
+                text = "Checkbox 1"
+            )
+            CheckBox(
+                checked = checkbox2Checked,
+                onCheckedChange = actionRunCallback<ToggleAction>(
+                    actionParametersOf(eventTargetKey to Buttons.CHECK_2.name)
+                ),
                 text = "Checkbox 2",
                 style = textStyle,
                 modifier = fillModifier,
@@ -98,22 +112,31 @@
                 )
             )
             CheckBox(
-                checked = toggled,
+                checked = checkbox3Checked,
+                onCheckedChange = actionRunCallback<ToggleAction>(
+                    actionParametersOf(eventTargetKey to Buttons.CHECK_3.name)
+                ),
                 text = "Checkbox 3",
                 colors = CheckBoxColors(R.color.my_checkbox_colors)
             )
             Switch(
-                checked = toggled,
+                checked = switch1Checked,
+                onCheckedChange = actionRunCallback<ToggleAction>(
+                    actionParametersOf(eventTargetKey to Buttons.SWITCH_1.name)
+                ),
                 text = "Switch 1",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(day = Color.Red, night = Color.Cyan),
                     uncheckedThumbColor = ColorProvider(day = Color.Green, night = Color.Magenta),
                     checkedTrackColor = ColorProvider(day = Color.Blue, night = Color.Yellow),
                     uncheckedTrackColor = ColorProvider(day = Color.Magenta, night = Color.Green)
-                )
+                ),
             )
             Switch(
-                checked = !toggled,
+                checked = switch2Checked,
+                onCheckedChange = actionRunCallback<ToggleAction>(
+                    actionParametersOf(eventTargetKey to Buttons.SWITCH_2.name)
+                ),
                 text = "Switch 2",
                 style = textStyle,
                 modifier = fillModifier
@@ -126,13 +149,11 @@
 @Composable
 fun CountClicks() {
     val prefs = currentState<Preferences>()
-    val count = prefs[countClicksKey]
-
-    val parameters = actionParametersOf(uiNameKey to LocalUiKey.current)
+    val count = prefs[countClicksKey] ?: 0
     Row(modifier = GlanceModifier.fillMaxWidth()) {
         Button(
             text = "Count clicks",
-            onClick = actionRunCallback<ClickAction>(parameters)
+            onClick = actionRunCallback<ClickAction>()
         )
         Text(text = "$count clicks")
     }
@@ -140,36 +161,38 @@
 
 class ClickAction : ActionCallback {
     override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
-        val uiKey = requireNotNull(parameters[uiNameKey]) {
-            "Add UI name to parameters, to access the view state."
-        }
-        GlanceState.updateValue(context, MyStateDefinition, uiKey) { prefs ->
+        updateAppWidgetState(context, PreferencesGlanceStateDefinition, glanceId) { prefs ->
             prefs.toMutablePreferences().apply {
-                this[countClicksKey] = prefs[countClicksKey]!! + 1
-            }.toPreferences()
+                this[countClicksKey] = (prefs[countClicksKey] ?: 0) + 1
+            }
         }
         CompoundButtonAppWidget().update(context, glanceId)
     }
 }
 
-object MyStateDefinition : GlanceStateDefinition<Preferences> {
-    override fun getLocation(context: Context, fileKey: String): File =
-        context.preferencesDataStoreFile(fileKey)
+private val countClicksKey = intPreferencesKey("CountClicks")
 
-    @Suppress("UNCHECKED_CAST")
-    override suspend fun <T> getDataStore(context: Context, fileKey: String): DataStore<T> =
-        PreferenceDataStoreFactory.create { context.preferencesDataStoreFile(fileKey) }
-            .apply {
-                edit { prefs ->
-                    if (prefs[countClicksKey] == null) {
-                        prefs[countClicksKey] = 0
-                    }
-                }
-            } as DataStore<T>
+class ToggleAction : ActionCallback {
+    override suspend fun onRun(
+        context: Context,
+        glanceId: GlanceId,
+        parameters: ActionParameters,
+    ) {
+        val target = requireNotNull(parameters[eventTargetKey]) {
+            "Add event target to parameters in order to update the view state."
+        }.let { CompoundButtonAppWidget.Buttons.valueOf(it) }
+        val checked = requireNotNull(parameters[ToggleableStateKey]) {
+            "This action should only be called in response to toggleable events"
+        }
+
+        updateAppWidgetState(context, PreferencesGlanceStateDefinition, glanceId) { prefs ->
+            prefs.toMutablePreferences().apply { set(target.prefsKey, checked) }
+        }
+        CompoundButtonAppWidget().update(context, glanceId)
+    }
 }
 
-private val countClicksKey = intPreferencesKey("CountClicks")
-private val uiNameKey = ActionParameters.Key<String>("UiKey")
+private val eventTargetKey = ActionParameters.Key<String>("EventTarget")
 
 class CompoundButtonAppWidgetReceiver : GlanceAppWidgetReceiver() {
     override val glanceAppWidget = CompoundButtonAppWidget()
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 d22c759..16c26a3 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
@@ -23,29 +23,35 @@
 import android.widget.Toast
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
-import androidx.compose.material.Text as ComposeText
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.booleanPreferencesKey
 import androidx.glance.Button
 import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
 import androidx.glance.LocalContext
 import androidx.glance.LocalSize
-import androidx.glance.appwidget.action.ActionCallback
 import androidx.glance.action.ActionParameters
-import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.action.actionParametersOf
 import androidx.glance.action.clickable
+import androidx.glance.appwidget.CheckBox
 import androidx.glance.appwidget.GlanceAppWidget
 import androidx.glance.appwidget.GlanceAppWidgetReceiver
 import androidx.glance.appwidget.SizeMode
+import androidx.glance.appwidget.action.ActionCallback
+import androidx.glance.appwidget.action.ToggleableStateKey
 import androidx.glance.appwidget.action.actionLaunchActivity
+import androidx.glance.appwidget.action.actionRunCallback
+import androidx.glance.appwidget.demos.ScrollableAppWidget.Companion.checkboxKey
 import androidx.glance.appwidget.lazy.LazyColumn
 import androidx.glance.appwidget.lazy.itemsIndexed
+import androidx.glance.appwidget.state.updateAppWidgetState
 import androidx.glance.background
+import androidx.glance.currentState
 import androidx.glance.layout.Alignment
 import androidx.glance.layout.Column
 import androidx.glance.layout.Row
@@ -53,11 +59,14 @@
 import androidx.glance.layout.fillMaxSize
 import androidx.glance.layout.fillMaxWidth
 import androidx.glance.layout.padding
+import androidx.glance.state.GlanceStateDefinition
+import androidx.glance.state.PreferencesGlanceStateDefinition
 import androidx.glance.text.FontWeight
 import androidx.glance.text.Text
 import androidx.glance.text.TextAlign
 import androidx.glance.text.TextDecoration
 import androidx.glance.text.TextStyle
+import androidx.compose.material.Text as ComposeText
 
 /**
  * Sample AppWidget that showcase scrollable layouts using the LazyColumn
@@ -68,8 +77,12 @@
         private val singleColumn = DpSize(100.dp, 48.dp)
         private val doubleColumn = DpSize(200.dp, 48.dp)
         private val tripleColumn = DpSize(300.dp, 48.dp)
+
+        val checkboxKey = booleanPreferencesKey("checkbox")
     }
 
+    override var stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition
+
     override val sizeMode: SizeMode = SizeMode.Responsive(
         setOf(singleColumn, doubleColumn, tripleColumn)
     )
@@ -105,6 +118,7 @@
 
 @Composable
 private fun ScrollColumn(modifier: GlanceModifier) {
+    val prefs = currentState<Preferences>()
     LazyColumn(modifier) {
         item {
             SectionHeading(
@@ -161,6 +175,19 @@
                     )
             )
         }
+        item {
+            SectionHeading(
+                title = "Compound buttons",
+                description = "Check buttons below"
+            )
+        }
+        item {
+            CheckBox(
+                checked = prefs[checkboxKey] ?: false,
+                onCheckedChange = actionRunCallback<ListToggleAction>(),
+                text = "Checkbox"
+            )
+        }
     }
 }
 
@@ -208,6 +235,20 @@
     }
 }
 
+class ListToggleAction : ActionCallback {
+    override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
+        ScrollableAppWidget().run {
+            updateAppWidgetState<Preferences>(context, glanceId) { prefs ->
+                prefs.toMutablePreferences().apply {
+                    val checked = parameters[ToggleableStateKey] ?: false
+                    set(checkboxKey, checked)
+                }
+            }
+            update(context, glanceId)
+        }
+    }
+}
+
 private val ClickedItemKey = ActionParameters.Key<Int>("ClickedItemKey")
 
 class ScrollableAppWidgetReceiver : GlanceAppWidgetReceiver() {
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
index 0a187b8..981a4cb 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
@@ -85,12 +85,15 @@
     private val mInnerRules = RuleChain.outerRule(mActivityRule).around(mOrientationRule)
 
     private var mHostStarted = false
-    lateinit var mHostView: TestAppWidgetHostView
+    private var mMaybeHostView: TestAppWidgetHostView? = null
     private var mAppWidgetId = 0
     private val mScenario: ActivityScenario<AppWidgetHostTestActivity>
         get() = mActivityRule.scenario
     private val mContext = ApplicationProvider.getApplicationContext<Context>()
 
+    val mHostView: TestAppWidgetHostView
+        get() = checkNotNull(mMaybeHostView) { "No app widget installed on the host" }
+
     override fun apply(base: Statement, description: Description) = object : Statement() {
 
         override fun evaluate() {
@@ -111,12 +114,21 @@
         mHostStarted = true
 
         mActivityRule.scenario.onActivity { activity ->
-            mHostView = activity.bindAppWidget(mPortraitSize, mLandscapeSize)
+            mMaybeHostView = activity.bindAppWidget(mPortraitSize, mLandscapeSize)
         }
 
+        val hostView = checkNotNull(mMaybeHostView) { "Host view wasn't successfully started" }
+
         runAndWaitForChildren {
-            mAppWidgetId = mHostView.appWidgetId
-            mHostView.waitForRemoteViews()
+            mAppWidgetId = hostView.appWidgetId
+            hostView.waitForRemoteViews()
+        }
+    }
+
+    fun removeAppWidget() {
+        mActivityRule.scenario.onActivity { activity ->
+            val hostView = checkNotNull(mMaybeHostView) { "No app widget to remove" }
+            activity.deleteAppWidget(hostView)
         }
     }
 
@@ -182,18 +194,21 @@
         mPortraitSize = portrait
         if (!mHostStarted) return
 
-        mScenario.onActivity {
-            mHostView.setSizes(portrait, landscape)
-        }
+        val hostView = mMaybeHostView
+        if (hostView != null) {
+            mScenario.onActivity {
+                hostView.setSizes(portrait, landscape)
+            }
 
-        if (updateRemoteViews) {
-            runAndWaitForChildren {
-                mHostView.resetRemoteViewsLatch()
-                AppWidgetManager.getInstance(mContext).updateAppWidgetOptions(
-                    mAppWidgetId,
-                    optionsBundleOf(listOf(portrait, landscape))
-                )
-                mHostView.waitForRemoteViews()
+            if (updateRemoteViews) {
+                runAndWaitForChildren {
+                    hostView.resetRemoteViewsLatch()
+                    AppWidgetManager.getInstance(mContext).updateAppWidgetOptions(
+                        mAppWidgetId,
+                        optionsBundleOf(listOf(portrait, landscape))
+                    )
+                    hostView.waitForRemoteViews()
+                }
             }
         }
     }
@@ -203,12 +218,13 @@
         run: () -> Unit = {},
         test: () -> Boolean
     ) {
+        val hostView = mHostView
         val latch = CountDownLatch(1)
         val onDrawListener = ViewTreeObserver.OnDrawListener {
-            if (mHostView.childCount > 0 && test()) latch.countDown()
+            if (hostView.childCount > 0 && test()) latch.countDown()
         }
         mActivityRule.scenario.onActivity {
-            mHostView.viewTreeObserver.addOnDrawListener(onDrawListener)
+            hostView.viewTreeObserver.addOnDrawListener(onDrawListener)
         }
 
         run()
@@ -224,7 +240,7 @@
         } finally {
             latch.countDown() // make sure it's released in all conditions
             mActivityRule.scenario.onActivity {
-                mHostView.viewTreeObserver.removeOnDrawListener(onDrawListener)
+                hostView.viewTreeObserver.removeOnDrawListener(onDrawListener)
             }
         }
     }
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
index a5b1fab..97f6c7d 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
@@ -101,6 +101,14 @@
         return hostView
     }
 
+    fun deleteAppWidget(hostView: TestAppWidgetHostView) {
+        val appWidgetId = hostView.appWidgetId
+        mHost?.deleteAppWidgetId(appWidgetId)
+        mHostViews.remove(hostView)
+        val contentFrame = findViewById<FrameLayout>(R.id.content)
+        contentFrame.removeView(hostView)
+    }
+
     override fun onConfigurationChanged(newConfig: Configuration) {
         super.onConfigurationChanged(newConfig)
         updateAllSizes(newConfig.orientation)
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
index a28888a..29ea48be 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
@@ -47,13 +47,13 @@
 
     private val checkedCheckBox: @Composable () -> Unit = {
         Box {
-            CheckBox(checked = true, text = "Hello world")
+            CheckBox(checked = true, onCheckedChange = null, text = "Hello world")
         }
     }
 
     private val uncheckedCheckBox: @Composable () -> Unit = {
         Box {
-            CheckBox(checked = false, text = "Hola mundo")
+            CheckBox(checked = false, onCheckedChange = null, text = "Hola mundo")
         }
     }
 
@@ -127,7 +127,10 @@
     fun check_box_modifiers() {
         TestGlanceAppWidget.uiDefinition = {
             Box {
-                CheckBox(checked = true, modifier = GlanceModifier.padding(5.dp, 6.dp, 7.dp, 8.dp))
+                CheckBox(
+                    checked = true,
+                    onCheckedChange = null,
+                    modifier = GlanceModifier.padding(5.dp, 6.dp, 7.dp, 8.dp))
             }
         }
 
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
index 5fe5b3a..d8dde64 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
@@ -224,12 +224,14 @@
                 Row(modifier = GlanceModifier.defaultWeight().fillMaxWidth()) {
                     CheckBox(
                         checked = false,
+                        onCheckedChange = null,
                         text = "Start",
                         modifier = GlanceModifier.defaultWeight().fillMaxHeight(),
                         style = TextStyle(textAlign = TextAlign.Start)
                     )
                     CheckBox(
                         checked = true,
+                        onCheckedChange = null,
                         text = "End",
                         modifier = GlanceModifier.defaultWeight().fillMaxHeight(),
                         style = TextStyle(textAlign = TextAlign.End)
@@ -238,12 +240,14 @@
                 Row(modifier = GlanceModifier.defaultWeight().fillMaxWidth()) {
                     Switch(
                         checked = false,
+                        onCheckedChange = null,
                         text = "Start",
                         modifier = GlanceModifier.defaultWeight().fillMaxHeight(),
                         style = TextStyle(textAlign = TextAlign.Start)
                     )
                     Switch(
                         checked = true,
+                        onCheckedChange = null,
                         text = "End",
                         modifier = GlanceModifier.defaultWeight().fillMaxHeight(),
                         style = TextStyle(textAlign = TextAlign.End)
@@ -582,6 +586,7 @@
     Column(modifier = GlanceModifier.background(day = Color.White, night = Color.Black)) {
         CheckBox(
             checked = true,
+            onCheckedChange = null,
             text = "Hello Checked Checkbox (text: day=black, night=white| box: day=magenta, " +
                 "night=yellow)",
             style = TextStyle(
@@ -596,6 +601,7 @@
 
         CheckBox(
             checked = false,
+            onCheckedChange = null,
             text = "Hello Unchecked Checkbox (text: day=dark gray, night=light gray, green box)",
             style = TextStyle(
                 color = ColorProvider(day = Color.DarkGray, night = Color.LightGray),
@@ -613,6 +619,7 @@
     Column(modifier = GlanceModifier.background(day = Color.White, night = Color.Black)) {
         Switch(
             checked = true,
+            onCheckedChange = null,
             text = "Hello Checked Switch (day: Blue/Green, night: Red/Yellow)",
             style = TextStyle(
                 color = ColorProvider(day = Color.Black, night = Color.White),
@@ -627,6 +634,7 @@
 
         Switch(
             checked = false,
+            onCheckedChange = null,
             text = "Hello Unchecked Switch",
             style = TextStyle(
                 color = ColorProvider(day = Color.Black, night = Color.White),
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
index bbf99f3..65e7965 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
@@ -34,15 +34,21 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.intPreferencesKey
 import androidx.glance.Button
+import androidx.glance.GlanceId
 import androidx.glance.GlanceModifier
 import androidx.glance.Image
 import androidx.glance.ImageProvider
 import androidx.glance.LocalContext
 import androidx.glance.LocalSize
 import androidx.glance.action.actionLaunchActivity
+import androidx.glance.appwidget.state.getAppWidgetState
+import androidx.glance.appwidget.state.updateAppWidgetState
 import androidx.glance.appwidget.test.R
 import androidx.glance.background
+import androidx.glance.currentState
 import androidx.glance.layout.Box
 import androidx.glance.layout.Column
 import androidx.glance.layout.ContentScale
@@ -53,6 +59,7 @@
 import androidx.glance.layout.height
 import androidx.glance.layout.width
 import androidx.glance.layout.wrapContentHeight
+import androidx.glance.state.PreferencesGlanceStateDefinition
 import androidx.glance.text.FontStyle
 import androidx.glance.text.FontWeight
 import androidx.glance.text.Text
@@ -60,10 +67,17 @@
 import androidx.glance.text.TextStyle
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.runBlocking
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicReference
 import kotlin.test.assertIs
 import kotlin.test.assertNotNull
 
@@ -73,6 +87,8 @@
     @get:Rule
     val mHostRule = AppWidgetHostRule()
 
+    val context = InstrumentationRegistry.getInstrumentation().targetContext!!
+
     @Before
     fun setUp() {
         // Reset the size mode to the default
@@ -432,7 +448,7 @@
 
     @Test
     fun bitmapBackground() {
-        TestGlanceAppWidget.uiDefinition = compose@{
+        TestGlanceAppWidget.uiDefinition = {
             val context = LocalContext.current
             val bitmap =
                 (context.resources.getDrawable(R.drawable.compose, null) as BitmapDrawable).bitmap
@@ -455,8 +471,156 @@
         }
     }
 
+    @Test
+    fun removeAppWidget() {
+        TestGlanceAppWidget.stateDefinition = PreferencesGlanceStateDefinition
+        TestGlanceAppWidget.uiDefinition = {
+            Text("something")
+        }
+
+        mHostRule.startHost()
+
+        val appWidgetManager = GlanceAppWidgetManager(context)
+        val glanceId = runBlocking {
+            appWidgetManager.getGlanceIds(TestGlanceAppWidget::class.java).single()
+        }
+
+        runBlocking {
+            TestGlanceAppWidget.updateAppWidgetState<Preferences>(context, glanceId) { prefs ->
+                prefs.toMutablePreferences().apply {
+                    this[testKey] = 3
+                }
+            }
+        }
+
+        val fileKey = createUniqueRemoteUiName((glanceId as AppWidgetId).appWidgetId)
+        val preferencesFile = PreferencesGlanceStateDefinition.getLocation(context, fileKey)
+
+        assertThat(preferencesFile.exists())
+
+        val deleteLatch = CountDownLatch(1)
+        TestGlanceAppWidget.setOnDeleteBlock {
+            deleteLatch.countDown()
+        }
+
+        mHostRule.removeAppWidget()
+
+        deleteLatch.await(5, TimeUnit.SECONDS)
+        val interval = 200L
+        for (timeout in 0..2000L step interval) {
+            if (!preferencesFile.exists()) return
+            Thread.sleep(interval)
+        }
+        assertWithMessage("View state file exists").that(preferencesFile.exists())
+            .isFalse()
+    }
+
+    @Test
+    fun updateAll() {
+        TestGlanceAppWidget.uiDefinition = {
+            Text("before")
+        }
+
+        mHostRule.startHost()
+
+        val didRun = AtomicBoolean(false)
+        TestGlanceAppWidget.uiDefinition = {
+            didRun.set(true)
+            Text("after")
+        }
+
+        runBlocking {
+            TestGlanceAppWidget.updateAll(context)
+        }
+        assertThat(didRun.get()).isTrue()
+    }
+
+    @Test
+    fun updateIf() {
+        TestGlanceAppWidget.stateDefinition = PreferencesGlanceStateDefinition
+
+        TestGlanceAppWidget.uiDefinition = {
+            Text("before")
+        }
+
+        mHostRule.startHost()
+
+        val appWidgetManager = GlanceAppWidgetManager(context)
+        runBlocking {
+            appWidgetManager.getGlanceIds(TestGlanceAppWidget::class.java)
+                .forEach { glanceId ->
+                    updateAppWidgetState(
+                        context,
+                        PreferencesGlanceStateDefinition,
+                        glanceId
+                    ) { prefs ->
+                        prefs.toMutablePreferences().apply {
+                            this[testKey] = 2
+                        }
+                    }
+                }
+        }
+
+        // Make sure the app widget is updated if the test is true
+        val didRun = AtomicBoolean(false)
+        TestGlanceAppWidget.uiDefinition = {
+            didRun.set(true)
+            Text("after")
+        }
+        runBlocking {
+            TestGlanceAppWidget.updateIf<Preferences>(context) { prefs ->
+                prefs[testKey] == 2
+            }
+        }
+
+        assertThat(didRun.get()).isTrue()
+
+        // Make sure it is not if the test is false
+        didRun.set(false)
+        runBlocking {
+            TestGlanceAppWidget.updateIf<Preferences>(context) { prefs ->
+                prefs[testKey] == 3
+            }
+        }
+
+        assertThat(didRun.get()).isFalse()
+    }
+
+    @Test
+    fun viewState() {
+        TestGlanceAppWidget.stateDefinition = PreferencesGlanceStateDefinition
+
+        TestGlanceAppWidget.uiDefinition = {
+            val value = currentState<Preferences>()[testKey] ?: -1
+            Text("Value = $value")
+        }
+
+        mHostRule.startHost()
+
+        val appWidgetId = AtomicReference<GlanceId>()
+        mHostRule.onHostView { view ->
+            appWidgetId.set(AppWidgetId(view.appWidgetId))
+        }
+
+        runBlocking {
+            TestGlanceAppWidget.updateAppWidgetState<Preferences>(
+                context,
+                appWidgetId.get()
+            ) { prefs ->
+                prefs.toMutablePreferences().apply {
+                    this[testKey] = 2
+                }
+            }
+
+            val prefs =
+                TestGlanceAppWidget.getAppWidgetState<Preferences>(context, appWidgetId.get())
+            assertThat(prefs[testKey]).isEqualTo(2)
+        }
+    }
+
     // Check there is a single span of the given type and that it passes the [check].
-    private inline fun <reified T> SpannedString.checkHasSingleTypedSpan(check: (T) -> Unit) {
+    private inline
+    fun <reified T> SpannedString.checkHasSingleTypedSpan(check: (T) -> Unit) {
         val spans = getSpans(0, length, T::class.java)
         assertThat(spans).hasLength(1)
         check(spans[0])
@@ -464,8 +628,10 @@
 
     private fun assertViewSize(view: View, expectedSize: DpSize) {
         val density = view.context.resources.displayMetrics.density
-        assertThat(view.width / density).isWithin(1.1f / density).of(expectedSize.width.value)
-        assertThat(view.height / density).isWithin(1.1f / density).of(expectedSize.height.value)
+        assertThat(view.width / density).isWithin(1.1f / density)
+            .of(expectedSize.width.value)
+        assertThat(view.height / density).isWithin(1.1f / density)
+            .of(expectedSize.height.value)
     }
 
     private fun assertViewDimension(view: View, sizePx: Int, expectedSize: Dp) {
@@ -473,3 +639,5 @@
         assertThat(sizePx / density).isWithin(1.1f / density).of(expectedSize.value)
     }
 }
+
+private val testKey = intPreferencesKey("testKey")
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
index c4ae56e..23acd1a 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
@@ -362,8 +362,8 @@
 
     private inline fun <reified T : View> ListView.getUnboxedListItem(position: Int): T {
         val remoteViewFrame = assertIs<FrameLayout>(getChildAt(position))
-        // Android R- have a RemoteViewsAdapter$RemoteViewsFrameLayout first, Android S+ do not.
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+        // Android S- have a RemoteViewsAdapter$RemoteViewsFrameLayout first, Android T+ do not.
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S) {
             return remoteViewFrame.getChildAt(0).getTargetView()
         }
         val frame = assertIs<FrameLayout>(remoteViewFrame.getChildAt(0))
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
index 5f17899..12ac3f0 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
@@ -17,6 +17,8 @@
 package androidx.glance.appwidget
 
 import androidx.compose.runtime.Composable
+import androidx.glance.GlanceId
+import androidx.glance.state.GlanceStateDefinition
 
 class TestGlanceAppWidgetReceiver : GlanceAppWidgetReceiver() {
     override val glanceAppWidget: GlanceAppWidget = TestGlanceAppWidget
@@ -24,6 +26,8 @@
 
 object TestGlanceAppWidget : GlanceAppWidget(errorUiLayout = 0) {
 
+    override var stateDefinition: GlanceStateDefinition<*>? = null
+
     override var sizeMode: SizeMode = SizeMode.Single
 
     @Composable
@@ -31,5 +35,19 @@
         uiDefinition()
     }
 
+    private var onDeleteBlock: ((GlanceId) -> Unit)? = null
+
+    fun setOnDeleteBlock(block: (GlanceId) -> Unit) {
+        onDeleteBlock = block
+    }
+
+    fun resetOnDeleteBlock() {
+        onDeleteBlock = null
+    }
+
+    override suspend fun onDelete(glanceId: GlanceId) {
+        onDeleteBlock?.apply { this(glanceId) }
+    }
+
     var uiDefinition: @Composable () -> Unit = { }
 }
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/glance/glance-appwidget/src/androidAndroidTest/res/values-v29/themes.xml
similarity index 79%
copy from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
copy to glance/glance-appwidget/src/androidAndroidTest/res/values-v29/themes.xml
index 987c157..1a85e18 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/glance/glance-appwidget/src/androidAndroidTest/res/values-v29/themes.xml
@@ -14,6 +14,6 @@
   limitations under the License.
   -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+<resources>
+    <style name="Glance.AppWidget.Theme" parent=""/>
+</resources>
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml b/glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml
index efd9192..2f50199 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml
+++ b/glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml
@@ -18,4 +18,5 @@
     <style name="Theme.TestDimensionAttr" parent="">
         <item name="dimensionAttr">@dimen/testDimension</item>
     </style>
+    <style name="Glance.AppWidget.Theme" parent=""/>
 </resources>
diff --git a/glance/glance-appwidget/src/androidMain/AndroidManifest.xml b/glance/glance-appwidget/src/androidMain/AndroidManifest.xml
index 579156f..9ca4dbf 100644
--- a/glance/glance-appwidget/src/androidMain/AndroidManifest.xml
+++ b/glance/glance-appwidget/src/androidMain/AndroidManifest.xml
@@ -18,11 +18,11 @@
     package="androidx.glance.appwidget" >
     <application>
         <activity
-            android:name=".ListAdapterLaunchActivityTrampolineActivity"
+            android:name=".ListAdapterTrampolineActivity"
             android:exported="false"
             android:enabled="true" />
         <activity
-            android:name=".ListAdapterCallbackTrampolineActivity"
+            android:name=".ListAdapterInvisibleTrampolineActivity"
             android:exported="false"
             android:taskAffinity="androidx.glance.appwidget.ListAdapterCallbackTrampoline"
             android:theme="@style/Widget.Glance.AppWidget.CallbackTrampoline"
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt
index cbb494c..16861ac 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt
@@ -19,7 +19,6 @@
 import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
-import android.net.Uri
 import android.os.Build
 import android.util.Log
 import android.util.TypedValue.COMPLEX_UNIT_DIP
@@ -32,6 +31,7 @@
 import androidx.annotation.IdRes
 import androidx.annotation.RequiresApi
 import androidx.compose.ui.graphics.toArgb
+import androidx.core.os.bundleOf
 import androidx.core.widget.RemoteViewsCompat.setTextViewHeight
 import androidx.core.widget.RemoteViewsCompat.setTextViewWidth
 import androidx.core.widget.RemoteViewsCompat.setViewBackgroundColor
@@ -45,17 +45,28 @@
 import androidx.glance.VisibilityModifier
 import androidx.glance.action.Action
 import androidx.glance.action.ActionModifier
+import androidx.glance.action.ActionParameters
 import androidx.glance.action.LaunchActivityAction
 import androidx.glance.action.LaunchActivityClassAction
 import androidx.glance.action.LaunchActivityComponentAction
-import androidx.glance.appwidget.ListAdapterLaunchActivityTrampolineActivity.Companion.putActivityIntentExtra
-import androidx.glance.appwidget.action.RunCallbackAction
+import androidx.glance.action.toMutableParameters
+import androidx.glance.appwidget.action.CompoundButtonAction
 import androidx.glance.appwidget.action.LaunchActivityIntentAction
+import androidx.glance.appwidget.action.LaunchBroadcastReceiverAction
+import androidx.glance.appwidget.action.LaunchBroadcastReceiverActionAction
+import androidx.glance.appwidget.action.LaunchBroadcastReceiverClassAction
+import androidx.glance.appwidget.action.LaunchBroadcastReceiverComponentAction
+import androidx.glance.appwidget.action.LaunchBroadcastReceiverIntentAction
+import androidx.glance.appwidget.action.LaunchServiceAction
+import androidx.glance.appwidget.action.LaunchServiceClassAction
+import androidx.glance.appwidget.action.LaunchServiceComponentAction
+import androidx.glance.appwidget.action.LaunchServiceIntentAction
+import androidx.glance.appwidget.action.RunCallbackAction
+import androidx.glance.appwidget.action.ToggleableStateKey
 import androidx.glance.appwidget.unit.DayNightColorProvider
 import androidx.glance.layout.HeightModifier
 import androidx.glance.layout.PaddingModifier
 import androidx.glance.layout.WidthModifier
-import androidx.glance.appwidget.ListAdapterCallbackTrampolineActivity.Companion.putBroadcastIntentExtra
 import androidx.glance.unit.Dimension
 import androidx.glance.unit.FixedColorProvider
 import androidx.glance.unit.ResourceColorProvider
@@ -84,6 +95,9 @@
             }
             is VisibilityModifier -> visibility = modifier.visibility
             is CornerRadiusModifier -> cornerRadius = modifier.radius
+            is AppWidgetBackgroundModifier -> {
+                // This modifier is handled somewhere else.
+            }
             else -> {
                 Log.w(GlanceAppWidgetTag, "Unknown modifier '$modifier', nothing done.")
             }
@@ -118,89 +132,200 @@
     action: Action,
     @IdRes viewId: Int
 ) {
+    try {
+        if (translationContext.isLazyCollectionDescendant) {
+            val fillInIntent = getFillInIntentForAction(action, translationContext, viewId)
+            if (action is CompoundButtonAction && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                ApplyModifiersApi31Impl.setOnCheckedChangeResponse(rv, viewId, fillInIntent)
+            } else {
+                rv.setOnClickFillInIntent(viewId, fillInIntent)
+            }
+        } else {
+            val pendingIntent = getPendingIntentForAction(action, translationContext)
+            if (action is CompoundButtonAction && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                ApplyModifiersApi31Impl.setOnCheckedChangeResponse(rv, viewId, pendingIntent)
+            } else {
+                rv.setOnClickPendingIntent(viewId, pendingIntent)
+            }
+        }
+    } catch (t: Throwable) {
+        Log.e(GlanceAppWidgetTag, "Unrecognized Action: $action", t)
+    }
+}
+
+private fun getPendingIntentForAction(
+    action: Action,
+    translationContext: TranslationContext,
+    editParams: (ActionParameters) -> ActionParameters = { it }
+): PendingIntent {
     when (action) {
         is LaunchActivityAction -> {
-            val activityIntent = when (action) {
-                is LaunchActivityComponentAction -> Intent().setComponent(action.componentName)
-                is LaunchActivityClassAction ->
-                    Intent(translationContext.context, action.activityClass)
-                is LaunchActivityIntentAction -> action.intent
-                else -> error("Action type not defined in app widget package: $action")
-            }
-
-            if (translationContext.isLazyCollectionDescendant) {
-                val fillIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-                    // Fill in the pending intent template with the action intent directly, with a
-                    // unique identifier to ensure unique filterEquals
-                    ApplyModifiersApiApi29Impl.setIntentIdentifier(activityIntent, viewId)
-                } else {
-                    // Send the action intent to an activity trampoline, where it will be invoked,
-                    // unmodified
-                    Intent(
-                        translationContext.context,
-                        ListAdapterLaunchActivityTrampolineActivity::class.java
-                    ).apply {
-                        data = Uri.parse(toUri(0))
-                            .buildUpon()
-                            .scheme("startActivityAction")
-                            .path(viewId.toString())
-                            .build()
-                        putActivityIntentExtra(activityIntent)
-                    }
-                }
-                rv.setOnClickFillInIntent(viewId, fillIntent)
+            return PendingIntent.getActivity(
+                translationContext.context,
+                0,
+                getLaunchActivityIntent(action, translationContext, editParams),
+                PendingIntent.FLAG_MUTABLE
+            )
+        }
+        is LaunchServiceAction -> {
+            val intent = getLaunchServiceIntent(action, translationContext)
+            return if (action.isForegroundService &&
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+            ) {
+                ApplyModifiersApi26Impl.getForegroundServicePendingIntent(
+                    context = translationContext.context,
+                    intent = intent
+                )
             } else {
-                val pendingIntent: PendingIntent =
-                    PendingIntent.getActivity(
-                        translationContext.context,
-                        0,
-                        activityIntent,
-                        PendingIntent.FLAG_MUTABLE
-                    )
-
-                rv.setOnClickPendingIntent(viewId, pendingIntent)
+                PendingIntent.getService(
+                    translationContext.context,
+                    0,
+                    intent,
+                    PendingIntent.FLAG_MUTABLE
+                )
             }
         }
+        is LaunchBroadcastReceiverAction -> {
+            return PendingIntent.getBroadcast(
+                translationContext.context,
+                0,
+                getLaunchBroadcastReceiverIntent(action, translationContext),
+                PendingIntent.FLAG_MUTABLE
+            )
+        }
         is RunCallbackAction -> {
-            if (translationContext.isLazyCollectionDescendant) {
-                val actionIntent = ActionCallbackBroadcastReceiver.createIntent(
-                    translationContext.context,
-                    action.callbackClass,
-                    translationContext.appWidgetId,
-                    action.parameters
-                )
-                rv.setOnClickFillInIntent(
-                    viewId,
-                    Intent(
-                        translationContext.context,
-                        ListAdapterCallbackTrampolineActivity::class.java
-                    ).apply {
-                        data = Uri.parse(toUri(0))
-                            .buildUpon()
-                            .scheme("updateContentAction")
-                            .path(viewId.toString())
-                            .build()
-                        putBroadcastIntentExtra(actionIntent)
-                    }
-                )
-            } else {
-                val pendingIntent =
-                    ActionCallbackBroadcastReceiver.createPendingIntent(
-                        translationContext.context,
-                        action.callbackClass,
-                        translationContext.appWidgetId,
-                        action.parameters
-                    )
-                rv.setOnClickPendingIntent(viewId, pendingIntent)
-            }
+            return ActionCallbackBroadcastReceiver.createPendingIntent(
+                translationContext.context,
+                action.callbackClass,
+                translationContext.appWidgetId,
+                editParams(action.parameters)
+            )
         }
-        else -> {
-            Log.e(
-                GlanceAppWidgetTag,
-                "Unrecognized action type: ${action.javaClass.canonicalName}."
+        is CompoundButtonAction -> {
+            return getPendingIntentForAction(
+                action.innerAction,
+                translationContext,
+                action.getActionParameters()
+            )
+        }
+        else -> error("Cannot create PendingIntent for action type: $action")
+    }
+}
+
+private fun getFillInIntentForAction(
+    action: Action,
+    translationContext: TranslationContext,
+    @IdRes viewId: Int,
+    editParams: (ActionParameters) -> ActionParameters = { it }
+): Intent = when (action) {
+    is LaunchActivityAction -> {
+        val launchActivityIntent = getLaunchActivityIntent(
+            action = action,
+            translationContext = translationContext,
+            editParams = editParams
+        )
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+            // Fill in the pending intent template with the action intent directly, with a
+            // unique identifier to ensure unique filterEquals
+            ApplyModifiersApi29Impl.setIntentIdentifier(launchActivityIntent, viewId)
+        } else {
+            launchActivityIntent.applyTrampolineIntent(
+                context = translationContext.context,
+                viewId = viewId,
+                type = ListAdapterTrampolineType.ACTIVITY
             )
         }
     }
+    is LaunchServiceAction -> getLaunchServiceIntent(
+        action = action,
+        translationContext = translationContext
+    ).applyTrampolineIntent(
+        context = translationContext.context,
+        viewId = viewId,
+        type = if (action.isForegroundService) {
+            ListAdapterTrampolineType.FOREGROUND_SERVICE
+        } else {
+            ListAdapterTrampolineType.SERVICE
+        }
+    )
+    is LaunchBroadcastReceiverAction -> getLaunchBroadcastReceiverIntent(
+        action = action,
+        translationContext = translationContext
+    ).applyTrampolineIntent(
+        context = translationContext.context,
+        viewId = viewId,
+        type = ListAdapterTrampolineType.BROADCAST
+    )
+    is RunCallbackAction -> ActionCallbackBroadcastReceiver.createIntent(
+        context = translationContext.context,
+        callbackClass = action.callbackClass,
+        appWidgetId = translationContext.appWidgetId,
+        parameters = editParams(action.parameters)
+    ).applyTrampolineIntent(
+        context = translationContext.context,
+        viewId = viewId,
+        type = ListAdapterTrampolineType.BROADCAST
+    )
+    is CompoundButtonAction -> getFillInIntentForAction(
+        action.innerAction,
+        translationContext,
+        viewId,
+        action.getActionParameters()
+    )
+    else -> error("Cannot create fill-in Intent for action type: $action")
+}
+
+private fun CompoundButtonAction.getActionParameters() = { params: ActionParameters ->
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+        params.toMutableParameters().apply {
+            set(ToggleableStateKey, !checked)
+        }
+    } else {
+        params
+    }
+}
+
+private fun getLaunchBroadcastReceiverIntent(
+    action: LaunchBroadcastReceiverAction,
+    translationContext: TranslationContext
+) = when (action) {
+    is LaunchBroadcastReceiverComponentAction -> Intent().setComponent(action.componentName)
+    is LaunchBroadcastReceiverClassAction ->
+        Intent(translationContext.context, action.receiverClass)
+    is LaunchBroadcastReceiverIntentAction -> action.intent
+    is LaunchBroadcastReceiverActionAction ->
+        Intent(action.action).setComponent(action.componentName)
+}
+
+private fun getLaunchServiceIntent(
+    action: LaunchServiceAction,
+    translationContext: TranslationContext
+): Intent = when (action) {
+    is LaunchServiceComponentAction -> Intent().setComponent(action.componentName)
+    is LaunchServiceClassAction ->
+        Intent(translationContext.context, action.serviceClass)
+    is LaunchServiceIntentAction -> action.intent
+}
+
+private fun getLaunchActivityIntent(
+    action: LaunchActivityAction,
+    translationContext: TranslationContext,
+    editParams: (ActionParameters) -> ActionParameters = { it }
+): Intent {
+    val activityIntent = when (action) {
+        is LaunchActivityComponentAction -> Intent().setComponent(action.componentName)
+        is LaunchActivityClassAction ->
+            Intent(translationContext.context, action.activityClass)
+        is LaunchActivityIntentAction -> action.intent
+        else -> error("Action type not defined in app widget package: $action")
+    }
+
+    val parametersPairs = editParams(action.parameters).asMap().map { (key, value) ->
+        key.name to value
+    }.toTypedArray()
+
+    activityIntent.putExtras(bundleOf(*parametersPairs))
+    return activityIntent
 }
 
 private fun applySizeModifiers(
@@ -409,12 +534,35 @@
             else -> error("Rounded corners should not be ${radius.javaClass.canonicalName}")
         }
     }
+
+    @DoNotInline
+    fun setOnCheckedChangeResponse(rv: RemoteViews, viewId: Int, intent: PendingIntent) {
+        rv.setOnCheckedChangeResponse(viewId, RemoteViews.RemoteResponse.fromPendingIntent(intent))
+    }
+
+    @DoNotInline
+    fun setOnCheckedChangeResponse(rv: RemoteViews, viewId: Int, intent: Intent) {
+        rv.setOnCheckedChangeResponse(viewId, RemoteViews.RemoteResponse.fromFillInIntent(intent))
+    }
 }
 
 @RequiresApi(Build.VERSION_CODES.Q)
-private object ApplyModifiersApiApi29Impl {
+private object ApplyModifiersApi29Impl {
     @DoNotInline
     fun setIntentIdentifier(intent: Intent, viewId: Int): Intent = intent.apply {
         identifier = viewId.toString()
     }
 }
+
+@RequiresApi(Build.VERSION_CODES.O)
+private object ApplyModifiersApi26Impl {
+    @DoNotInline
+    fun getForegroundServicePendingIntent(context: Context, intent: Intent): PendingIntent {
+        return PendingIntent.getForegroundService(
+            context,
+            0,
+            intent,
+            PendingIntent.FLAG_MUTABLE
+        )
+    }
+}
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt
index bcffc17..c00b526 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt
@@ -22,6 +22,9 @@
 import androidx.glance.Emittable
 import androidx.glance.GlanceModifier
 import androidx.glance.GlanceNode
+import androidx.glance.action.Action
+import androidx.glance.action.ActionModifier
+import androidx.glance.appwidget.action.CompoundButtonAction
 import androidx.glance.appwidget.unit.CheckableColorProvider
 import androidx.glance.appwidget.unit.CheckedUncheckedColorProvider.Companion.createCheckableColorProvider
 import androidx.glance.appwidget.unit.ResourceCheckableColorProvider
@@ -100,6 +103,10 @@
  * Adds a check box view to the glance view.
  *
  * @param checked whether the check box is checked
+ * @param onCheckedChange the action to be run when the checkbox is clicked. The current value of
+ * checked is provided to this action in its ActionParameters, and can be retrieved using the
+ * [ToggleableStateKey]. If this action launches an activity, the current value of checked will be
+ * passed as an intent extra with the name [RemoteViews.EXTRA_CHECKED].
  * @param modifier the modifier to apply to the check box
  * @param text the text to display to the end of the check box
  * @param style the style to apply to [text]
@@ -108,17 +115,23 @@
 @Composable
 public fun CheckBox(
     checked: Boolean,
+    onCheckedChange: Action?,
     modifier: GlanceModifier = GlanceModifier,
     text: String = "",
     style: TextStyle? = null,
     colors: CheckBoxColors = CheckBoxDefaults.colors
 ) {
+    val finalModifier = if (onCheckedChange != null) {
+        modifier.then(ActionModifier(CompoundButtonAction(onCheckedChange, checked)))
+    } else {
+        modifier
+    }
     GlanceNode(
         factory = ::EmittableCheckBox,
         update = {
             this.set(checked) { this.checked = it }
             this.set(text) { this.text = it }
-            this.set(modifier) { this.modifier = it }
+            this.set(finalModifier) { this.modifier = it }
             this.set(style) { this.style = it }
             this.set(colors) { this.colors = it }
         }
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt
index 863af1c..d812e74 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt
@@ -19,7 +19,6 @@
 import android.os.Bundle
 import androidx.compose.runtime.ProvidableCompositionLocal
 import androidx.compose.runtime.staticCompositionLocalOf
-import androidx.glance.state.GlanceStateDefinition
 
 /**
  * Option Bundle accessible when generating an App Widget.
@@ -28,10 +27,3 @@
  */
 public val LocalAppWidgetOptions: ProvidableCompositionLocal<Bundle> =
     staticCompositionLocalOf { error("No default app widget options") }
-
-/**
- * Uniquely identifying key for this remote UI, for use with [GlanceStateDefinition].
- */
-// TODO: Look into refactoring the state to not need this key constant
-public val LocalUiKey =
-    staticCompositionLocalOf<String> { error("No default UI key") }
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt
index d49d35f..05336fd 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt
@@ -19,7 +19,6 @@
 import android.appwidget.AppWidgetManager
 import android.appwidget.AppWidgetProviderInfo
 import android.content.Context
-import android.content.Intent
 import android.os.Build
 import android.os.Bundle
 import android.util.DisplayMetrics
@@ -43,6 +42,7 @@
 import androidx.glance.LocalGlanceId
 import androidx.glance.LocalSize
 import androidx.glance.LocalState
+import androidx.glance.appwidget.state.getAppWidgetState
 import kotlinx.coroutines.CancellationException
 import androidx.glance.state.GlanceState
 import androidx.glance.state.GlanceStateDefinition
@@ -85,6 +85,13 @@
     public open val stateDefinition: GlanceStateDefinition<*>? = null
 
     /**
+     * Method called by the framework when an App Widget has been removed from its host.
+     *
+     * When the method returns, the state associated with the [glanceId] will be deleted.
+     */
+    public open suspend fun onDelete(glanceId: GlanceId) { }
+
+    /**
      * Triggers the composition of [Content] and sends the result to the [AppWidgetManager].
      */
     public suspend fun update(context: Context, glanceId: GlanceId) {
@@ -95,6 +102,26 @@
     }
 
     /**
+     * Calls [onDelete], then clear local data associated with the [appWidgetId].
+     *
+     * This is meant to be called when the App Widget instance has been deleted from the host.
+     */
+    internal suspend fun deleted(context: Context, appWidgetId: Int) {
+        val glanceId = AppWidgetId(appWidgetId)
+        try {
+            onDelete(glanceId)
+        } catch (cancelled: CancellationException) {
+            // Nothing to do here
+        } catch (t: Throwable) {
+            Log.e(GlanceAppWidgetTag, "Error in user-provided deletion callback", t)
+        } finally {
+            stateDefinition?.let {
+                GlanceState.deleteStore(context, it, createUniqueRemoteUiName(appWidgetId))
+            }
+        }
+    }
+
+    /**
      * Internal version of [update], to be used by the broadcast receiver directly.
      */
     internal suspend fun update(
@@ -348,13 +375,11 @@
         val recomposer = Recomposer(coroutineContext)
         val composition = Composition(applier, recomposer)
         val glanceId = AppWidgetId(appWidgetId)
-        val uiKey = createUniqueRemoteUiName(appWidgetId)
         composition.setContent {
             CompositionLocalProvider(
                 LocalContext provides context,
                 LocalGlanceId provides glanceId,
                 LocalAppWidgetOptions provides options,
-                LocalUiKey provides uiKey,
                 LocalState provides state,
                 LocalSize provides size,
             ) { Content() }
@@ -507,14 +532,24 @@
     Log.e(GlanceAppWidgetTag, "Error in Glance App Widget", throwable)
 }
 
-private fun Intent.extractAppWidgetIds() =
-    getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
-        ?: intArrayOf(
-            getIntExtra(
-                AppWidgetManager.EXTRA_APPWIDGET_ID,
-                AppWidgetManager.INVALID_APPWIDGET_ID
-            ).also {
-                check(it != AppWidgetManager.INVALID_APPWIDGET_ID) {
-                    "Cannot determine the app widget id"
-                }
-            })
+/** Update all App Widgets managed by the [GlanceAppWidget] class. */
+public suspend fun GlanceAppWidget.updateAll(@Suppress("ContextFirst") context: Context) {
+    val manager = GlanceAppWidgetManager(context)
+    manager.getGlanceIds(javaClass).forEach { update(context, it) }
+}
+
+/**
+ * Update all App Widgets managed by the [GlanceAppWidget] class, if they fulfill some condition.
+ */
+public suspend inline fun <reified State> GlanceAppWidget.updateIf(
+    @Suppress("ContextFirst") context: Context,
+    predicate: (State) -> Boolean
+) {
+    val stateDef = stateDefinition
+    requireNotNull(stateDef) { "GlanceAppWidget.updateIf cannot be used if no state is defined." }
+    val manager = GlanceAppWidgetManager(context)
+    manager.getGlanceIds(javaClass).forEach { glanceId ->
+        val state = getAppWidgetState(context, stateDef, glanceId) as State
+        if (predicate(state)) update(context, glanceId)
+    }
+}
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
index 6545359..a276ec9 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
@@ -43,6 +43,10 @@
  *
  * Note: If you override any of the [AppWidgetProvider] methods, ensure you call their super-class
  * implementation.
+ *
+ * Important: if you override any of the methods of this class, you must call the super
+ * implementation, and you must not call [AppWidgetProvider.goAsync], as it will be called by the
+ * super implementation. This means your processing time must be short.
  */
 abstract class GlanceAppWidgetReceiver : AppWidgetProvider() {
 
@@ -88,10 +92,11 @@
         }
     }
 
-    override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
-        // TODO: When a widget is deleted, delete the datastore
-        appWidgetIds?.forEach {
-            createUniqueRemoteUiName(it)
+    @CallSuper
+    override fun onDeleted(context: Context, appWidgetIds: IntArray) {
+        goAsync {
+            updateManager(context)
+            appWidgetIds.forEach { glanceAppWidget.deleted(context, it) }
         }
     }
 
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterCallbackTrampolineActivity.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterInvisibleTrampolineActivity.kt
similarity index 60%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterCallbackTrampolineActivity.kt
rename to glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterInvisibleTrampolineActivity.kt
index 96108e7..1cc17f8 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterCallbackTrampolineActivity.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterInvisibleTrampolineActivity.kt
@@ -17,28 +17,17 @@
 package androidx.glance.appwidget
 
 import android.app.Activity
-import android.content.Intent
 import android.os.Bundle
 
 /**
- * Trampoline activity for handling click interactions of list adapter items that invoke action
- * callbacks.
+ * Trampoline activity for handling click interactions of list adapter items that invoke actions
+ * that don't launch an activity. Thus not showing any UI.
  */
 @Suppress("ForbiddenSuperClass")
-internal class ListAdapterCallbackTrampolineActivity : Activity() {
+internal class ListAdapterInvisibleTrampolineActivity : Activity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        intent?.getParcelableExtra<Intent>(ActionIntentKey)
-            ?.let { sendBroadcast(it) }
-            ?: error("List adapter activity trampoline invoked without specifying target intent.")
-        finish()
+        launchTrampolineAction(intent)
     }
-
-    companion object {
-        private const val ActionIntentKey = "UPDATE_CONTENT_ACTION_INTENT"
-
-        internal fun Intent.putBroadcastIntentExtra(actionIntent: Intent) =
-            putExtra(ActionIntentKey, actionIntent)
-    }
-}
+}
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampoline.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampoline.kt
new file mode 100644
index 0000000..5ff4bc4
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampoline.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.glance.appwidget
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.widget.RemoteViews
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
+
+internal enum class ListAdapterTrampolineType {
+    ACTIVITY, BROADCAST, SERVICE, FOREGROUND_SERVICE
+}
+
+/**
+ * Wraps the "action intent" into an activity trampoline intent, where it will be invoked based on
+ * the type, with modifying its content.
+ *
+ * @see launchTrampolineAction
+ */
+internal fun Intent.applyTrampolineIntent(
+    context: Context,
+    viewId: Int,
+    type: ListAdapterTrampolineType,
+): Intent {
+    val target = if (type == ListAdapterTrampolineType.ACTIVITY) {
+        ListAdapterTrampolineActivity::class.java
+    } else {
+        ListAdapterInvisibleTrampolineActivity::class.java
+    }
+    return Intent(context, target).apply {
+        data = Uri.parse(toUri(0))
+            .buildUpon()
+            .scheme(type.name)
+            .path(viewId.toString())
+            .build()
+        putExtra(ActionTypeKey, type.name)
+        putExtra(ActionIntentKey, this@applyTrampolineIntent)
+    }
+}
+
+/**
+ * Unwraps and launches the action intent based on its type.
+ *
+ * @see applyTrampolineIntent
+ */
+internal fun Activity.launchTrampolineAction(intent: Intent) {
+    val actionIntent = requireNotNull(intent.getParcelableExtra<Intent>(ActionIntentKey)) {
+        "List adapter activity trampoline invoked without specifying target intent."
+    }
+    if (intent.hasExtra(RemoteViews.EXTRA_CHECKED)) {
+        actionIntent.putExtra(
+            RemoteViews.EXTRA_CHECKED,
+            intent.getBooleanExtra(RemoteViews.EXTRA_CHECKED, false)
+        )
+    }
+    val type = requireNotNull(intent.getStringExtra(ActionTypeKey)) {
+        "List adapter activity trampoline invoked without trampoline type"
+    }
+    when (ListAdapterTrampolineType.valueOf(type)) {
+        ListAdapterTrampolineType.ACTIVITY -> startActivity(actionIntent)
+        ListAdapterTrampolineType.BROADCAST -> sendBroadcast(actionIntent)
+        ListAdapterTrampolineType.SERVICE -> startService(actionIntent)
+        ListAdapterTrampolineType.FOREGROUND_SERVICE -> {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                ListAdapterTrampolineApi26Impl.startForegroundService(
+                    context = this,
+                    intent = actionIntent
+                )
+            } else {
+                startService(actionIntent)
+            }
+        }
+    }
+    finish()
+}
+
+private const val ActionTypeKey = "ACTION_TYPE"
+private const val ActionIntentKey = "ACTION_INTENT"
+
+@RequiresApi(Build.VERSION_CODES.O)
+private object ListAdapterTrampolineApi26Impl {
+    @DoNotInline
+    fun startForegroundService(context: Context, intent: Intent) {
+        context.startForegroundService(intent)
+    }
+}
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterLaunchActivityTrampolineActivity.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampolineActivity.kt
similarity index 60%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterLaunchActivityTrampolineActivity.kt
rename to glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampolineActivity.kt
index 38b17c7..4fdbdc9 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterLaunchActivityTrampolineActivity.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ListAdapterTrampolineActivity.kt
@@ -17,7 +17,6 @@
 package androidx.glance.appwidget
 
 import android.app.Activity
-import android.content.Intent
 import android.os.Bundle
 
 /**
@@ -25,24 +24,10 @@
  * This trampoline is only used for device versions before [android.os.Build.VERSION_CODES.Q].
  */
 @Suppress("ForbiddenSuperClass")
-internal class ListAdapterLaunchActivityTrampolineActivity : Activity() {
+internal class ListAdapterTrampolineActivity : Activity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
-        intent?.getParcelableExtra<Intent>(ActionIntentKey)
-            ?.let {
-                // Copy flags from trampoline intent to action intent
-                it.flags = it.flags or intent.flags
-                startActivity(it)
-            }
-            ?: error("List adapter activity trampoline invoked without specifying target intent.")
-        finish()
-    }
-
-    companion object {
-        private const val ActionIntentKey = "ACTIVITY_ACTION_INTENT"
-
-        internal fun Intent.putActivityIntentExtra(actionIntent: Intent) =
-            putExtra(ActionIntentKey, actionIntent)
+        launchTrampolineAction(intent)
     }
 }
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt
index b6f2a50..a20a4e5 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt
@@ -21,6 +21,9 @@
 import androidx.glance.Emittable
 import androidx.glance.GlanceModifier
 import androidx.glance.GlanceNode
+import androidx.glance.action.Action
+import androidx.glance.action.ActionModifier
+import androidx.glance.appwidget.action.CompoundButtonAction
 import androidx.glance.appwidget.unit.CheckableColorProvider
 import androidx.glance.appwidget.unit.CheckedUncheckedColorProvider.Companion.createCheckableColorProvider
 import androidx.glance.appwidget.unit.ResourceCheckableColorProvider
@@ -111,6 +114,10 @@
  * Adds a switch view to the glance view.
  *
  * @param checked whether the switch is checked
+ * @param onCheckedChange the action to be run when the switch is clicked. The current value of
+ * checked is provided to this action in its ActionParameters, and can be retrieved using the
+ * [ToggleableStateKey]. If this action launches an activity, the current value of checked will be
+ * passed as an intent extra with the name [RemoteViews.EXTRA_CHECKED].
  * @param modifier the modifier to apply to the switch
  * @param text the text to display to the end of the switch
  * @param style the style to apply to [text]
@@ -119,17 +126,23 @@
 @Composable
 fun Switch(
     checked: Boolean,
+    onCheckedChange: Action?,
     modifier: GlanceModifier = GlanceModifier,
     text: String = "",
     style: TextStyle? = null,
     colors: SwitchColors = SwitchDefaults.colors
 ) {
+    val finalModifier = if (onCheckedChange != null) {
+        modifier.then(ActionModifier(CompoundButtonAction(onCheckedChange, checked)))
+    } else {
+        modifier
+    }
     GlanceNode(
         factory = ::EmittableSwitch,
         update = {
             this.set(checked) { this.checked = it }
             this.set(text) { this.text = it }
-            this.set(modifier) { this.modifier = it }
+            this.set(finalModifier) { this.modifier = it }
             this.set(style) { this.style = it }
             this.set(colors) { this.colors = it }
         }
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt
index e3a38e6..71785ab 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt
@@ -280,11 +280,13 @@
     override fun getLocation(context: Context, fileKey: String): File =
         context.dataStoreFile(fileKey)
 
-    @Suppress("UNCHECKED_CAST")
-    override suspend fun <T> getDataStore(context: Context, fileKey: String): DataStore<T> =
+    override suspend fun getDataStore(
+        context: Context,
+        fileKey: String,
+    ): DataStore<LayoutProto.LayoutConfig> =
         DataStoreFactory.create(serializer = LayoutProtoSerializer) {
             context.dataStoreFile(fileKey)
-        } as DataStore<T>
+        }
 }
 
 private fun Alignment.Vertical.toProto() = when (this) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/CompoundButtonAction.kt
similarity index 68%
copy from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
copy to glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/CompoundButtonAction.kt
index d721bff..cdc9db0 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/CompoundButtonAction.kt
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.glance.appwidget.action
 
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemsProvider
+import androidx.glance.action.Action
 
-internal interface LazyListItemsProvider : LazyLayoutItemsProvider {
-    /** The list of indexes of the sticky header items */
-    val headerIndexes: List<Int>
-}
+internal class CompoundButtonAction(
+    val innerAction: Action,
+    val checked: Boolean
+) : Action
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchActivityIntentAction.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchActivityIntentAction.kt
index 5ce93e9..7e7f48a 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchActivityIntentAction.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchActivityIntentAction.kt
@@ -19,9 +19,14 @@
 import android.app.Activity
 import android.content.Intent
 import androidx.glance.action.Action
+import androidx.glance.action.ActionParameters
 import androidx.glance.action.LaunchActivityAction
+import androidx.glance.action.actionParametersOf
 
-internal class LaunchActivityIntentAction(val intent: Intent) : LaunchActivityAction
+internal class LaunchActivityIntentAction(
+    val intent: Intent,
+    override val parameters: ActionParameters = actionParametersOf()
+) : LaunchActivityAction
 
 /**
  * Creates an [Action] that launches an [Activity] from the given [Intent] when triggered. The
@@ -30,5 +35,10 @@
  * This action is supported by app widgets only.
  *
  * @param intent the intent used to launch the activity
+ * @param parameters the parameters associated with the action. Parameter values will be added to
+ * the activity intent, keyed by the parameter key name string.
  */
-public fun actionLaunchActivity(intent: Intent): Action = LaunchActivityIntentAction(intent)
+public fun actionLaunchActivity(
+    intent: Intent,
+    parameters: ActionParameters = actionParametersOf()
+): Action = LaunchActivityIntentAction(intent, parameters)
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchBroadcastAction.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchBroadcastAction.kt
new file mode 100644
index 0000000..c4a050f
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchBroadcastAction.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.glance.appwidget.action
+
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Intent
+import androidx.glance.action.Action
+
+internal sealed interface LaunchBroadcastReceiverAction : Action
+
+internal class LaunchBroadcastReceiverActionAction(
+    val action: String,
+    val componentName: ComponentName? = null,
+) : LaunchBroadcastReceiverAction
+
+internal class LaunchBroadcastReceiverComponentAction(
+    val componentName: ComponentName,
+) : LaunchBroadcastReceiverAction
+
+internal class LaunchBroadcastReceiverClassAction(
+    val receiverClass: Class<out BroadcastReceiver>,
+) : LaunchBroadcastReceiverAction
+
+internal class LaunchBroadcastReceiverIntentAction(
+    val intent: Intent,
+) : LaunchBroadcastReceiverAction
+
+/**
+ * Creates an [Action] that launches the [BroadcastReceiver] specified by the given action.
+ *
+ * @param action of the BroadcastReceiver to launch
+ * @param componentName optional [ComponentName] of the target BroadcastReceiver
+ */
+public fun actionLaunchBroadcastReceiver(
+    action: String,
+    componentName: ComponentName? = null
+): Action = LaunchBroadcastReceiverActionAction(action, componentName)
+
+/**
+ * Creates an [Action] that launches a [BroadcastReceiver] from the given [Intent] when triggered.
+ * The intent should specify a component with [Intent.setClass] or [Intent.setComponent].
+ *
+ * @param intent the [Intent] used to launch the [BroadcastReceiver]
+ */
+public fun actionLaunchBroadcastReceiver(intent: Intent): Action =
+    LaunchBroadcastReceiverIntentAction(intent)
+
+/**
+ * Creates an [Action] that launches the [BroadcastReceiver] specified by the given [ComponentName].
+ *
+ * @param componentName component of the [BroadcastReceiver] to launch
+ */
+public fun actionLaunchBroadcastReceiver(componentName: ComponentName): Action =
+    LaunchBroadcastReceiverComponentAction(componentName)
+
+/**
+ * Creates an [Action] that launches the specified [BroadcastReceiver] when triggered.
+ *
+ * @param receiver class of the [BroadcastReceiver] to launch
+ */
+public fun <T : BroadcastReceiver> actionLaunchBroadcastReceiver(receiver: Class<T>): Action =
+    LaunchBroadcastReceiverClassAction(receiver)
+
+/**
+ * Creates an [Action] that launches the specified [BroadcastReceiver] when triggered.
+ */
+@Suppress("MissingNullability") // Shouldn't need to specify @NonNull. b/199284086
+public inline fun <reified T : BroadcastReceiver> actionLaunchBroadcastReceiver(): Action =
+    actionLaunchBroadcastReceiver(T::class.java)
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchServiceAction.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchServiceAction.kt
new file mode 100644
index 0000000..183e9bf
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LaunchServiceAction.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.glance.appwidget.action
+
+import android.app.Service
+import android.content.ComponentName
+import android.content.Intent
+import androidx.glance.action.Action
+
+internal sealed interface LaunchServiceAction : Action {
+    val isForegroundService: Boolean
+}
+
+internal class LaunchServiceComponentAction(
+    val componentName: ComponentName,
+    override val isForegroundService: Boolean
+) : LaunchServiceAction
+
+internal class LaunchServiceClassAction(
+    val serviceClass: Class<out Service>,
+    override val isForegroundService: Boolean
+) : LaunchServiceAction
+
+internal class LaunchServiceIntentAction(
+    val intent: Intent,
+    override val isForegroundService: Boolean
+) : LaunchServiceAction
+
+/**
+ * Creates an [Action] that launches a [Service] from the given [Intent] when triggered. The
+ * intent should specify a component with [Intent.setClass] or [Intent.setComponent].
+ *
+ * @param intent the intent used to launch the activity
+ * @param isForegroundService set to true when the provided [Service] runs in foreground. This flag
+ * is only used for device versions after [android.os.Build.VERSION_CODES.O] that requires
+ * foreground service to be launched differently
+ */
+public fun actionLaunchService(intent: Intent, isForegroundService: Boolean = false): Action =
+    LaunchServiceIntentAction(intent, isForegroundService)
+
+/**
+ * Creates an [Action] that launches the [Service] specified by the given [ComponentName].
+ *
+ * @param componentName component of the Service to launch
+ * @param isForegroundService set to true when the provided [Service] runs in foreground. This flag
+ * is only used for device versions after [android.os.Build.VERSION_CODES.O] that requires
+ * foreground service to be launched differently
+ */
+public fun actionLaunchService(
+    componentName: ComponentName,
+    isForegroundService: Boolean = false
+): Action = LaunchServiceComponentAction(componentName, isForegroundService)
+
+/**
+ * Creates an [Action] that launches the specified [Service] when triggered.
+ *
+ * @param service class of the Service to launch
+ * @param isForegroundService set to true when the provided [Service] runs in foreground. This flag
+ * is only used for device versions after [android.os.Build.VERSION_CODES.O] that requires
+ * foreground service to be launched differently
+ */
+public fun <T : Service> actionLaunchService(
+    service: Class<T>,
+    isForegroundService: Boolean = false
+): Action =
+    LaunchServiceClassAction(service, isForegroundService)
+
+/**
+ * Creates an [Action] that launches the specified [Service] when triggered.
+ *
+ * @param isForegroundService set to true when the provided [Service] runs in foreground. This flag
+ * is only used for device versions after [android.os.Build.VERSION_CODES.O] that requires
+ * foreground service to be launched differently.
+ */
+@Suppress("MissingNullability") /* Shouldn't need to specify @NonNull. b/199284086 */
+public inline fun <reified T : Service> actionLaunchService(
+    isForegroundService: Boolean = false
+): Action = actionLaunchService(T::class.java, isForegroundService)
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt
index 8eb48e5..43b3ef2 100644
--- a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt
@@ -77,12 +77,12 @@
     parameters: ActionParameters = actionParametersOf()
 ): Action = RunCallbackAction(callbackClass, parameters)
 
-@Suppress("MissingNullability") /* Shouldn't need to specify @NonNull. b/199284086 */
 /**
  * Creates an [Action] that executes a given [ActionCallback] implementation
  *
  * @param parameters the parameters associated with the action
  */
+@Suppress("MissingNullability") // Shouldn't need to specify @NonNull. b/199284086
 public inline fun <reified T : ActionCallback> actionRunCallback(
     parameters: ActionParameters = actionParametersOf()
 ): Action = actionRunCallback(T::class.java, parameters)
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/Toggleable.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/Toggleable.kt
new file mode 100644
index 0000000..f47f573e
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/Toggleable.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.glance.appwidget.action
+
+import android.widget.RemoteViews
+import androidx.glance.action.ActionParameters
+
+/**
+ * This key is used to access the current checked value for actions that are triggered by compound
+ * button interactions (e.g. [CheckBox], [Switch]). This key is used to retrieve the value from the
+ * [ActionParameters] passed to the action.
+ */
+val ToggleableStateKey = ActionParameters.Key<Boolean>(RemoteViews.EXTRA_CHECKED)
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/state/GlanceAppWidgetState.kt b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/state/GlanceAppWidgetState.kt
new file mode 100644
index 0000000..3c4455d
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/state/GlanceAppWidgetState.kt
@@ -0,0 +1,87 @@
+/*
+ * 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.glance.appwidget.state
+
+import android.content.Context
+import androidx.glance.GlanceId
+import androidx.glance.appwidget.AppWidgetId
+import androidx.glance.appwidget.GlanceAppWidget
+import androidx.glance.appwidget.createUniqueRemoteUiName
+import androidx.glance.state.GlanceState
+import androidx.glance.state.GlanceStateDefinition
+
+/**
+ * Retrieve the state of an app widget.
+ *
+ * The state definition must be the one used for that particular app widget.
+ */
+public suspend fun <T> getAppWidgetState(
+    context: Context,
+    definition: GlanceStateDefinition<T>,
+    glanceId: GlanceId,
+): T {
+    require(glanceId is AppWidgetId) { "The glance ID is not the one of an App Widget" }
+    return GlanceState.getValue(context, definition, createUniqueRemoteUiName(glanceId.appWidgetId))
+}
+
+/**
+ * Update the state of an app widget.
+ *
+ * The state definition must be the one used for that particular app widget.
+ */
+public suspend fun <T> updateAppWidgetState(
+    context: Context,
+    definition: GlanceStateDefinition<T>,
+    glanceId: GlanceId,
+    updateState: suspend (T) -> T,
+): T {
+    require(glanceId is AppWidgetId) { "The glance ID is not the one of an App Widget" }
+    return GlanceState.updateValue(
+        context,
+        definition,
+        createUniqueRemoteUiName(glanceId.appWidgetId),
+        updateState,
+    )
+}
+
+/** Get the state of an App Widget. */
+@Suppress("UNCHECKED_CAST")
+public suspend fun <T> GlanceAppWidget.getAppWidgetState(
+    @Suppress("ContextFirst") context: Context,
+    glanceId: GlanceId
+): T =
+    getAppWidgetState(
+        context,
+        checkNotNull(stateDefinition) { "No state defined in this provider" },
+        glanceId
+    ) as T
+
+/** Update the state of an app widget. */
+@Suppress("UNCHECKED_CAST")
+public suspend fun <T> GlanceAppWidget.updateAppWidgetState(
+    @Suppress("ContextFirst") context: Context,
+    glanceId: GlanceId,
+    updateState: suspend (T) -> T,
+): T =
+    updateAppWidgetState(
+        context,
+        checkNotNull(stateDefinition as GlanceStateDefinition<T>) {
+            "No state defined in this provider"
+        },
+        glanceId,
+        updateState,
+    )
diff --git a/glance/glance-appwidget/src/androidMain/res/color/switch_off_ambient_shadow.xml b/glance/glance-appwidget/src/androidMain/res/color/switch_off_ambient_shadow.xml
new file mode 100644
index 0000000..e31f49e
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/color/switch_off_ambient_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+    android:centerX="13"
+    android:centerY="12"
+    android:gradientRadius="10.25"
+    android:type="radial">
+    <item
+        android:color="#6D050505"
+        android:offset="0" />
+    <item
+        android:color="#50050505"
+        android:offset="0.6" />
+    <item
+        android:color="#20000000"
+        android:offset="0.90" />
+    <item
+        android:color="#00000000"
+        android:offset="1" />
+</gradient>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/color/switch_off_key_shadow.xml b/glance/glance-appwidget/src/androidMain/res/color/switch_off_key_shadow.xml
new file mode 100644
index 0000000..2834f7f
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/color/switch_off_key_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+    android:centerX="13"
+    android:centerY="14"
+    android:gradientRadius="10"
+    android:type="radial">
+    <item
+        android:color="#6D050505"
+        android:offset="0" />
+    <item
+        android:color="#50050505"
+        android:offset="0.6" />
+    <item
+        android:color="#20000000"
+        android:offset="0.8" />
+    <item
+        android:color="#00000000"
+        android:offset="1" />
+</gradient>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/color/switch_on_ambient_shadow.xml b/glance/glance-appwidget/src/androidMain/res/color/switch_on_ambient_shadow.xml
new file mode 100644
index 0000000..3f4f9cc
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/color/switch_on_ambient_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+    android:centerX="24"
+    android:centerY="12"
+    android:gradientRadius="10.25"
+    android:type="radial">
+    <item
+        android:color="#6D050505"
+        android:offset="0" />
+    <item
+        android:color="#50050505"
+        android:offset="0.6" />
+    <item
+        android:color="#20000000"
+        android:offset="0.90" />
+    <item
+        android:color="#00000000"
+        android:offset="1" />
+</gradient>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/color/switch_on_key_shadow.xml b/glance/glance-appwidget/src/androidMain/res/color/switch_on_key_shadow.xml
new file mode 100644
index 0000000..d374869
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/color/switch_on_key_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+    android:centerX="24"
+    android:centerY="14"
+    android:gradientRadius="10.25"
+    android:type="radial">
+    <item
+        android:color="#6D050505"
+        android:offset="0" />
+    <item
+        android:color="#50050505"
+        android:offset="0.6" />
+    <item
+        android:color="#40000000"
+        android:offset="0.8" />
+    <item
+        android:color="#00000000"
+        android:offset="1" />
+</gradient>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00001.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00001.9.png
deleted file mode 100644
index 4657a25..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00001.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00012.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00012.9.png
deleted file mode 100644
index 8dc415b..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-hdpi/abc_btn_switch_to_on_mtrl_00012.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_unchecked.xml b/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_unchecked.xml
deleted file mode 100644
index d2d35b7..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_unchecked.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  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.
-  -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00001"
-    android:insetLeft="18dp"/>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00001.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00001.9.png
deleted file mode 100644
index d0a41a5..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00001.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00012.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00012.9.png
deleted file mode 100644
index bebb1e2..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-mdpi/abc_btn_switch_to_on_mtrl_00012.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00001.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
deleted file mode 100644
index 1d29f9a..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00012.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
deleted file mode 100644
index 92b43ba..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
deleted file mode 100644
index c079867..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
deleted file mode 100644
index 3b9dc7c..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
deleted file mode 100644
index 639e6cb..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00001.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png b/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
deleted file mode 100644
index 355d5b7..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable-xxxhdpi/abc_btn_switch_to_on_mtrl_00012.9.png
+++ /dev/null
Binary files differ
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_animated.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_animated.xml
new file mode 100644
index 0000000..c3491b6
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_animated.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/on"
+        android:drawable="@drawable/switch_thumb_on"
+        android:state_enabled="true" />
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/switch_thumb_off" />
+    <transition
+        android:drawable="@drawable/switch_thumb_off_to_on"
+        android:fromId="@+id/off"
+        android:toId="@+id/on" />
+    <transition
+        android:drawable="@drawable/switch_thumb_on_to_off"
+        android:fromId="@+id/on"
+        android:toId="@+id/off" />
+</animated-selector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material.xml
deleted file mode 100644
index 939b1c2..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="true" android:drawable="@drawable/switch_thumb_material_checked" />
-    <item android:drawable="@drawable/switch_thumb_material_unchecked" />
-</selector>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_checked.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_checked.xml
deleted file mode 100644
index ece7ee7..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_checked.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  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.
-  -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetLeft="18dp"/>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_unchecked.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_unchecked.xml
deleted file mode 100644
index a151ef9..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_material_unchecked.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  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.
-  -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00001"
-    android:insetRight="18dp"/>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off.xml
new file mode 100644
index 0000000..721590f
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off.xml
@@ -0,0 +1,25 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="26dp"
+    android:viewportWidth="40"
+    android:viewportHeight="26"
+>
+  <group android:name="thumb" android:translateX="0">
+    <path
+        android:pathData="M13,22.5C18.7989,22.5 23.5,17.7989 23.5,12 23.5,6.201 18.7989,1.5 13,1.5 7.201,1.5 2.5,6.201 2.5,12 2.5,17.7989 7.201,22.5 13,22.5Z"
+        android:strokeWidth="1.05"
+        android:fillColor="@color/switch_off_ambient_shadow"
+        android:fillType="evenOdd"/>
+    <path
+        android:pathData="m12.9681,24.2511c5.7734,0 10.4537,-5.084 10.4537,-11.3552 0,-6.2713 -4.6803,-11.3552 -10.4537,-11.3552 -5.7734,0 -10.4537,5.0839 -10.4537,11.3552 0,6.2713 4.6803,11.3552 10.4537,11.3552z"
+        android:strokeWidth="1.08951"
+        android:fillColor="@color/switch_off_key_shadow"
+        android:fillType="evenOdd"/>
+    <path
+        android:name="thumb_icon"
+        android:pathData="M13,22C18.5228,22 23,17.5228 23,12 23,6.4771 18.5228,2 13,2 7.4771,2 3,6.4771 3,12c0,5.5228 4.4771,10 10,10z"
+        android:strokeWidth="1"
+        android:fillColor="#fff"
+        android:fillType="evenOdd"/>
+  </group>
+</vector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off_to_on.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off_to_on.xml
new file mode 100644
index 0000000..a162697
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_off_to_on.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:drawable="@drawable/switch_thumb_off">
+    <target
+        android:name="thumb" >
+        <aapt:attr name="android:animation">
+            <objectAnimator
+                android:propertyName="translateX"
+                android:valueFrom="0"
+                android:valueTo="14"
+                android:duration="250"
+                android:interpolator="@android:interpolator/linear" />
+        </aapt:attr>
+    </target>
+</animated-vector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on.xml
new file mode 100644
index 0000000..bf6ea1c
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on.xml
@@ -0,0 +1,26 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="26dp"
+    android:viewportWidth="40"
+    android:viewportHeight="26"
+    >
+    <group
+        android:name="thumb"
+        android:translateX="3">
+        <path
+            android:fillColor="@color/switch_on_key_shadow"
+            android:fillType="evenOdd"
+            android:pathData="m23.9373,24.5329c5.7734,0 10.4537,-5.084 10.4537,-11.3552 0,-6.2713 -4.6803,-11.3552 -10.4537,-11.3552 -5.7734,0 -10.4537,5.0839 -10.4537,11.3552 0,6.2713 4.6803,11.3552 10.4537,11.3552z"
+            android:strokeWidth="1.08951" />
+        <path
+            android:fillColor="@color/switch_on_ambient_shadow"
+            android:fillType="evenOdd"
+            android:pathData="M24,22.5C29.7989,22.5 34.5,17.7989 34.5,12 34.5,6.201 29.7989,1.5 24,1.5 18.201,1.5 13.5,6.201 13.5,12c0,5.7989 4.701,10.5 10.5,10.5z"
+            android:strokeWidth="1.05" />
+        <path
+            android:name="thumb_icon"
+            android:fillColor="#fff"
+            android:fillType="evenOdd"
+            android:pathData="M24,22C29.5228,22 34,17.5228 34,12C34,6.4771 29.5228,2 24,2C18.4772,2 14,6.4771 14,12C14,17.5228 18.4772,22 24,22Z" />
+    </group>
+</vector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on_to_off.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on_to_off.xml
new file mode 100644
index 0000000..e78f0c2
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_thumb_on_to_off.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:drawable="@drawable/switch_thumb_on">
+    <target
+        android:name="thumb" >
+        <aapt:attr name="android:animation">
+            <objectAnimator
+                android:propertyName="translateX"
+                android:valueFrom="0"
+                android:valueTo="-14"
+                android:duration="250"
+                android:interpolator="@android:interpolator/linear" />
+        </aapt:attr>
+    </target>
+</animated-vector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_track.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_track.xml
new file mode 100644
index 0000000..3c0f448
--- /dev/null
+++ b/glance/glance-appwidget/src/androidMain/res/drawable/switch_track.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="26dp"
+    android:viewportWidth="40"
+    android:viewportHeight="26"
+>
+  <path
+      android:name="track"
+      android:pathData="M10,5L30,5A7,7 0,0 1,37 12L37,12A7,7 0,0 1,30 19L10,19A7,7 0,0 1,3 12L3,12A7,7 0,0 1,10 5z"
+      android:fillColor="@android:color/white"
+      android:fillAlpha="?android:attr/disabledAlpha"/>
+</vector>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/switch_track_material.xml b/glance/glance-appwidget/src/androidMain/res/drawable/switch_track_material.xml
deleted file mode 100644
index 0e93096..0000000
--- a/glance/glance-appwidget/src/androidMain/res/drawable/switch_track_material.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:gravity="center_vertical|fill_horizontal"
-        android:start="4dp"
-        android:end="4dp">
-        <shape android:shape="rectangle">
-            <corners android:radius="7dp" />
-            <solid android:color="@color/white_disabled_material_anim" />
-            <size android:height="14dp" />
-        </shape>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/swtch_text.xml b/glance/glance-appwidget/src/androidMain/res/layout/switch_text.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/swtch_text.xml
rename to glance/glance-appwidget/src/androidMain/res/layout/switch_text.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/swtch_thumb.xml b/glance/glance-appwidget/src/androidMain/res/layout/switch_thumb.xml
similarity index 94%
rename from glance/glance-appwidget/src/androidMain/res/layout/swtch_thumb.xml
rename to glance/glance-appwidget/src/androidMain/res/layout/switch_thumb.xml
index bb31034..8106726 100644
--- a/glance/glance-appwidget/src/androidMain/res/layout/swtch_thumb.xml
+++ b/glance/glance-appwidget/src/androidMain/res/layout/switch_thumb.xml
@@ -18,5 +18,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical|start"
-    android:src="@drawable/switch_thumb_material"
+    android:src="@drawable/switch_thumb_animated"
     style="@style/Glance.AppWidget.SwitchThumb"/>
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/swtch_track.xml b/glance/glance-appwidget/src/androidMain/res/layout/switch_track.xml
similarity index 94%
rename from glance/glance-appwidget/src/androidMain/res/layout/swtch_track.xml
rename to glance/glance-appwidget/src/androidMain/res/layout/switch_track.xml
index 375967e..e65bc84 100644
--- a/glance/glance-appwidget/src/androidMain/res/layout/swtch_track.xml
+++ b/glance/glance-appwidget/src/androidMain/res/layout/switch_track.xml
@@ -17,5 +17,5 @@
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="42dp"
     android:layout_height="28dp"
-    android:src="@drawable/switch_track_material"
+    android:src="@drawable/switch_track"
     style="@style/Glance.AppWidget.SwitchTrack"/>
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/swtch_backport.xml b/glance/glance-appwidget/src/androidMain/res/layout/swtch_backport.xml
index 0258870..f6caf8a 100644
--- a/glance/glance-appwidget/src/androidMain/res/layout/swtch_backport.xml
+++ b/glance/glance-appwidget/src/androidMain/res/layout/swtch_backport.xml
@@ -25,7 +25,7 @@
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_weight="1"
-        android:layout="@layout/swtch_text" />
+        android:layout="@layout/switch_text" />
     <FrameLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -35,12 +35,12 @@
             android:id="@id/switchTrack"
             android:layout_width="42dp"
             android:layout_height="28dp"
-            android:layout="@layout/swtch_track" />
+            android:layout="@layout/switch_track" />
 
         <ViewStub
             android:id="@id/switchThumb"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout="@layout/swtch_thumb" />
+            android:layout_width="42dp"
+            android:layout_height="28dp"
+            android:layout="@layout/switch_thumb" />
     </FrameLayout>
 </LinearLayout>
diff --git a/glance/glance-appwidget/src/androidMain/res/values/ids.xml b/glance/glance-appwidget/src/androidMain/res/values/ids.xml
index 6ab0397..5d9dcb7 100644
--- a/glance/glance-appwidget/src/androidMain/res/values/ids.xml
+++ b/glance/glance-appwidget/src/androidMain/res/values/ids.xml
@@ -23,8 +23,8 @@
     <id name="sizeView" />
     <id name="sizeViewStub" />
     <id name="switchText" />
-    <id name="switchTrack" />
     <id name="switchThumb" />
+    <id name="switchTrack" />
     <id name="rootView" />
     <id name="rootStubId" />
     <id name="deletedViewId" />
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/glance/glance-appwidget/src/main/res/values-v29/themes.xml
similarity index 79%
copy from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
copy to glance/glance-appwidget/src/main/res/values-v29/themes.xml
index 987c157..4cce739 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/glance/glance-appwidget/src/main/res/values-v29/themes.xml
@@ -14,6 +14,6 @@
   limitations under the License.
   -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+<resources>
+    <style name="Glance.AppWidget.Theme" parent="android:Theme.DeviceDefault.DayNight" />
+</resources>
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml b/glance/glance-appwidget/src/main/res/values/themes.xml
similarity index 79%
rename from glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
rename to glance/glance-appwidget/src/main/res/values/themes.xml
index 987c157..efd5acd 100644
--- a/glance/glance-appwidget/src/androidMain/res/drawable-ldrtl/switch_thumb_material_checked.xml
+++ b/glance/glance-appwidget/src/main/res/values/themes.xml
@@ -14,6 +14,6 @@
   limitations under the License.
   -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/abc_btn_switch_to_on_mtrl_00012"
-    android:insetRight="18dp"/>
\ No newline at end of file
+<resources>
+    <style name="Glance.AppWidget.Theme" parent="android:Theme.DeviceDefault"/>
+</resources>
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/RemoteViewsTranslatorKtTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/RemoteViewsTranslatorKtTest.kt
index dcdf7cc..14e36af 100644
--- a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/RemoteViewsTranslatorKtTest.kt
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/RemoteViewsTranslatorKtTest.kt
@@ -638,6 +638,7 @@
         val rv = context.runAndTranslate {
             CheckBox(
                 checked = false,
+                onCheckedChange = null,
                 text = "test",
                 style = TextStyle(
                     color = ColorProvider(Color.Red),
@@ -665,6 +666,7 @@
         val rv = context.runAndTranslate {
             CheckBox(
                 checked = true,
+                onCheckedChange = null,
                 text = "test checked",
                 style = TextStyle(textDecoration = TextDecoration.LineThrough),
             )
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/WidgetLayoutTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/WidgetLayoutTest.kt
index baa4073..a154511 100644
--- a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/WidgetLayoutTest.kt
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/WidgetLayoutTest.kt
@@ -62,7 +62,11 @@
     fun testLayout() = fakeCoroutineScope.runBlockingTest {
         val root = runTestingComposition {
             Column(horizontalAlignment = Alignment.End) {
-                CheckBox(checked = false, modifier = GlanceModifier.fillMaxSize())
+                CheckBox(
+                    checked = false,
+                    onCheckedChange = null,
+                    modifier = GlanceModifier.fillMaxSize()
+                )
                 Button(text = "test", onClick = actionLaunchActivity<Activity>())
                 Image(
                     ImageProvider(R.drawable.oval),
@@ -102,7 +106,11 @@
         val appId = 999
         val root = runTestingComposition {
             Column {
-                CheckBox(checked = true, modifier = GlanceModifier.fillMaxSize())
+                CheckBox(
+                    checked = true,
+onCheckedChange = null,
+                    modifier = GlanceModifier.fillMaxSize()
+                )
                 Button(text = "test", onClick = actionLaunchActivity<Activity>())
             }
         }
@@ -110,6 +118,7 @@
             Column {
                 CheckBox(
                     checked = true,
+                    onCheckedChange = null,
                     modifier = GlanceModifier.wrapContentWidth().fillMaxHeight()
                 )
                 Button(text = "test", onClick = actionLaunchActivity<Activity>())
@@ -324,13 +333,21 @@
         val appId = 787
         val root = runTestingComposition {
             Column {
-                CheckBox(checked = true, modifier = GlanceModifier.fillMaxSize())
+                CheckBox(
+                    checked = true,
+                    onCheckedChange = null,
+                    modifier = GlanceModifier.fillMaxSize()
+                )
                 Button(text = "test", onClick = actionLaunchActivity<Activity>())
             }
         }
         val root2 = runTestingComposition {
             Column {
-                CheckBox(checked = false, modifier = GlanceModifier.fillMaxSize())
+                CheckBox(
+                    checked = false,
+                    onCheckedChange = null,
+                    modifier = GlanceModifier.fillMaxSize()
+                )
                 Button(text = "testtesttest", onClick = actionLaunchActivity<Activity>())
             }
         }
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchBroadcastReceiverActionTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchBroadcastReceiverActionTest.kt
new file mode 100644
index 0000000..79215f4
--- /dev/null
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchBroadcastReceiverActionTest.kt
@@ -0,0 +1,108 @@
+/*
+ * 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.glance.appwidget.action
+
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import androidx.glance.GlanceModifier
+import androidx.glance.action.ActionModifier
+import androidx.glance.action.clickable
+import androidx.glance.findModifier
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import kotlin.test.assertIs
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(RobolectricTestRunner::class)
+class LaunchBroadcastReceiverActionTest {
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+
+    @Test
+    fun testLaunchClass() {
+        val modifiers =
+            GlanceModifier.clickable(actionLaunchBroadcastReceiver<TestBroadcastReceiver>())
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchBroadcastReceiverClassAction>(modifier.action)
+        assertThat(action.receiverClass).isEqualTo(TestBroadcastReceiver::class.java)
+    }
+
+    @Test
+    fun testLaunchAction() {
+        val intentActionString = "test_action"
+        val modifiers = GlanceModifier.clickable(actionLaunchBroadcastReceiver(intentActionString))
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchBroadcastReceiverActionAction>(modifier.action)
+        assertThat(action.action).isEqualTo(intentActionString)
+        assertThat(action.componentName).isNull()
+    }
+
+    @Test
+    fun testLaunchActionWithComponentName() {
+        val intentActionString = "test_action"
+        val componentName = ComponentName(
+            "androidx.glance.appwidget.action",
+            "androidx.glance.appwidget.action.TestBroadcastReceiver"
+        )
+        val modifiers = GlanceModifier.clickable(
+            actionLaunchBroadcastReceiver(
+                intentActionString,
+                componentName
+            )
+        )
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchBroadcastReceiverActionAction>(modifier.action)
+        assertThat(action.action).isEqualTo(intentActionString)
+        assertThat(action.componentName).isEqualTo(componentName)
+    }
+
+    @Test
+    fun testLaunchIntent() {
+        val intentActionString = "test_action"
+        val intent =
+            Intent(context, TestBroadcastReceiver::class.java).setAction(intentActionString)
+        val modifiers = GlanceModifier.clickable(actionLaunchBroadcastReceiver(intent))
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchBroadcastReceiverIntentAction>(modifier.action)
+        assertThat(action.intent).isEqualTo(intent)
+        assertThat(action.intent.action).isEqualTo(intentActionString)
+    }
+
+    @Test
+    fun testLaunchComponent() {
+        val componentName = ComponentName(
+            "androidx.glance.appwidget.action",
+            "androidx.glance.appwidget.action.TestBroadcastReceiver"
+        )
+        val modifiers = GlanceModifier.clickable(actionLaunchBroadcastReceiver(componentName))
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchBroadcastReceiverComponentAction>(modifier.action)
+        assertThat(action.componentName).isEqualTo(componentName)
+    }
+}
+
+class TestBroadcastReceiver : BroadcastReceiver() {
+    override fun onReceive(context: Context, intent: Intent) {
+        // Nothing
+    }
+}
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchServiceActionTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchServiceActionTest.kt
new file mode 100644
index 0000000..5dbffd7
--- /dev/null
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/action/LaunchServiceActionTest.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.glance.appwidget.action
+
+import android.app.Service
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.IBinder
+import androidx.glance.GlanceModifier
+import androidx.glance.action.ActionModifier
+import androidx.glance.action.clickable
+import androidx.glance.findModifier
+import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import kotlin.test.assertIs
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(RobolectricTestRunner::class)
+class LaunchServiceActionTest {
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+
+    @Test
+    fun testLaunchClass() {
+        val modifiers = GlanceModifier.clickable(actionLaunchService<TestService>())
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchServiceClassAction>(modifier.action)
+        assertThat(action.serviceClass).isEqualTo(TestService::class.java)
+        assertThat(action.isForegroundService).isEqualTo(false)
+    }
+
+    @Test
+    fun testLaunchClassWithForeground() {
+        val modifiers = GlanceModifier.clickable(
+            actionLaunchService<TestService>(
+                isForegroundService = true
+            )
+        )
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchServiceClassAction>(modifier.action)
+        assertThat(action.serviceClass).isEqualTo(TestService::class.java)
+        assertThat(action.isForegroundService).isEqualTo(true)
+    }
+
+    @Test
+    fun testLaunchIntent() {
+        val intentActionString = "test_action"
+        val intent = Intent(context, TestService::class.java).setAction(intentActionString)
+        val modifiers = GlanceModifier.clickable(actionLaunchService(intent))
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchServiceIntentAction>(modifier.action)
+        assertThat(action.intent).isEqualTo(intent)
+        assertThat(action.intent.action).isEqualTo(intentActionString)
+        assertThat(action.isForegroundService).isEqualTo(false)
+    }
+
+    @Test
+    fun testLaunchComponent() {
+        val componentName = ComponentName(
+            "androidx.glance.appwidget.action",
+            "androidx.glance.appwidget.action.TestService"
+        )
+        val modifiers = GlanceModifier.clickable(actionLaunchService(componentName))
+        val modifier = checkNotNull(modifiers.findModifier<ActionModifier>())
+        val action = assertIs<LaunchServiceComponentAction>(modifier.action)
+        assertThat(action.componentName).isEqualTo(componentName)
+        assertThat(action.isForegroundService).isEqualTo(false)
+    }
+}
+
+class TestService : Service() {
+    override fun onBind(p0: Intent?): IBinder? = null
+}
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslatorTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslatorTest.kt
index 8ba6e81..b56d57b9b 100644
--- a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslatorTest.kt
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslatorTest.kt
@@ -24,6 +24,8 @@
 import androidx.glance.appwidget.CheckBox
 import androidx.glance.appwidget.CheckBoxColors
 import androidx.glance.appwidget.ImageViewSubject.Companion.assertThat
+import androidx.glance.appwidget.action.ActionCallback
+import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.appwidget.applyRemoteViews
 import androidx.glance.appwidget.configurationContext
 import androidx.glance.appwidget.findViewByType
@@ -31,6 +33,7 @@
 import androidx.glance.appwidget.test.R
 import androidx.glance.appwidget.unit.ColorProvider
 import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.TestCoroutineScope
 import kotlinx.coroutines.test.runBlockingTest
@@ -61,6 +64,7 @@
         val rv = context.runAndTranslate {
             CheckBox(
                 checked = false,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(checkedColor = Color.Red, uncheckedColor = Color.Blue)
             )
@@ -77,6 +81,7 @@
         val rv = context.runAndTranslate {
             CheckBox(
                 checked = true,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(checkedColor = Color.Red, uncheckedColor = Color.Blue)
             )
@@ -93,6 +98,7 @@
         val rv = lightContext.runAndTranslate {
             CheckBox(
                 checked = false,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(
                     checkedColor = ColorProvider(day = Color.Red, night = Color.Blue),
@@ -112,6 +118,7 @@
         val rv = darkContext.runAndTranslate {
             CheckBox(
                 checked = false,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(
                     checkedColor = ColorProvider(day = Color.Red, night = Color.Blue),
@@ -131,6 +138,7 @@
         val rv = lightContext.runAndTranslate {
             CheckBox(
                 checked = true,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(
                     checkedColor = ColorProvider(day = Color.Red, night = Color.Blue),
@@ -150,6 +158,7 @@
         val rv = darkContext.runAndTranslate {
             CheckBox(
                 checked = true,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(
                     checkedColor = ColorProvider(day = Color.Red, night = Color.Blue),
@@ -169,6 +178,7 @@
         val rv = context.runAndTranslate {
             CheckBox(
                 checked = true,
+                onCheckedChange = null,
                 text = "Check",
                 colors = CheckBoxColors(R.color.my_checkbox_colors)
             )
@@ -178,4 +188,34 @@
         val icon = checkBoxRoot.findViewByType<ImageView>()
         assertThat(icon).hasColorFilter("#FF0000")
     }
+
+    @Config(sdk = [29])
+    @Test
+    fun canTranslateCheckBox_onCheckedChange_null() = fakeCoroutineScope.runBlockingTest {
+        val rv = context.runAndTranslate {
+            CheckBox(
+                checked = true,
+                onCheckedChange = null,
+                text = "CheckBox",
+            )
+        }
+
+        val checkboxRoot = assertIs<ViewGroup>(context.applyRemoteViews(rv))
+        assertThat(checkboxRoot.hasOnClickListeners()).isFalse()
+    }
+
+    @Config(sdk = [29])
+    @Test
+    fun canTranslateCheckBox_onCheckedChange_withAction() = fakeCoroutineScope.runBlockingTest {
+        val rv = context.runAndTranslate {
+            CheckBox(
+                checked = true,
+                onCheckedChange = actionRunCallback<ActionCallback>(),
+                text = "CheckBox",
+            )
+        }
+
+        val checkboxRoot = assertIs<ViewGroup>(context.applyRemoteViews(rv))
+        assertThat(checkboxRoot.hasOnClickListeners()).isTrue()
+    }
 }
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/SwitchTranslatorTest.kt b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/SwitchTranslatorTest.kt
index 8b5766a..2e30f94 100644
--- a/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/SwitchTranslatorTest.kt
+++ b/glance/glance-appwidget/src/test/kotlin/androidx/glance/appwidget/translators/SwitchTranslatorTest.kt
@@ -24,6 +24,8 @@
 import androidx.glance.appwidget.ImageViewSubject.Companion.assertThat
 import androidx.glance.appwidget.Switch
 import androidx.glance.appwidget.SwitchColors
+import androidx.glance.appwidget.action.ActionCallback
+import androidx.glance.appwidget.action.actionRunCallback
 import androidx.glance.appwidget.applyRemoteViews
 import androidx.glance.appwidget.configurationContext
 import androidx.glance.appwidget.findView
@@ -32,6 +34,7 @@
 import androidx.glance.appwidget.unit.ColorProvider
 import androidx.glance.unit.ColorProvider
 import androidx.test.core.app.ApplicationProvider
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.TestCoroutineScope
 import kotlinx.coroutines.test.runBlockingTest
@@ -63,6 +66,7 @@
         val rv = context.runAndTranslate {
             Switch(
                 checked = false,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(Color.Blue),
@@ -83,6 +87,7 @@
         val rv = context.runAndTranslate {
             Switch(
                 checked = true,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(Color.Blue),
@@ -103,6 +108,7 @@
         val rv = lightContext.runAndTranslate {
             Switch(
                 checked = false,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(day = Color.Blue, night = Color.Red),
@@ -126,6 +132,7 @@
         val rv = darkContext.runAndTranslate {
             Switch(
                 checked = false,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(day = Color.Blue, night = Color.Red),
@@ -149,6 +156,7 @@
         val rv = lightContext.runAndTranslate {
             Switch(
                 checked = true,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(day = Color.Blue, night = Color.Red),
@@ -172,6 +180,7 @@
         val rv = darkContext.runAndTranslate {
             Switch(
                 checked = true,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     checkedThumbColor = ColorProvider(day = Color.Blue, night = Color.Red),
@@ -195,6 +204,7 @@
         val rv = lightContext.runAndTranslate {
             Switch(
                 checked = false,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     thumbColor = R.color.my_switch_thumb_colors,
@@ -213,6 +223,7 @@
         val rv = lightContext.runAndTranslate {
             Switch(
                 checked = true,
+                onCheckedChange = null,
                 text = "Switch",
                 colors = SwitchColors(
                     thumbColor = R.color.my_switch_thumb_colors,
@@ -226,15 +237,43 @@
         assertThat(switchRoot.trackImageView).hasColorFilter("#22040040")
     }
 
+    @Test
+    fun canTranslateSwitch_onCheckedChange_null() = fakeCoroutineScope.runBlockingTest {
+        val rv = context.runAndTranslate {
+            Switch(
+                checked = true,
+                onCheckedChange = null,
+                text = "Switch",
+            )
+        }
+
+        val switchRoot = assertIs<ViewGroup>(context.applyRemoteViews(rv))
+        assertThat(switchRoot.hasOnClickListeners()).isFalse()
+    }
+
+    @Test
+    fun canTranslateSwitch_onCheckedChange_withAction() = fakeCoroutineScope.runBlockingTest {
+        val rv = context.runAndTranslate {
+            Switch(
+                checked = true,
+                onCheckedChange = actionRunCallback<ActionCallback>(),
+                text = "Switch",
+            )
+        }
+
+        val switchRoot = assertIs<ViewGroup>(context.applyRemoteViews(rv))
+        assertThat(switchRoot.hasOnClickListeners()).isTrue()
+    }
+
     private val ViewGroup.thumbImageView: ImageView?
         get() = findView {
             shadowOf(it.drawable).createdFromResId ==
-                androidx.glance.appwidget.R.drawable.switch_thumb_material
+                androidx.glance.appwidget.R.drawable.switch_thumb_animated
         }
 
     private val ViewGroup.trackImageView: ImageView?
         get() = findView {
             shadowOf(it.drawable).createdFromResId ==
-                androidx.glance.appwidget.R.drawable.switch_track_material
+                androidx.glance.appwidget.R.drawable.switch_track
         }
 }
\ No newline at end of file
diff --git a/glance/glance-wear/api/current.txt b/glance/glance-wear/api/current.txt
index d1bb2da..66d8ba9 100644
--- a/glance/glance-wear/api/current.txt
+++ b/glance/glance-wear/api/current.txt
@@ -10,17 +10,48 @@
     method public static androidx.glance.GlanceModifier border(androidx.glance.GlanceModifier, @DimenRes int width, androidx.glance.unit.ColorProvider color);
   }
 
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> getLocalTimeInterval();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> LocalTimeInterval;
+  }
+
   public abstract class GlanceTileService extends androidx.wear.tiles.TileService {
     ctor public GlanceTileService();
     method @androidx.compose.runtime.Composable public abstract void Content();
+    method public androidx.glance.wear.TimelineMode getTimelineMode();
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> onResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
     method public void onStart(android.content.Intent? intent, int startId);
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> onTileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    property public androidx.glance.wear.TimelineMode timelineMode;
   }
 
   public final class NormalizeCompositionTreeKt {
   }
 
+  public final class TimeInterval {
+    ctor public TimeInterval(optional java.time.Instant start, optional java.time.Instant end);
+    method public java.time.Instant component1();
+    method public java.time.Instant component2();
+    method public androidx.glance.wear.TimeInterval copy(java.time.Instant start, java.time.Instant end);
+    method public java.time.Instant getEnd();
+    method public java.time.Instant getStart();
+    property public final java.time.Instant end;
+    property public final java.time.Instant start;
+  }
+
+  public sealed interface TimelineMode {
+  }
+
+  public static final class TimelineMode.SingleEntry implements androidx.glance.wear.TimelineMode {
+    field public static final androidx.glance.wear.TimelineMode.SingleEntry INSTANCE;
+  }
+
+  public static final class TimelineMode.TimeBoundEntries implements androidx.glance.wear.TimelineMode {
+    ctor public TimelineMode.TimeBoundEntries(java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals);
+    method public java.util.Set<androidx.glance.wear.TimeInterval> getTimeIntervals();
+    property public final java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals;
+  }
+
   public final class WearCompositionTranslatorKt {
   }
 
diff --git a/glance/glance-wear/api/public_plus_experimental_current.txt b/glance/glance-wear/api/public_plus_experimental_current.txt
index d1bb2da..66d8ba9 100644
--- a/glance/glance-wear/api/public_plus_experimental_current.txt
+++ b/glance/glance-wear/api/public_plus_experimental_current.txt
@@ -10,17 +10,48 @@
     method public static androidx.glance.GlanceModifier border(androidx.glance.GlanceModifier, @DimenRes int width, androidx.glance.unit.ColorProvider color);
   }
 
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> getLocalTimeInterval();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> LocalTimeInterval;
+  }
+
   public abstract class GlanceTileService extends androidx.wear.tiles.TileService {
     ctor public GlanceTileService();
     method @androidx.compose.runtime.Composable public abstract void Content();
+    method public androidx.glance.wear.TimelineMode getTimelineMode();
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> onResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
     method public void onStart(android.content.Intent? intent, int startId);
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> onTileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    property public androidx.glance.wear.TimelineMode timelineMode;
   }
 
   public final class NormalizeCompositionTreeKt {
   }
 
+  public final class TimeInterval {
+    ctor public TimeInterval(optional java.time.Instant start, optional java.time.Instant end);
+    method public java.time.Instant component1();
+    method public java.time.Instant component2();
+    method public androidx.glance.wear.TimeInterval copy(java.time.Instant start, java.time.Instant end);
+    method public java.time.Instant getEnd();
+    method public java.time.Instant getStart();
+    property public final java.time.Instant end;
+    property public final java.time.Instant start;
+  }
+
+  public sealed interface TimelineMode {
+  }
+
+  public static final class TimelineMode.SingleEntry implements androidx.glance.wear.TimelineMode {
+    field public static final androidx.glance.wear.TimelineMode.SingleEntry INSTANCE;
+  }
+
+  public static final class TimelineMode.TimeBoundEntries implements androidx.glance.wear.TimelineMode {
+    ctor public TimelineMode.TimeBoundEntries(java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals);
+    method public java.util.Set<androidx.glance.wear.TimeInterval> getTimeIntervals();
+    property public final java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals;
+  }
+
   public final class WearCompositionTranslatorKt {
   }
 
diff --git a/glance/glance-wear/api/restricted_current.txt b/glance/glance-wear/api/restricted_current.txt
index d1bb2da..66d8ba9 100644
--- a/glance/glance-wear/api/restricted_current.txt
+++ b/glance/glance-wear/api/restricted_current.txt
@@ -10,17 +10,48 @@
     method public static androidx.glance.GlanceModifier border(androidx.glance.GlanceModifier, @DimenRes int width, androidx.glance.unit.ColorProvider color);
   }
 
+  public final class CompositionLocalsKt {
+    method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> getLocalTimeInterval();
+    property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.glance.wear.TimeInterval> LocalTimeInterval;
+  }
+
   public abstract class GlanceTileService extends androidx.wear.tiles.TileService {
     ctor public GlanceTileService();
     method @androidx.compose.runtime.Composable public abstract void Content();
+    method public androidx.glance.wear.TimelineMode getTimelineMode();
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> onResourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
     method public void onStart(android.content.Intent? intent, int startId);
     method protected final com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> onTileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+    property public androidx.glance.wear.TimelineMode timelineMode;
   }
 
   public final class NormalizeCompositionTreeKt {
   }
 
+  public final class TimeInterval {
+    ctor public TimeInterval(optional java.time.Instant start, optional java.time.Instant end);
+    method public java.time.Instant component1();
+    method public java.time.Instant component2();
+    method public androidx.glance.wear.TimeInterval copy(java.time.Instant start, java.time.Instant end);
+    method public java.time.Instant getEnd();
+    method public java.time.Instant getStart();
+    property public final java.time.Instant end;
+    property public final java.time.Instant start;
+  }
+
+  public sealed interface TimelineMode {
+  }
+
+  public static final class TimelineMode.SingleEntry implements androidx.glance.wear.TimelineMode {
+    field public static final androidx.glance.wear.TimelineMode.SingleEntry INSTANCE;
+  }
+
+  public static final class TimelineMode.TimeBoundEntries implements androidx.glance.wear.TimelineMode {
+    ctor public TimelineMode.TimeBoundEntries(java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals);
+    method public java.util.Set<androidx.glance.wear.TimeInterval> getTimeIntervals();
+    property public final java.util.Set<androidx.glance.wear.TimeInterval> timeIntervals;
+  }
+
   public final class WearCompositionTranslatorKt {
   }
 
diff --git a/glance/glance-wear/build.gradle b/glance/glance-wear/build.gradle
index eb1fdf2..0fc530b 100644
--- a/glance/glance-wear/build.gradle
+++ b/glance/glance-wear/build.gradle
@@ -44,6 +44,7 @@
     implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
     implementation "androidx.lifecycle:lifecycle-service:2.3.1"
 
+    testImplementation(project(":core:core-ktx"))
     testImplementation(libs.testCore)
     testImplementation(libs.testRules)
     testImplementation(libs.testRunner)
@@ -59,6 +60,7 @@
     testImplementation("androidx.wear.tiles:tiles-renderer:1.0.0-alpha12")
     testImplementation("androidx.wear.tiles:tiles-testing:1.0.0-alpha12")
 
+    androidTestImplementation(project(":core:core-ktx"))
     androidTestImplementation("androidx.core:core:1.7.0")
     androidTestImplementation(project(":test:screenshot:screenshot"))
     androidTestImplementation("androidx.wear.tiles:tiles-renderer:1.0.0-alpha12")
diff --git a/glance/glance-wear/src/androidAndroidTest/kotlin/androidx/glance/wear/ScreenshotTests.kt b/glance/glance-wear/src/androidAndroidTest/kotlin/androidx/glance/wear/ScreenshotTests.kt
index e9bda4b..9552fab 100644
--- a/glance/glance-wear/src/androidAndroidTest/kotlin/androidx/glance/wear/ScreenshotTests.kt
+++ b/glance/glance-wear/src/androidAndroidTest/kotlin/androidx/glance/wear/ScreenshotTests.kt
@@ -29,6 +29,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.core.content.ContextCompat
+import androidx.core.graphics.drawable.toBitmap
 import androidx.glance.Applier
 import androidx.glance.GlanceModifier
 import androidx.glance.Image
@@ -81,10 +82,12 @@
     var screenshotRule = AndroidXScreenshotTestRule("glance/glance-wear")
 
     private lateinit var fakeCoroutineScope: TestCoroutineScope
+    private lateinit var testBitmap: Bitmap
 
     @Before
     fun setUp() {
         fakeCoroutineScope = TestCoroutineScope()
+        testBitmap = getApplicationContext<Context>().getDrawable(R.drawable.oval)!!.toBitmap()
     }
 
     @Test
@@ -229,7 +232,7 @@
             )
             Spacer(modifier = GlanceModifier.height(10.dp))
             Image(
-                provider = ImageProvider(R.drawable.oval),
+                provider = ImageProvider(testBitmap),
                 contentDescription = "Oval-fit",
                 modifier = GlanceModifier.size(50.dp),
                 contentScale = ContentScale.Fit
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/CompositionLocals.kt
similarity index 68%
copy from compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
copy to glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/CompositionLocals.kt
index d721bff..99ca2cb 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListItemsProvider.kt
+++ b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/CompositionLocals.kt
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package androidx.compose.foundation.lazy
+package androidx.glance.wear
 
-import androidx.compose.foundation.lazy.layout.LazyLayoutItemsProvider
+import androidx.compose.runtime.staticCompositionLocalOf
 
-internal interface LazyListItemsProvider : LazyLayoutItemsProvider {
-    /** The list of indexes of the sticky header items */
-    val headerIndexes: List<Int>
-}
+/**
+ * Time interval of the glance tile UI being generated.
+ */
+public val LocalTimeInterval =
+    staticCompositionLocalOf<TimeInterval?> { error("No default time interval") }
\ No newline at end of file
diff --git a/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/GlanceTileService.kt b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/GlanceTileService.kt
index 07d72f0..cf6e35a 100644
--- a/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/GlanceTileService.kt
+++ b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/GlanceTileService.kt
@@ -22,6 +22,7 @@
 import androidx.compose.runtime.BroadcastFrameClock
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Composition
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Recomposer
 import androidx.glance.Applier
 import androidx.glance.layout.EmittableBox
@@ -96,25 +97,37 @@
         super.onStart(intent, startId)
     }
 
-    private suspend fun runComposition(): CompositionResult = coroutineScope {
-        val root = EmittableBox()
-        val applier = Applier(root)
-        val recomposer = Recomposer(currentCoroutineContext())
-        val composition = Composition(applier, recomposer)
+    private suspend fun runComposition(
+        timeInterval: TimeInterval? = null
+    ): CompositionResult =
+        coroutineScope {
+            val root = EmittableBox()
+            val applier = Applier(root)
+            val recomposer = Recomposer(currentCoroutineContext())
+            val composition = Composition(applier, recomposer)
 
-        composition.setContent { Content() }
+            composition.setContent {
+                CompositionLocalProvider(
+                    LocalTimeInterval provides timeInterval
+                ) { Content() }
+            }
 
-        launch { recomposer.runRecomposeAndApplyChanges() }
+            launch { recomposer.runRecomposeAndApplyChanges() }
 
-        recomposer.close()
-        recomposer.join()
+            recomposer.close()
+            recomposer.join()
 
-        normalizeCompositionTree(this@GlanceTileService, root)
+            normalizeCompositionTree(this@GlanceTileService, root)
 
-        translateTopLevelComposition(this@GlanceTileService, root)
-    }
+            translateTopLevelComposition(this@GlanceTileService, root)
+        }
 
-    /** Implement with the layout to use in your Tile. */
+    /**
+     * Defines the handling of timeline
+     */
+    public open val timelineMode: TimelineMode = TimelineMode.SingleEntry
+
+    /** Override this method to set the layout to use in your Tile. */
     @Composable
     public abstract fun Content()
 
@@ -127,21 +140,46 @@
     final override fun onTileRequest(
         requestParams: RequestBuilders.TileRequest
     ): ListenableFuture<TileBuilders.Tile> = coroutineScope.future {
-        val content = runComposition().layout
+        val timelineBuilders = TimelineBuilders.Timeline.Builder()
+        if (timelineMode === TimelineMode.SingleEntry) {
+            val content = runComposition().layout
+
+            timelineBuilders
+                .addTimelineEntry(
+                    TimelineBuilders.TimelineEntry.Builder()
+                        .setLayout(
+                            LayoutElementBuilders.Layout.Builder()
+                                .setRoot(content)
+                                .build()
+                        ).build()
+                )
+        } else { // timelineMode is TimelineMode.TimeBoundEntries
+            val timeIntervals = (timelineMode as TimelineMode.TimeBoundEntries).timeIntervals
+            timeIntervals.forEach {
+                val result = runComposition(it).layout
+
+                timelineBuilders
+                    .addTimelineEntry(
+                        TimelineBuilders.TimelineEntry.Builder()
+                            .setValidity(
+                                TimelineBuilders.TimeInterval.Builder()
+                                    .setStartMillis(it.start.toEpochMilli())
+                                    .setEndMillis(it.end.toEpochMilli())
+                                    .build()
+                            )
+                            .setLayout(
+                                LayoutElementBuilders.Layout.Builder()
+                                    .setRoot(result)
+                                    .build()
+                            ).build()
+                    )
+            }
+        }
 
         TileBuilders.Tile.Builder()
             .setResourcesVersion(ResourcesVersion)
-            .setTimeline(
-                TimelineBuilders.Timeline.Builder()
-                    .addTimelineEntry(
-                        TimelineBuilders.TimelineEntry.Builder()
-                            .setLayout(
-                                LayoutElementBuilders.Layout.Builder()
-                                    .setRoot(content)
-                                    .build()
-                            ).build()
-                    ).build()
-            ).build()
+            .setTimeline(timelineBuilders.build())
+            .build()
     }
 
     /**
@@ -153,7 +191,21 @@
     final override fun onResourcesRequest(
         requestParams: RequestBuilders.ResourcesRequest
     ): ListenableFuture<ResourceBuilders.Resources> = coroutineScope.future {
-        runComposition().resources.setVersion(ResourcesVersion).build()
+        var resourceBuilder: ResourceBuilders.Resources.Builder
+        if (timelineMode === TimelineMode.SingleEntry) {
+            resourceBuilder = runComposition().resources
+        } else {
+            timelineMode is TimelineMode.TimeBoundEntries
+            resourceBuilder = ResourceBuilders.Resources.Builder()
+            val timeIntervals = (timelineMode as TimelineMode.TimeBoundEntries).timeIntervals
+            timeIntervals.forEach {
+                val result = runComposition(it).resources
+                result.build().idToImageMapping.forEach { res ->
+                    resourceBuilder.addIdToImageMapping(res.key, res.value)
+                }
+            }
+        }
+        resourceBuilder.setVersion(ResourcesVersion).build()
     }
 
     @VisibleForTesting
diff --git a/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/TimelineMode.kt b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/TimelineMode.kt
new file mode 100644
index 0000000..4e92fa6
--- /dev/null
+++ b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/TimelineMode.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.glance.wear
+
+import java.time.Instant
+
+/**
+ * TimeInterval class defines a period from [start] to [end]
+ *
+ * @param start The start time of the time interval
+ * @param end The end time of the time interval
+ */
+public data class TimeInterval(
+    val start: Instant = Instant.ofEpochMilli(0),
+    val end: Instant = Instant.ofEpochMilli(Long.MAX_VALUE)
+) {
+    init {
+        require(end > start) {
+            "End time shall come after start time to form a valid interval"
+        }
+    }
+}
+
+public sealed interface TimelineMode {
+    /**
+     * The [GlanceTileService] provides a single UI.
+     * The layout is fixed, and only the information inside the layout changes.
+     */
+    public object SingleEntry : TimelineMode {
+        public override fun toString(): String = "TimelineMode: SingleEntry"
+    }
+
+    /**
+     * The [GlanceTileService] provides a UI for a fixed set of time intervals
+     *
+     * @param timeIntervals Used to build the list of time intervals, the list must not be empty.
+     */
+    public class TimeBoundEntries(val timeIntervals: Set<TimeInterval>) : TimelineMode {
+        init {
+            require(timeIntervals.isNotEmpty()) { "The set of time intervals cannot be empty" }
+        }
+
+        public override fun equals(other: Any?): Boolean {
+            if (this === other) return true
+            if (javaClass != other?.javaClass) return false
+
+            other as TimeBoundEntries
+
+            if (timeIntervals != other.timeIntervals) return false
+
+            return true
+        }
+
+        public override fun hashCode(): Int = timeIntervals.hashCode()
+
+        public override fun toString(): String =
+            "TimelineMode.TimeBoundEntries(timeIntervals=$timeIntervals)"
+    }
+}
\ No newline at end of file
diff --git a/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/WearCompositionTranslator.kt b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/WearCompositionTranslator.kt
index f78e8a6..a312473 100644
--- a/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/WearCompositionTranslator.kt
+++ b/glance/glance-wear/src/androidMain/kotlin/androidx/glance/wear/WearCompositionTranslator.kt
@@ -17,12 +17,14 @@
 package androidx.glance.wear
 
 import android.content.Context
+import android.graphics.Bitmap
 import android.view.View
 import android.view.ViewGroup
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.unit.dp
 import androidx.glance.AndroidResourceImageProvider
 import androidx.glance.BackgroundModifier
+import androidx.glance.BitmapImageProvider
 import androidx.glance.Emittable
 import androidx.glance.EmittableButton
 import androidx.glance.EmittableImage
@@ -86,6 +88,8 @@
 import androidx.wear.tiles.LayoutElementBuilders.VerticalAlignment
 import androidx.wear.tiles.ModifiersBuilders
 import androidx.wear.tiles.ResourceBuilders
+import java.io.ByteArrayOutputStream
+import java.util.Arrays
 
 @VerticalAlignment
 private fun Alignment.Vertical.toProto(): Int =
@@ -133,6 +137,7 @@
     else -> error("Unsupported color provider: $this")
 }
 
+// TODO: handle parameters
 private fun LaunchActivityAction.toProto(context: Context): ActionBuilders.LaunchAction =
     ActionBuilders.LaunchAction.Builder()
         .setAndroidActivity(
@@ -397,17 +402,40 @@
     resourceBuilder: ResourceBuilders.Resources.Builder,
     element: EmittableImage
 ): LayoutElementBuilders.LayoutElement {
-
-    val resId = (element.provider as AndroidResourceImageProvider).resId
-    val mappedResId = "android_$resId"
-    resourceBuilder.addIdToImageMapping(
-        mappedResId,
-        ResourceBuilders.ImageResource.Builder().setAndroidResourceByResId(
-            ResourceBuilders.AndroidImageResourceByResId.Builder()
-                .setResourceId(resId)
-                .build()
-        ).build()
-    )
+    var mappedResId: String
+    when (element.provider) {
+        is AndroidResourceImageProvider -> {
+            val resId = (element.provider as AndroidResourceImageProvider).resId
+            mappedResId = "android_$resId"
+            resourceBuilder.addIdToImageMapping(
+                mappedResId,
+                ResourceBuilders.ImageResource.Builder().setAndroidResourceByResId(
+                    ResourceBuilders.AndroidImageResourceByResId.Builder()
+                        .setResourceId(resId)
+                        .build()
+                ).build()
+            )
+        }
+        is BitmapImageProvider -> {
+            val bitmap = (element.provider as BitmapImageProvider).bitmap
+            val buffer = ByteArrayOutputStream().apply {
+                bitmap.compress(Bitmap.CompressFormat.PNG, 100, this)
+            }.toByteArray()
+            mappedResId = "android_${Arrays.hashCode(buffer)}"
+            resourceBuilder.addIdToImageMapping(
+                mappedResId,
+                ResourceBuilders.ImageResource.Builder().setInlineResource(
+                    ResourceBuilders.InlineImageResource.Builder()
+                        .setWidthPx(bitmap.width)
+                        .setHeightPx(bitmap.height)
+                        .setData(buffer)
+                        .build()
+                ).build()
+            )
+        }
+        else ->
+            throw IllegalArgumentException("An unsupported ImageProvider type was used")
+    }
 
     val imageBuilder = LayoutElementBuilders.Image.Builder()
         .setWidth(element.modifier.getWidth(context).toImageDimension())
diff --git a/glance/glance-wear/src/test/kotlin/androidx/glance/wear/GlanceTileServiceTest.kt b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/GlanceTileServiceTest.kt
index fadf753..7133c06 100644
--- a/glance/glance-wear/src/test/kotlin/androidx/glance/wear/GlanceTileServiceTest.kt
+++ b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/GlanceTileServiceTest.kt
@@ -18,9 +18,17 @@
 
 import android.os.Looper
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.dp
+import androidx.glance.GlanceModifier
+import androidx.glance.Image
+import androidx.glance.ImageProvider
+import androidx.glance.layout.ContentScale
+import androidx.glance.layout.size
 import androidx.glance.text.Text
+import androidx.glance.wear.test.R
 import androidx.wear.tiles.LayoutElementBuilders
 import androidx.wear.tiles.RequestBuilders
+import androidx.wear.tiles.TimelineBuilders
 import androidx.wear.tiles.testing.TestTileClient
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineDispatcher
@@ -33,6 +41,7 @@
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
 import org.robolectric.Shadows.shadowOf
+import java.time.Instant
 import kotlin.test.assertIs
 
 @OptIn(ExperimentalCoroutinesApi::class, ExperimentalStdlibApi::class)
@@ -41,23 +50,30 @@
     private lateinit var fakeCoroutineScope: TestCoroutineScope
     private lateinit var tileService: TestGlanceTileService
     private lateinit var tileServiceClient: TestTileClient<GlanceTileService>
+    private lateinit var tileServiceWithTimeline: TestGlanceTileServiceWithTimeline
+    private lateinit var tileServiceClientWithTimeline: TestTileClient<GlanceTileService>
 
     @Before
     fun setUp() {
         fakeCoroutineScope = TestCoroutineScope()
+
         tileService = TestGlanceTileService()
         tileServiceClient = TestTileClient(
             tileService,
             fakeCoroutineScope,
             fakeCoroutineScope.coroutineContext[CoroutineDispatcher]!!
         )
+
+        tileServiceWithTimeline = TestGlanceTileServiceWithTimeline()
+        tileServiceClientWithTimeline = TestTileClient(
+            tileServiceWithTimeline,
+            fakeCoroutineScope,
+            fakeCoroutineScope.coroutineContext[CoroutineDispatcher]!!
+        )
     }
 
     @Test
     fun tileProviderReturnsTile() = fakeCoroutineScope.runBlockingTest {
-        // Add the composition to the service.
-        tileService.actualContent = { Text("Hello World!") }
-
         // Request is currently un-used, provide an empty one.
         val tileRequest = RequestBuilders.TileRequest.Builder().build()
 
@@ -79,16 +95,62 @@
 
         // It always emits a box as the root-level layout.
         val box = assertIs<LayoutElementBuilders.Box>(entry.layout!!.root!!)
-        assertThat(box.contents).hasSize(1)
+        assertThat(box.contents).hasSize(2)
         val text = assertIs<LayoutElementBuilders.Text>(box.contents[0])
 
         assertThat(text.text!!.value).isEqualTo("Hello World!")
     }
 
     @Test
+    fun tileProviderReturnsTimelineTile() = fakeCoroutineScope.runBlockingTest {
+        // Request is currently un-used, provide an empty one.
+        val tileRequest = RequestBuilders.TileRequest.Builder().build()
+
+        // Requests need to be split; we need to allow Robolectric to schedule the service calls on
+        // the main looper, so we can't just do requestTile().await().
+        val tileFuture = tileServiceClientWithTimeline.requestTile(tileRequest)
+        shadowOf(Looper.getMainLooper()).idle()
+        val tile = tileFuture.await()
+
+        // Just uses a simple resource version for now.
+        assertThat(tile.resourcesVersion).isEqualTo(GlanceTileService.ResourcesVersion)
+
+        // No freshness interval (for now)
+        assertThat(tile.freshnessIntervalMillis).isEqualTo(0)
+
+        assertThat(tile.timeline!!.timelineEntries).hasSize(4)
+
+        checkTimelineEntry(
+            tile.timeline!!.timelineEntries[0],
+            0,
+            Long.MAX_VALUE,
+            "No event"
+        )
+
+        checkTimelineEntry(
+            tile.timeline!!.timelineEntries[1],
+            time1.toEpochMilli(),
+            time2.toEpochMilli(),
+            "Coffee"
+        )
+
+        checkTimelineEntry(
+            tile.timeline!!.timelineEntries[2],
+            time2.toEpochMilli(),
+            time3.toEpochMilli(),
+            "Work"
+        )
+
+        checkTimelineEntry(
+            tile.timeline!!.timelineEntries[3],
+            time4.toEpochMilli(),
+            Long.MAX_VALUE,
+            "Dinner"
+        )
+    }
+
+    @Test
     fun tileProviderReturnsResources() = fakeCoroutineScope.runBlockingTest {
-        // The service doesn't use resources right now, but it must correctly respond to
-        // onResourcesRequest. Just ensure that the version is set correctly.
         val resourcesRequest = RequestBuilders.ResourcesRequest.Builder().build()
 
         val resourcesFuture = tileServiceClient.requestResources(resourcesRequest)
@@ -96,14 +158,91 @@
         val resources = resourcesFuture.await()
 
         assertThat(resources.version).isEqualTo(GlanceTileService.ResourcesVersion)
+        assertThat(resources.idToImageMapping.size).isEqualTo(1)
+        assertThat(resources.idToImageMapping.containsKey("android_" + R.drawable.oval)).isTrue()
+    }
+
+    @Test
+    fun tileProviderReturnsTimelineResources() = fakeCoroutineScope.runBlockingTest {
+        val resourcesRequest = RequestBuilders.ResourcesRequest.Builder().build()
+
+        val resourcesFuture = tileServiceClientWithTimeline.requestResources(resourcesRequest)
+        shadowOf(Looper.getMainLooper()).idle()
+        val resources = resourcesFuture.await()
+
+        assertThat(resources.version).isEqualTo(GlanceTileService.ResourcesVersion)
+        assertThat(resources.idToImageMapping.size).isEqualTo(2)
+        assertThat(resources.idToImageMapping.containsKey("android_" + R.drawable.oval)).isTrue()
+        assertThat(
+            resources.idToImageMapping.containsKey("android_" + R.drawable.ic_launcher_background)
+        ).isTrue()
+    }
+
+    private fun checkTimelineEntry(
+        entry: TimelineBuilders.TimelineEntry,
+        startMillis: Long,
+        endMillis: Long,
+        textValue: String
+    ) {
+        assertThat(entry.validity!!.startMillis).isEqualTo(startMillis)
+        assertThat(entry.validity!!.endMillis).isEqualTo(endMillis)
+        var box = assertIs<LayoutElementBuilders.Box>(entry.layout!!.root!!)
+        var text = assertIs<LayoutElementBuilders.Text>(box.contents[0])
+        assertThat(text.text!!.value).isEqualTo(textValue)
     }
 
     private inner class TestGlanceTileService : GlanceTileService() {
-        var actualContent: @Composable () -> Unit = {}
-
         @Composable
         override fun Content() {
-            actualContent()
+            Text("Hello World!")
+            Image(
+                provider = ImageProvider(R.drawable.oval),
+                contentDescription = "Oval",
+                modifier = GlanceModifier.size(40.dp),
+                contentScale = ContentScale.FillBounds
+            )
         }
     }
+
+     private inner class TestGlanceTileServiceWithTimeline : GlanceTileService() {
+         override val timelineMode = testTimelineMode
+
+         @Composable
+         override fun Content() {
+             when (LocalTimeInterval.current) {
+                 testTimelineMode.timeIntervals.elementAt(0) -> { Text("No event") }
+                 testTimelineMode.timeIntervals.elementAt(1) -> {
+                     Text("Coffee")
+                     Image(
+                         provider = ImageProvider(R.drawable.oval),
+                         contentDescription = "Oval",
+                         modifier = GlanceModifier.size(40.dp),
+                         contentScale = ContentScale.FillBounds
+                     )
+                 }
+                 testTimelineMode.timeIntervals.elementAt(2) -> {
+                     Text("Work")
+                     Image(
+                         provider = ImageProvider(R.drawable.ic_launcher_background),
+                         contentDescription = "Icon",
+                         modifier = GlanceModifier.size(40.dp),
+                     )
+                 }
+                 testTimelineMode.timeIntervals.elementAt(3) -> { Text("Dinner") }
+             }
+         }
+     }
+
+    private companion object {
+        private val time1 = Instant.parse("2021-11-12T13:15:30.00Z")
+        private val time2 = Instant.parse("2021-11-12T13:45:30.00Z")
+        private val time3 = Instant.parse("2021-11-12T17:45:30.00Z")
+        private val time4 = Instant.parse("2021-11-12T18:30:30.00Z")
+        val testTimelineMode = TimelineMode.TimeBoundEntries(setOf(
+            TimeInterval(),
+            TimeInterval(time1, time2),
+            TimeInterval(time2, time3),
+            TimeInterval(time4)
+        ))
+    }
 }
\ No newline at end of file
diff --git a/glance/glance-wear/src/test/kotlin/androidx/glance/wear/TimelineModeTest.kt b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/TimelineModeTest.kt
new file mode 100644
index 0000000..d044d94
--- /dev/null
+++ b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/TimelineModeTest.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.glance.wear
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import java.time.Instant
+
+class TimelineModeTest {
+
+    @Test
+    fun timeboundEntriesTest() {
+        val time1 = Instant.parse("2021-11-12T13:15:30.00Z")
+        val time2 = Instant.parse("2021-11-12T13:45:30.00Z")
+        val time3 = Instant.parse("2021-11-12T17:45:30.00Z")
+        val time4 = Instant.parse("2021-11-12T18:30:30.00Z")
+
+        val timeBoundEntries = TimelineMode.TimeBoundEntries(setOf(
+            TimeInterval(),
+            TimeInterval(time1, time2),
+            TimeInterval(time2, time3),
+            TimeInterval(time4)
+        ))
+        val intervals = timeBoundEntries.timeIntervals
+
+        assertThat(intervals.size).isEqualTo(4)
+
+        assertThat(intervals.elementAt(0).start.toEpochMilli()).isEqualTo(0)
+        assertThat(intervals.elementAt(0).end.toEpochMilli()).isEqualTo(Long.MAX_VALUE)
+
+        assertThat(intervals.elementAt(1).start).isEqualTo(time1)
+        assertThat(intervals.elementAt(1).end).isEqualTo(time2)
+
+        assertThat(intervals.elementAt(2).start).isEqualTo(time2)
+        assertThat(intervals.elementAt(2).end).isEqualTo(time3)
+
+        assertThat(intervals.elementAt(3).start).isEqualTo(time4)
+        assertThat(intervals.elementAt(3).end.toEpochMilli()).isEqualTo(Long.MAX_VALUE)
+    }
+}
\ No newline at end of file
diff --git a/glance/glance-wear/src/test/kotlin/androidx/glance/wear/WearCompositionTranslatorTest.kt b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/WearCompositionTranslatorTest.kt
index c133aaa..74efee7 100644
--- a/glance/glance-wear/src/test/kotlin/androidx/glance/wear/WearCompositionTranslatorTest.kt
+++ b/glance/glance-wear/src/test/kotlin/androidx/glance/wear/WearCompositionTranslatorTest.kt
@@ -18,11 +18,13 @@
 
 import android.app.Activity
 import android.content.Context
+import android.graphics.Bitmap
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
+import androidx.core.graphics.drawable.toBitmap
 import androidx.glance.Button
 import androidx.glance.GlanceModifier
 import androidx.glance.Image
@@ -72,6 +74,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
+import java.io.ByteArrayOutputStream
+import java.util.Arrays
 import kotlin.test.assertIs
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -134,8 +138,10 @@
     @Test
     fun canTranslatePaddingModifier() = fakeCoroutineScope.runBlockingTest {
         val content = runAndTranslate {
-            Box(modifier =
-                GlanceModifier.padding(start = 1.dp, top = 2.dp, end = 3.dp, bottom = 4.dp)) {}
+            Box(
+                modifier =
+                GlanceModifier.padding(start = 1.dp, top = 2.dp, end = 3.dp, bottom = 4.dp)
+            ) {}
         }.layout
 
         val innerBox =
@@ -151,14 +157,18 @@
     @Test
     fun canTranslateBorderModifier() = fakeCoroutineScope.runBlockingTest {
         val content = runAndTranslate {
-            Box(modifier = GlanceModifier.border(
+            Box(
+                modifier = GlanceModifier.border(
                     width = 3.dp,
                     color = ColorProvider(color = Color.Blue)
-            )) {}
-            Box(modifier = GlanceModifier.border(
+                )
+            ) {}
+            Box(
+                modifier = GlanceModifier.border(
                     width = R.dimen.dimension1,
-                color = ColorProvider(color = Color.Red)
-            )) {}
+                    color = ColorProvider(color = Color.Red)
+                )
+            ) {}
         }.layout
 
         val innerBox1 =
@@ -556,35 +566,61 @@
 
     @Test
     fun canTranslateImage() = fakeCoroutineScope.runBlockingTest {
+        val context = getApplicationContext<Context>()
+        val bitmap = context.getDrawable(R.drawable.oval)!!.toBitmap()
         val compositionResult = runAndTranslate {
-          Image(
-              provider = ImageProvider(R.drawable.oval),
-              contentDescription = "Oval",
-              modifier = GlanceModifier.width(R.dimen.dimension1).height(R.dimen.dimension2),
-              contentScale = ContentScale.FillBounds
-          )
+            Image(
+                provider = ImageProvider(R.drawable.oval),
+                contentDescription = "Oval",
+                modifier = GlanceModifier.width(R.dimen.dimension1).height(R.dimen.dimension2),
+                contentScale = ContentScale.FillBounds
+            )
+            Image(
+                provider = ImageProvider(bitmap),
+                contentDescription = "OvalBitmap",
+                modifier = GlanceModifier.width(R.dimen.dimension1).height(R.dimen.dimension2),
+                contentScale = ContentScale.Crop
+            )
         }
         val content = compositionResult.layout
         val resources = compositionResult.resources
 
-        val image = (content as LayoutElementBuilders.Box).contents[0] as
+        val image1 = (content as LayoutElementBuilders.Box).contents[0] as
             LayoutElementBuilders.Image
 
-        val context = getApplicationContext<Context>()
-        assertThat((image.width as DimensionBuilders.DpProp).value).isEqualTo(
+        assertThat((image1.width as DimensionBuilders.DpProp).value).isEqualTo(
             context.resources.getDimension(R.dimen.dimension1)
         )
-        assertThat((image.height as DimensionBuilders.DpProp).value).isEqualTo(
-                context.resources.getDimension(R.dimen.dimension2)
+        assertThat((image1.height as DimensionBuilders.DpProp).value).isEqualTo(
+            context.resources.getDimension(R.dimen.dimension2)
         )
-        assertThat(image.contentScaleMode!!.value).isEqualTo(
+        assertThat(image1.contentScaleMode!!.value).isEqualTo(
             LayoutElementBuilders.CONTENT_SCALE_MODE_FILL_BOUNDS
         )
-        assertThat(image.resourceId!!.value).isEqualTo("android_" + R.drawable.oval)
+        val mappedId1 = "android_" + R.drawable.oval
+        assertThat(image1.resourceId!!.value).isEqualTo(mappedId1)
 
-        assertThat(resources.build().idToImageMapping.containsKey(R.drawable.oval.toString()))
+        assertThat(image1.modifiers!!.semantics!!.contentDescription).isEqualTo("Oval")
 
-        assertThat(image.modifiers!!.semantics!!.contentDescription).isEqualTo("Oval")
+        val image2 = content.contents[1] as LayoutElementBuilders.Image
+        assertThat(image2.contentScaleMode!!.value).isEqualTo(
+            LayoutElementBuilders.CONTENT_SCALE_MODE_CROP
+        )
+
+        val buffer = ByteArrayOutputStream().apply {
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, this) }
+            .toByteArray()
+        val mappedId2 = "android_" + Arrays.hashCode(buffer)
+        assertThat(image2.resourceId!!.value).isEqualTo(mappedId2)
+        assertThat(image2.modifiers!!.semantics!!.contentDescription).isEqualTo("OvalBitmap")
+
+        val idToImageMap = resources.build().idToImageMapping
+        assertThat(idToImageMap.containsKey(mappedId1)).isTrue()
+        assertThat(idToImageMap[mappedId1]!!.androidResourceByResId).isNotNull()
+        assertThat(idToImageMap[mappedId1]!!.inlineResource).isNull()
+        assertThat(idToImageMap.containsKey(mappedId2)).isTrue()
+        assertThat(idToImageMap[mappedId2]!!.inlineResource).isNotNull()
+        assertThat(idToImageMap[mappedId2]!!.androidResourceByResId).isNull()
     }
 
     @Test
diff --git a/glance/glance-wear/src/test/res/drawable/ic_launcher_background.xml b/glance/glance-wear/src/test/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..ca3826a
--- /dev/null
+++ b/glance/glance-wear/src/test/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+    android:height="108dp"
+    android:width="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#3DDC84"
+          android:pathData="M0,0h108v108h-108z"/>
+    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
+          android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+</vector>
diff --git a/glance/glance/api/current.txt b/glance/glance/api/current.txt
index 56e1253..5955625 100644
--- a/glance/glance/api/current.txt
+++ b/glance/glance/api/current.txt
@@ -117,12 +117,13 @@
     method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
     method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
     method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
   }
 
   public final class LaunchActivityActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName);
-    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity);
-    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity();
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity(optional androidx.glance.action.ActionParameters parameters);
   }
 
   public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
@@ -276,15 +277,15 @@
 
 package androidx.glance.state {
 
-  public final class GlanceState {
-    method public suspend <T> Object? getValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.coroutines.Continuation<? super T> p);
-    method public suspend <T> Object? updateValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateBlock, kotlin.coroutines.Continuation<? super T> p);
-    field public static final androidx.glance.state.GlanceState INSTANCE;
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
   }
 
-  public interface GlanceStateDefinition<T> {
-    method public suspend <T> Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>> p);
     method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
   }
 
 }
diff --git a/glance/glance/api/public_plus_experimental_current.txt b/glance/glance/api/public_plus_experimental_current.txt
index 56e1253..5955625 100644
--- a/glance/glance/api/public_plus_experimental_current.txt
+++ b/glance/glance/api/public_plus_experimental_current.txt
@@ -117,12 +117,13 @@
     method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
     method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
     method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
   }
 
   public final class LaunchActivityActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName);
-    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity);
-    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity();
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity(optional androidx.glance.action.ActionParameters parameters);
   }
 
   public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
@@ -276,15 +277,15 @@
 
 package androidx.glance.state {
 
-  public final class GlanceState {
-    method public suspend <T> Object? getValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.coroutines.Continuation<? super T> p);
-    method public suspend <T> Object? updateValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateBlock, kotlin.coroutines.Continuation<? super T> p);
-    field public static final androidx.glance.state.GlanceState INSTANCE;
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
   }
 
-  public interface GlanceStateDefinition<T> {
-    method public suspend <T> Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>> p);
     method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
   }
 
 }
diff --git a/glance/glance/api/restricted_current.txt b/glance/glance/api/restricted_current.txt
index 56e1253..5955625 100644
--- a/glance/glance/api/restricted_current.txt
+++ b/glance/glance/api/restricted_current.txt
@@ -117,12 +117,13 @@
     method public static androidx.glance.action.MutableActionParameters mutableActionParametersOf(androidx.glance.action.ActionParameters.Pair<?>... pairs);
     method public static androidx.glance.action.MutableActionParameters toMutableParameters(androidx.glance.action.ActionParameters);
     method public static androidx.glance.action.ActionParameters toParameters(androidx.glance.action.ActionParameters);
+    method public static <T> androidx.glance.action.ActionParameters.Key<T> toParametersKey(androidx.datastore.preferences.core.Preferences.Key<T>);
   }
 
   public final class LaunchActivityActionKt {
-    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName);
-    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity);
-    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity();
+    method public static androidx.glance.action.Action actionLaunchActivity(android.content.ComponentName componentName, optional androidx.glance.action.ActionParameters parameters);
+    method public static <T extends android.app.Activity> androidx.glance.action.Action actionLaunchActivity(Class<T> activity, optional androidx.glance.action.ActionParameters parameters);
+    method public static inline <reified T extends android.app.Activity> androidx.glance.action.Action! actionLaunchActivity(optional androidx.glance.action.ActionParameters parameters);
   }
 
   public final class MutableActionParameters extends androidx.glance.action.ActionParameters {
@@ -276,15 +277,15 @@
 
 package androidx.glance.state {
 
-  public final class GlanceState {
-    method public suspend <T> Object? getValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.coroutines.Continuation<? super T> p);
-    method public suspend <T> Object? updateValue(android.content.Context context, androidx.glance.state.GlanceStateDefinition<T> definition, String fileName, kotlin.jvm.functions.Function2<? super T,? super kotlin.coroutines.Continuation<? super T>,?> updateBlock, kotlin.coroutines.Continuation<? super T> p);
-    field public static final androidx.glance.state.GlanceState INSTANCE;
+  public interface GlanceStateDefinition<T> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+    method public java.io.File getLocation(android.content.Context context, String fileKey);
   }
 
-  public interface GlanceStateDefinition<T> {
-    method public suspend <T> Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<T>> p);
+  public final class PreferencesGlanceStateDefinition implements androidx.glance.state.GlanceStateDefinition<androidx.datastore.preferences.core.Preferences> {
+    method public suspend Object? getDataStore(android.content.Context context, String fileKey, kotlin.coroutines.Continuation<? super androidx.datastore.core.DataStore<androidx.datastore.preferences.core.Preferences>> p);
     method public java.io.File getLocation(android.content.Context context, String fileKey);
+    field public static final androidx.glance.state.PreferencesGlanceStateDefinition INSTANCE;
   }
 
 }
diff --git a/glance/glance/build.gradle b/glance/glance/build.gradle
index 1bd9e3b..1933c14 100644
--- a/glance/glance/build.gradle
+++ b/glance/glance/build.gradle
@@ -36,6 +36,8 @@
     api("androidx.compose.ui:ui-graphics:1.1.0-beta01")
     api("androidx.compose.ui:ui-unit:1.1.0-beta01")
     api("androidx.datastore:datastore-core:1.0.0")
+    api("androidx.datastore:datastore-preferences-core:1.0.0")
+    api("androidx.datastore:datastore-preferences:1.0.0")
 
     implementation("androidx.annotation:annotation:1.1.0")
     implementation(libs.kotlinStdlib)
@@ -64,7 +66,6 @@
 androidx {
     name = "Glance Core Library"
     type = LibraryType.PUBLISHED_LIBRARY
-    publish = Publish.SNAPSHOT_ONLY
     mavenGroup = LibraryGroups.GLANCE
     inceptionYear = "2021"
     description = "Glance allows developers to build layouts for remote surfaces using a Jetpack " +
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt b/glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt
index 40ecf1d..eb02d71 100644
--- a/glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt
+++ b/glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt
@@ -16,6 +16,7 @@
 
 package androidx.glance.action
 
+import androidx.datastore.preferences.core.Preferences
 import java.util.Collections
 
 /**
@@ -197,3 +198,7 @@
  * @return a copy of this Parameters
  */
 public fun ActionParameters.toParameters(): ActionParameters = toMutableParameters()
+
+/** Creates an action key from a preferences key. */
+public fun <T : Any> Preferences.Key<T>.toParametersKey(): ActionParameters.Key<T> =
+    ActionParameters.Key(name)
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/LaunchActivityAction.kt b/glance/glance/src/androidMain/kotlin/androidx/glance/action/LaunchActivityAction.kt
index 387893d..ff1e90b 100644
--- a/glance/glance/src/androidMain/kotlin/androidx/glance/action/LaunchActivityAction.kt
+++ b/glance/glance/src/androidMain/kotlin/androidx/glance/action/LaunchActivityAction.kt
@@ -22,39 +22,55 @@
 
 /** @suppress */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public interface LaunchActivityAction : Action
+public interface LaunchActivityAction : Action {
+    abstract val parameters: ActionParameters
+}
 
 /** @suppress */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class LaunchActivityComponentAction(
-    public val componentName: ComponentName
+    public val componentName: ComponentName,
+    public override val parameters: ActionParameters
 ) : LaunchActivityAction
 
 /** @suppress */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class LaunchActivityClassAction(
-    public val activityClass: Class<out Activity>
+    public val activityClass: Class<out Activity>,
+    public override val parameters: ActionParameters
 ) : LaunchActivityAction
 
 /**
  * Creates an [Action] that launches the [Activity] specified by the given [ComponentName].
  *
  * @param componentName component of the activity to launch
+ * @param parameters the parameters associated with the action. Parameter values will be added to
+ * the activity intent, keyed by the parameter key name string.
  */
-public fun actionLaunchActivity(componentName: ComponentName): Action =
-    LaunchActivityComponentAction(componentName)
+public fun actionLaunchActivity(
+    componentName: ComponentName,
+    parameters: ActionParameters = actionParametersOf()
+): Action = LaunchActivityComponentAction(componentName, parameters)
 
 /**
  * Creates an [Action] that launches the specified [Activity] when triggered.
  *
  * @param activity class of the activity to launch
+ * @param parameters the parameters associated with the action. Parameter values will be added to
+ * the activity intent, keyed by the parameter key name string.
  */
-public fun <T : Activity> actionLaunchActivity(activity: Class<T>): Action =
-    LaunchActivityClassAction(activity)
+public fun <T : Activity> actionLaunchActivity(
+    activity: Class<T>,
+    parameters: ActionParameters = actionParametersOf()
+): Action = LaunchActivityClassAction(activity, parameters)
 
 @Suppress("MissingNullability") /* Shouldn't need to specify @NonNull. b/199284086 */
 /**
  * Creates an [Action] that launches the specified [Activity] when triggered.
+ *
+ * @param parameters the parameters associated with the action. Parameter values will be added to
+ * the activity intent, keyed by the parameter key name string.
  */
-public inline fun <reified T : Activity> actionLaunchActivity(): Action =
-    actionLaunchActivity(T::class.java)
+public inline fun <reified T : Activity> actionLaunchActivity(
+    parameters: ActionParameters = actionParametersOf()
+): Action = actionLaunchActivity(T::class.java, parameters)
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt b/glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt
index ca1cc33..51b9999 100644
--- a/glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt
+++ b/glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt
@@ -17,7 +17,11 @@
 package androidx.glance.state
 
 import android.content.Context
+import androidx.annotation.RestrictTo
 import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.PreferenceDataStoreFactory
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.preferencesDataStoreFile
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
@@ -46,52 +50,69 @@
      * @param fileKey The unique string key used to name and identify the data file corresponding to
      * a remote UI. Each remote UI has a unique UI key, used to key the data for that UI.
      */
-    public suspend fun <T> getDataStore(context: Context, fileKey: String): DataStore<T>
+    public suspend fun getDataStore(context: Context, fileKey: String): DataStore<T>
 }
 
 /**
  * Data store for data specific to the glanceable view. Stored data should include information
  * relevant to the representation of views, but not surface specific view data. For example, the
  * month displayed on a calendar rather than actual calendar entries.
+ *
+ * @suppress
  */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public object GlanceState {
-    // TODO(b/205496180): Make methods internal
     /**
      * Returns the stored data associated with the given UI key string.
      *
      * @param definition the configuration that defines this state.
-     * @param fileName identifies the data file associated with the store, must be unique for any
+     * @param fileKey identifies the data file associated with the store, must be unique for any
      * remote UI in the app.
      */
     public suspend fun <T> getValue(
         context: Context,
         definition: GlanceStateDefinition<T>,
-        fileName: String
-    ): T = getDataStore(context, definition, fileName).data.first()
+        fileKey: String
+    ): T = getDataStore(context, definition, fileKey).data.first()
 
     /**
      * Updates the underlying data by applying the provided update block.
      *
      * @param definition the configuration that defines this state.
-     * @param fileName identifies the date file associated with the store, must be unique for any
+     * @param fileKey identifies the date file associated with the store, must be unique for any
      * remote UI in the app.
      */
     public suspend fun <T> updateValue(
         context: Context,
         definition: GlanceStateDefinition<T>,
-        fileName: String,
+        fileKey: String,
         updateBlock: suspend (T) -> T
-    ) = getDataStore(context, definition, fileName).updateData(updateBlock)
+    ): T = getDataStore(context, definition, fileKey).updateData(updateBlock)
+
+    /**
+     * Delete the file underlying the [DataStore] and remove local references to the [DataStore].
+     */
+    public suspend fun deleteStore(
+        context: Context,
+        definition: GlanceStateDefinition<*>,
+        fileKey: String
+    ) {
+        mutex.withLock {
+            dataStores.remove(fileKey)
+            val location = definition.getLocation(context, fileKey)
+            location.delete()
+        }
+    }
 
     @Suppress("UNCHECKED_CAST")
     private suspend fun <T> getDataStore(
         context: Context,
         definition: GlanceStateDefinition<T>,
-        fileName: String
+        fileKey: String
     ): DataStore<T> =
         mutex.withLock {
-            dataStores.getOrPut(fileName) {
-                definition.getDataStore<T>(context, fileName)
+            dataStores.getOrPut(fileKey) {
+                definition.getDataStore(context, fileKey)
             } as DataStore<T>
         }
 
@@ -100,3 +121,14 @@
     // TODO: Move to a single, global source to manage the data lifecycle
     private val dataStores: MutableMap<String, DataStore<*>> = mutableMapOf()
 }
+
+/**
+ * Base class helping the creation of a state using DataStore's [Preferences].
+ */
+object PreferencesGlanceStateDefinition : GlanceStateDefinition<Preferences> {
+    override fun getLocation(context: Context, fileKey: String): File =
+        context.preferencesDataStoreFile(fileKey)
+
+    override suspend fun getDataStore(context: Context, fileKey: String): DataStore<Preferences> =
+        PreferenceDataStoreFactory.create { context.preferencesDataStoreFile(fileKey) }
+}
diff --git a/glance/glance/src/test/kotlin/androidx/glance/ButtonTest.kt b/glance/glance/src/test/kotlin/androidx/glance/ButtonTest.kt
index 6ae0921..6f49d6a2 100644
--- a/glance/glance/src/test/kotlin/androidx/glance/ButtonTest.kt
+++ b/glance/glance/src/test/kotlin/androidx/glance/ButtonTest.kt
@@ -17,8 +17,10 @@
 
 import android.app.Activity
 import androidx.glance.action.ActionModifier
+import androidx.glance.action.ActionParameters
 import androidx.glance.action.LaunchActivityAction
 import androidx.glance.action.actionLaunchActivity
+import androidx.glance.action.actionParametersOf
 import androidx.glance.layout.runTestingComposition
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -39,15 +41,26 @@
 
     @Test
     fun createComposableButton() = fakeCoroutineScope.runBlockingTest {
+        val stringKey = ActionParameters.Key<String>("test")
+        val intKey = ActionParameters.Key<Int>("test2")
+        val string = "testString"
+        val int = 12
+
         val root = runTestingComposition {
-            Button(text = "button", onClick = actionLaunchActivity<Activity>(), enabled = true)
+            Button(text = "button", onClick = actionLaunchActivity<Activity>(
+                actionParametersOf(stringKey to string, intKey to int)
+            ), enabled = true)
         }
 
         assertThat(root.children).hasSize(1)
         val child = assertIs<EmittableButton>(root.children[0])
         assertThat(child.text).isEqualTo("button")
-        assertIs<LaunchActivityAction>(child.modifier.findModifier<ActionModifier>()?.action)
+        val action =
+            assertIs<LaunchActivityAction>(child.modifier.findModifier<ActionModifier>()?.action)
         assertThat(child.enabled).isTrue()
+        assertThat(action.parameters.asMap()).hasSize(2)
+        assertThat(action.parameters[stringKey]).isEqualTo(string)
+        assertThat(action.parameters[intKey]).isEqualTo(int)
     }
 
     @Test
diff --git a/glance/glance/src/test/kotlin/androidx/glance/state/StateDefinitionTest.kt b/glance/glance/src/test/kotlin/androidx/glance/state/StateDefinitionTest.kt
index 6610c26..91a054a 100644
--- a/glance/glance/src/test/kotlin/androidx/glance/state/StateDefinitionTest.kt
+++ b/glance/glance/src/test/kotlin/androidx/glance/state/StateDefinitionTest.kt
@@ -17,12 +17,8 @@
 package androidx.glance.state
 
 import android.content.Context
-import androidx.datastore.core.DataStore
-import androidx.datastore.preferences.core.PreferenceDataStoreFactory
-import androidx.datastore.preferences.core.Preferences
 import androidx.datastore.preferences.core.intPreferencesKey
 import androidx.datastore.preferences.core.stringPreferencesKey
-import androidx.datastore.preferences.preferencesDataStoreFile
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -30,7 +26,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
-import java.io.File
 import kotlin.test.assertNotNull
 
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -45,7 +40,13 @@
     fun emptyStore() {
         runBlocking {
             val uiString = "testUiString1"
-            val store = assertNotNull(GlanceState.getValue(context, EmptyStateDefinition, uiString))
+            val store = assertNotNull(
+                GlanceState.getValue(
+                    context,
+                    PreferencesGlanceStateDefinition,
+                    uiString
+                )
+            )
             assertThat(store.contains(counterKey)).isFalse()
             assertThat(store.contains(stringKey)).isFalse()
         }
@@ -55,20 +56,32 @@
     fun counterKey() {
         runBlocking {
             val uiString = "testUiString2"
-            GlanceState.updateValue(context, EmptyStateDefinition, uiString) { prefs ->
+            GlanceState.updateValue(context, PreferencesGlanceStateDefinition, uiString) { prefs ->
                 prefs.toMutablePreferences().apply { this[counterKey] = 0 }.toPreferences()
             }
 
-            var store = assertNotNull(GlanceState.getValue(context, EmptyStateDefinition, uiString))
+            var store = assertNotNull(
+                GlanceState.getValue(
+                    context,
+                    PreferencesGlanceStateDefinition,
+                    uiString
+                )
+            )
             assertThat(store.contains(counterKey)).isTrue()
             assertThat(store[counterKey]).isEqualTo(0)
 
-            GlanceState.updateValue(context, EmptyStateDefinition, uiString) { prefs ->
+            GlanceState.updateValue(context, PreferencesGlanceStateDefinition, uiString) { prefs ->
                 prefs.toMutablePreferences().apply {
                     this[counterKey] = prefs[counterKey]!! + 1
                 }.toPreferences()
             }
-            store = assertNotNull(GlanceState.getValue(context, EmptyStateDefinition, uiString))
+            store = assertNotNull(
+                GlanceState.getValue(
+                    context,
+                    PreferencesGlanceStateDefinition,
+                    uiString
+                )
+            )
             assertThat(store.contains(counterKey)).isTrue()
             assertThat(store[counterKey]).isEqualTo(1)
         }
@@ -81,36 +94,37 @@
         val storedMessage2 = "Another test string"
 
         runBlocking {
-            GlanceState.updateValue(context, EmptyStateDefinition, uiString) { prefs ->
+            GlanceState.updateValue(context, PreferencesGlanceStateDefinition, uiString) { prefs ->
                 prefs.toMutablePreferences().apply { this[stringKey] = storedMessage1 }
                     .toPreferences()
             }
 
-            var store = assertNotNull(GlanceState.getValue(context, EmptyStateDefinition, uiString))
+            var store = assertNotNull(
+                GlanceState.getValue(
+                    context,
+                    PreferencesGlanceStateDefinition,
+                    uiString
+                )
+            )
             assertThat(store.contains(counterKey)).isFalse()
             assertThat(store.contains(stringKey)).isTrue()
             assertThat(store[stringKey]).isEqualTo(storedMessage1)
 
-            GlanceState.updateValue(context, EmptyStateDefinition, uiString) { prefs ->
+            GlanceState.updateValue(context, PreferencesGlanceStateDefinition, uiString) { prefs ->
                 prefs.toMutablePreferences().apply {
                     this[stringKey] = storedMessage2
                 }.toPreferences()
             }
-            store = assertNotNull(GlanceState.getValue(context, EmptyStateDefinition, uiString))
+            store = assertNotNull(
+                GlanceState.getValue(
+                    context,
+                    PreferencesGlanceStateDefinition,
+                    uiString
+                )
+            )
             assertThat(store.contains(counterKey)).isFalse()
             assertThat(store.contains(stringKey)).isTrue()
             assertThat(store[stringKey]).isEqualTo(storedMessage2)
         }
     }
-
-    object EmptyStateDefinition : GlanceStateDefinition<Preferences> {
-        override fun getLocation(context: Context, fileKey: String): File =
-            context.preferencesDataStoreFile(fileKey)
-
-        @Suppress("UNCHECKED_CAST")
-        override suspend fun <T> getDataStore(context: Context, fileKey: String): DataStore<T> =
-            PreferenceDataStoreFactory.create {
-                context.preferencesDataStoreFile(fileKey)
-            } as DataStore<T>
-    }
 }
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 1f962fa..c44b094 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
-org.gradle.jvmargs=-Xmx8g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
+org.gradle.jvmargs=-Xmx8g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g -Dlint.nullness.ignore-deprecated=true
 org.gradle.daemon=true
 org.gradle.configureondemand=true
 org.gradle.parallel=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index eb02229..6bcb125 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -15,7 +15,7 @@
 androidLintMinCompose = "30.0.0"
 androidxTestRunner = "1.4.0"
 androidxTestRules = "1.4.0"
-androidxTestMonitor = "1.5.0-beta01"
+androidxTestMonitor = "1.5.0-rc01"
 androidxTestCore = "1.4.0"
 androidxTestExtJunit = "1.1.3"
 androidxTestExtTruth = "1.4.0"
@@ -145,7 +145,7 @@
 protobufLite = { module = "com.google.protobuf:protobuf-javalite", version = "3.10.0" }
 reactiveStreams = { module = "org.reactivestreams:reactive-streams", version = "1.0.0" }
 retrofit = { module = "com.squareup.retrofit2:retrofit", version = "2.7.2" }
-robolectric = { module = "org.robolectric:robolectric", version = "4.6.1" }
+robolectric = { module = "org.robolectric:robolectric", version = "4.7" }
 rxjava2 = { module = "io.reactivex.rxjava2:rxjava", version = "2.2.9" }
 rxjava3 = { module = "io.reactivex.rxjava3:rxjava", version = "3.0.0" }
 shadow = { module = "gradle.plugin.com.github.johnrengelman:shadow", version = "7.1.0" }
@@ -173,3 +173,6 @@
 wireRuntime = { module = "com.squareup.wire:wire-runtime", version.ref = "wire" }
 xpp3 = { module = "xpp3:xpp3", version = "1.1.4c" }
 xmlpull = { module = "xmlpull:xmlpull", version = "1.1.3.1" }
+
+[plugins]
+kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 7f930a72..e7769e2 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,3 @@
-#Tue Aug 16 10:43:36 PDT 2016
-# IMPORTANT: Also update ui/gradle/wrapper/gradle-wrapper.properties
-# when changing this file
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
diff --git a/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/DexInspectorTask.kt b/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/DexInspectorTask.kt
index de040cf..50e6f8d 100644
--- a/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/DexInspectorTask.kt
+++ b/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/DexInspectorTask.kt
@@ -25,6 +25,7 @@
 import org.gradle.api.file.ConfigurableFileCollection
 import org.gradle.api.file.DirectoryProperty
 import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.CacheableTask
 import org.gradle.api.tasks.Classpath
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputFile
@@ -42,6 +43,7 @@
 import java.io.File
 import java.nio.charset.Charset
 
+@CacheableTask
 abstract class DexInspectorTask : DefaultTask() {
     @get:PathSensitive(PathSensitivity.NONE)
     @get:InputFile
diff --git a/jetifier/OWNERS b/jetifier/OWNERS
deleted file mode 100644
index 8ae348f..0000000
--- a/jetifier/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-pavlis@google.com
diff --git a/lifecycle/OWNERS b/lifecycle/OWNERS
index 99fbeef..27789fd 100644
--- a/lifecycle/OWNERS
+++ b/lifecycle/OWNERS
@@ -1,7 +1,9 @@
 # Bug component: 413132
+ilake@google.com
+jbwoods@google.com
+sanura@google.com
 sergeyv@google.com
 yboyar@google.com
-jbwoods@google.com
 
 per-file settings.gradle = dustinlam@google.com, rahulrav@google.com
 
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/build.gradle b/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
index f0497c3..8776e4f 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
+++ b/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
@@ -28,6 +28,8 @@
     compileOnly(libs.kotlinStdlib)
 
     testImplementation(libs.kotlinStdlib)
+    testImplementation(libs.kotlinReflect)
+    testImplementation(libs.kotlinStdlibJdk8)
     testImplementation(libs.androidLint)
     testImplementation(libs.androidLintTests)
     testImplementation(libs.junit)
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleWhenChecks.kt b/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleWhenChecks.kt
index a1d8509..f863f3c 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleWhenChecks.kt
+++ b/lifecycle/lifecycle-runtime-ktx-lint/src/main/java/androidx/lifecycle/lint/LifecycleWhenChecks.kt
@@ -42,7 +42,9 @@
 import org.jetbrains.uast.UIfExpression
 import org.jetbrains.uast.ULambdaExpression
 import org.jetbrains.uast.UMethod
+import org.jetbrains.uast.USwitchClauseExpression
 import org.jetbrains.uast.UTryExpression
+import org.jetbrains.uast.kotlin.KotlinUSwitchEntry
 import org.jetbrains.uast.toUElement
 import org.jetbrains.uast.tryResolve
 import org.jetbrains.uast.visitor.AbstractUastVisitor
@@ -190,6 +192,23 @@
         }
         return false
     }
+
+    override fun visitSwitchClauseExpression(node: USwitchClauseExpression): Boolean {
+        // check each case in the switch statement
+        node.caseValues.forEach { expression ->
+            val method = expression.tryResolve() as? PsiMethod ?: return false
+            if (method.isLifecycleIsAtLeastMethod(context)) {
+                // If the case containing the lifecycle check evaluates to true, check the body
+                withNewState(checkUIAccess = false) {
+                    (node as? KotlinUSwitchEntry)?.body?.expressions?.forEach {
+                        it.accept(this)
+                    }
+                }
+                return true
+            }
+        }
+        return false
+    }
 }
 
 private const val DISPATCHER_CLASS_NAME = "androidx.lifecycle.PausingDispatcherKt"
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/LifecycleWhenChecksTest.kt b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/LifecycleWhenChecksTest.kt
index dbba1ac..e45da05 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/LifecycleWhenChecksTest.kt
+++ b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/LifecycleWhenChecksTest.kt
@@ -24,7 +24,6 @@
 import com.android.tools.lint.checks.infrastructure.TestFiles.kt
 import com.android.tools.lint.checks.infrastructure.TestLintResult
 import com.android.tools.lint.checks.infrastructure.TestLintTask
-import com.android.tools.lint.checks.infrastructure.TestMode
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -35,8 +34,6 @@
     private fun check(body: String): TestLintResult {
         return TestLintTask.lint()
             .files(VIEW_STUB, LIFECYCLE_STUB, COROUTINES_STUB, kt(template(body)))
-            .allowCompilationErrors(true) // b/193267317
-            .skipTestModes(TestMode.IF_TO_WHEN) // b/203245752
             .issues(ISSUE)
             .run()
     }
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/RepeatOnLifecycleDetectorTest.kt b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/RepeatOnLifecycleDetectorTest.kt
index cce75cd..aa6e8ef 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/RepeatOnLifecycleDetectorTest.kt
+++ b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/RepeatOnLifecycleDetectorTest.kt
@@ -107,7 +107,6 @@
                 *REPEAT_ON_LIFECYCLE_STUBS,
                 TestFiles.kt(fileToAdd)
             )
-            .allowCompilationErrors(true) // b/193267317
             .issues(RepeatOnLifecycleDetector.ISSUE)
             .run()
     }
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/WhenMethodsTest.kt b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/WhenMethodsTest.kt
index 5b26766..701f1da 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/WhenMethodsTest.kt
+++ b/lifecycle/lifecycle-runtime-ktx-lint/src/test/java/androidx/lifecycle/runtime/lint/WhenMethodsTest.kt
@@ -51,7 +51,6 @@
 
     private fun check(body: String): TestLintResult {
         return TestLintTask.lint()
-            .allowCompilationErrors(true) // b/193267317
             .files(VIEW_STUB, LIFECYCLE_STUB, COROUTINES_STUB, TestFiles.kt(template(body)))
             .issues(LifecycleWhenChecks.ISSUE)
             .run()
diff --git a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
index 737c820..5075f11 100644
--- a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
@@ -37,6 +37,9 @@
                 BanInappropriateExperimentalUsage.ISSUE,
                 BanKeepAnnotation.ISSUE,
                 TargetApiAnnotationUsageDetector.ISSUE,
+                // If you add more SampledAnnotationDetector issues here, you
+                // MUST also update `buildSrc/lint_samples.xml` to ensure they
+                // run against samples projects.
                 SampledAnnotationDetector.OBSOLETE_SAMPLED_ANNOTATION,
                 SampledAnnotationDetector.UNRESOLVED_SAMPLE_LINK,
                 SampledAnnotationDetector.MULTIPLE_FUNCTIONS_FOUND,
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/RemoteUserInfoWithMediaControllerCompatTest.java b/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/RemoteUserInfoWithMediaControllerCompatTest.java
index 8bde7c9..c950d58 100644
--- a/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/RemoteUserInfoWithMediaControllerCompatTest.java
+++ b/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/RemoteUserInfoWithMediaControllerCompatTest.java
@@ -46,6 +46,7 @@
 import android.view.KeyEvent;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 
 import org.junit.After;
@@ -61,6 +62,7 @@
  * Test of {@link MediaSessionCompat#getCurrentControllerInfo()} with all
  * {@link MediaControllerCompat} methods.
  */
+@FlakyTest(bugId = 206969269)
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class RemoteUserInfoWithMediaControllerCompatTest {
diff --git a/mediarouter/mediarouter/api/current.txt b/mediarouter/mediarouter/api/current.txt
index 6af2727..a750177 100644
--- a/mediarouter/mediarouter/api/current.txt
+++ b/mediarouter/mediarouter/api/current.txt
@@ -452,7 +452,7 @@
 
   public class MediaRouterParams {
     method public int getDialogType();
-    method public boolean isMediaTransferReceiverDisabled();
+    method public boolean isMediaTransferReceiverEnabled();
     method public boolean isOutputSwitcherEnabled();
     method public boolean isTransferToLocalEnabled();
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
@@ -465,7 +465,7 @@
     ctor public MediaRouterParams.Builder(androidx.mediarouter.media.MediaRouterParams);
     method public androidx.mediarouter.media.MediaRouterParams build();
     method public androidx.mediarouter.media.MediaRouterParams.Builder setDialogType(int);
-    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverDisabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setOutputSwitcherEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setTransferToLocalEnabled(boolean);
   }
diff --git a/mediarouter/mediarouter/api/public_plus_experimental_current.txt b/mediarouter/mediarouter/api/public_plus_experimental_current.txt
index 6af2727..a750177 100644
--- a/mediarouter/mediarouter/api/public_plus_experimental_current.txt
+++ b/mediarouter/mediarouter/api/public_plus_experimental_current.txt
@@ -452,7 +452,7 @@
 
   public class MediaRouterParams {
     method public int getDialogType();
-    method public boolean isMediaTransferReceiverDisabled();
+    method public boolean isMediaTransferReceiverEnabled();
     method public boolean isOutputSwitcherEnabled();
     method public boolean isTransferToLocalEnabled();
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
@@ -465,7 +465,7 @@
     ctor public MediaRouterParams.Builder(androidx.mediarouter.media.MediaRouterParams);
     method public androidx.mediarouter.media.MediaRouterParams build();
     method public androidx.mediarouter.media.MediaRouterParams.Builder setDialogType(int);
-    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverDisabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setOutputSwitcherEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setTransferToLocalEnabled(boolean);
   }
diff --git a/mediarouter/mediarouter/api/restricted_current.txt b/mediarouter/mediarouter/api/restricted_current.txt
index 6af2727..a750177 100644
--- a/mediarouter/mediarouter/api/restricted_current.txt
+++ b/mediarouter/mediarouter/api/restricted_current.txt
@@ -452,7 +452,7 @@
 
   public class MediaRouterParams {
     method public int getDialogType();
-    method public boolean isMediaTransferReceiverDisabled();
+    method public boolean isMediaTransferReceiverEnabled();
     method public boolean isOutputSwitcherEnabled();
     method public boolean isTransferToLocalEnabled();
     field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
@@ -465,7 +465,7 @@
     ctor public MediaRouterParams.Builder(androidx.mediarouter.media.MediaRouterParams);
     method public androidx.mediarouter.media.MediaRouterParams build();
     method public androidx.mediarouter.media.MediaRouterParams.Builder setDialogType(int);
-    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverDisabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setOutputSwitcherEnabled(boolean);
     method public androidx.mediarouter.media.MediaRouterParams.Builder setTransferToLocalEnabled(boolean);
   }
diff --git a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
index aa9fff3..186093b 100644
--- a/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
+++ b/mediarouter/mediarouter/src/androidTest/java/androidx/mediarouter/media/MediaRouterTest.java
@@ -130,7 +130,7 @@
         final int dialogType = MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP;
         final boolean isOutputSwitcherEnabled = true;
         final boolean transferToLocalEnabled = true;
-        final boolean transferReceiverDisabled = true;
+        final boolean transferReceiverEnabled = false;
         final Bundle extras = new Bundle();
         extras.putString(TEST_KEY, TEST_VALUE);
 
@@ -138,7 +138,7 @@
                 .setDialogType(dialogType)
                 .setOutputSwitcherEnabled(isOutputSwitcherEnabled)
                 .setTransferToLocalEnabled(transferToLocalEnabled)
-                .setMediaTransferReceiverDisabled(transferReceiverDisabled)
+                .setMediaTransferReceiverEnabled(transferReceiverEnabled)
                 .setExtras(extras)
                 .build();
 
@@ -147,13 +147,13 @@
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
             assertEquals(isOutputSwitcherEnabled, params.isOutputSwitcherEnabled());
             assertEquals(transferToLocalEnabled, params.isTransferToLocalEnabled());
-            assertEquals(transferReceiverDisabled, params.isMediaTransferReceiverDisabled());
+            assertEquals(transferReceiverEnabled, params.isMediaTransferReceiverEnabled());
         } else {
             // Earlier than Android R, output switcher cannot be enabled.
             // Same for transfer to local.
             assertFalse(params.isOutputSwitcherEnabled());
             assertFalse(params.isTransferToLocalEnabled());
-            assertFalse(params.isMediaTransferReceiverDisabled());
+            assertFalse(params.isMediaTransferReceiverEnabled());
         }
 
         extras.remove(TEST_KEY);
@@ -164,8 +164,8 @@
         assertEquals(params.getDialogType(), copiedParams.getDialogType());
         assertEquals(params.isOutputSwitcherEnabled(), copiedParams.isOutputSwitcherEnabled());
         assertEquals(params.isTransferToLocalEnabled(), copiedParams.isTransferToLocalEnabled());
-        assertEquals(params.isMediaTransferReceiverDisabled(),
-                copiedParams.isMediaTransferReceiverDisabled());
+        assertEquals(params.isMediaTransferReceiverEnabled(),
+                copiedParams.isMediaTransferReceiverEnabled());
         assertBundleEquals(params.getExtras(), copiedParams.getExtras());
     }
 
@@ -176,7 +176,7 @@
         final int dialogType = MediaRouterParams.DIALOG_TYPE_DYNAMIC_GROUP;
         final boolean isOutputSwitcherEnabled = true;
         final boolean transferToLocalEnabled = true;
-        final boolean transferReceiverDisabled = true;
+        final boolean transferReceiverEnabled = false;
         final Bundle paramExtras = new Bundle();
         paramExtras.putString(TEST_KEY, TEST_VALUE);
 
@@ -184,7 +184,7 @@
                 .setDialogType(dialogType)
                 .setOutputSwitcherEnabled(isOutputSwitcherEnabled)
                 .setTransferToLocalEnabled(transferToLocalEnabled)
-                .setMediaTransferReceiverDisabled(transferReceiverDisabled)
+                .setMediaTransferReceiverEnabled(transferReceiverEnabled)
                 .setExtras(paramExtras)
                 .build();
 
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
index 6eb9f22..3334211 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter.java
@@ -2654,6 +2654,8 @@
                     mMr2Provider = new MediaRoute2Provider(
                             mApplicationContext, new Mr2ProviderCallback());
                     addProvider(mMr2Provider);
+                    // Make sure mDiscoveryRequestForMr2Provider is updated
+                    updateDiscoveryRequest();
                     mRegisteredProviderWatcher.rescan();
                 }
 
@@ -2938,8 +2940,9 @@
         }
 
         boolean isMediaTransferEnabled() {
+            // The default value for isMediaTransferReceiverEnabled() is {@code true}.
             return mTransferReceiverDeclared
-                    && (mRouterParams == null || !mRouterParams.isMediaTransferReceiverDisabled());
+                    && (mRouterParams == null || mRouterParams.isMediaTransferReceiverEnabled());
         }
 
         boolean isTransferToLocalEnabled() {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
index f580da1..405202f 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouterParams.java
@@ -76,14 +76,14 @@
 
     @DialogType
     final int mDialogType;
-    final boolean mMediaTransferReceiverDisabled;
+    final boolean mMediaTransferReceiverEnabled;
     final boolean mOutputSwitcherEnabled;
     final boolean mTransferToLocalEnabled;
     final Bundle mExtras;
 
     MediaRouterParams(@NonNull Builder builder) {
         mDialogType = builder.mDialogType;
-        mMediaTransferReceiverDisabled = builder.mMediaTransferDisabled;
+        mMediaTransferReceiverEnabled = builder.mMediaTransferEnabled;
         mOutputSwitcherEnabled = builder.mOutputSwitcherEnabled;
         mTransferToLocalEnabled = builder.mTransferToLocalEnabled;
 
@@ -101,12 +101,12 @@
     }
 
     /**
-     * Gets whether declared {@link MediaTransferReceiver} is disabled.
+     * Gets whether declared {@link MediaTransferReceiver} is enabled.
      *
-     * @see Builder#setMediaTransferReceiverDisabled(boolean)
+     * @see Builder#setMediaTransferReceiverEnabled(boolean)
      */
-    public boolean isMediaTransferReceiverDisabled() {
-        return mMediaTransferReceiverDisabled;
+    public boolean isMediaTransferReceiverEnabled() {
+        return mMediaTransferReceiverEnabled;
     }
 
     /**
@@ -146,7 +146,7 @@
     public static final class Builder {
         @DialogType
         int mDialogType = DIALOG_TYPE_DEFAULT;
-        boolean mMediaTransferDisabled;
+        boolean mMediaTransferEnabled = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
         boolean mOutputSwitcherEnabled;
         boolean mTransferToLocalEnabled;
         Bundle mExtras;
@@ -170,7 +170,7 @@
             mDialogType = params.mDialogType;
             mOutputSwitcherEnabled = params.mOutputSwitcherEnabled;
             mTransferToLocalEnabled = params.mTransferToLocalEnabled;
-            mMediaTransferDisabled = params.mMediaTransferReceiverDisabled;
+            mMediaTransferEnabled = params.mMediaTransferReceiverEnabled;
             mExtras = params.mExtras == null ? null : new Bundle(params.mExtras);
         }
 
@@ -194,12 +194,13 @@
         }
 
         /**
-         * Sets whether declared {@link MediaTransferReceiver} is disabled. This method will be
-         * no-op for Android versions earlier than Android R. The default value is {@code false}.
+         * Sets whether declared {@link MediaTransferReceiver} is enabled. The default value is
+         * {@code true}. This method will be no-op for Android versions earlier than Android R and
+         * it stays {@code false} on devices earlier than Android R.
          * <p>
-         * It is used to disable media transfer feature when {@link MediaTransferReceiver} is
+         * It can be used to disable media transfer feature when {@link MediaTransferReceiver} is
          * declared.
-         * If set to {@code true}, media transfer feature will be disabled
+         * If set to {@code false}, media transfer feature will be disabled
          * even when {@link MediaTransferReceiver} is declared.
          * <p>
          * It is not recommended to change this value at runtime.
@@ -207,9 +208,9 @@
          * @see MediaTransferReceiver
          */
         @NonNull
-        public Builder setMediaTransferReceiverDisabled(boolean disabled) {
+        public Builder setMediaTransferReceiverEnabled(boolean enabled) {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-                mMediaTransferDisabled = disabled;
+                mMediaTransferEnabled = enabled;
             }
             return this;
         }
diff --git a/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt b/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt
index 59d3623..be66cde 100644
--- a/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt
+++ b/navigation/navigation-compose/src/androidTest/java/androidx/navigation/compose/NavHostTest.kt
@@ -714,6 +714,36 @@
     }
 
     @Test
+    fun testGetDialogViewModel() {
+        lateinit var navController: NavHostController
+        lateinit var model: TestViewModel
+
+        composeTestRule.setContent {
+            navController = rememberNavController()
+            NavHost(navController, first) {
+                composable(first) { }
+                dialog(second) {
+                    model = viewModel(it)
+                }
+            }
+        }
+
+        composeTestRule.runOnIdle {
+            navController.navigate(second)
+        }
+
+        composeTestRule.runOnIdle {
+            navController.popBackStack()
+        }
+
+        assertThat(model.wasCleared).isFalse()
+
+        composeTestRule.waitForIdle()
+
+        assertThat(model.wasCleared).isTrue()
+    }
+
+    @Test
     fun testGetGraphViewModelAfterRecompose() {
         lateinit var navController: NavHostController
         lateinit var model: TestViewModel
diff --git a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogHost.kt b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogHost.kt
index c8ef92c..700efea 100644
--- a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogHost.kt
+++ b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogHost.kt
@@ -17,6 +17,7 @@
 package androidx.navigation.compose
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.saveable.rememberSaveableStateHolder
@@ -47,6 +48,12 @@
             backStackEntry.LocalOwnersProvider(saveableStateHolder) {
                 destination.content(backStackEntry)
             }
+
+            DisposableEffect(backStackEntry) {
+                onDispose {
+                    dialogNavigator.onTransitionComplete(backStackEntry)
+                }
+            }
         }
     }
 }
diff --git a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogNavigator.kt b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogNavigator.kt
index 4d433ec..bfac256 100644
--- a/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogNavigator.kt
+++ b/navigation/navigation-compose/src/main/java/androidx/navigation/compose/DialogNavigator.kt
@@ -61,7 +61,11 @@
     }
 
     override fun popBackStack(popUpTo: NavBackStackEntry, savedState: Boolean) {
-        state.pop(popUpTo, savedState)
+        state.popWithTransition(popUpTo, savedState)
+    }
+
+    internal fun onTransitionComplete(entry: NavBackStackEntry) {
+        state.markTransitionComplete(entry)
     }
 
     /**
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
index c1e144d..fb24f725 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/ActivityNavigatorTest.kt
@@ -302,6 +302,82 @@
     }
 
     @Test
+    fun testEquals() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        assertThat(firstDestination).isEqualTo(secondDestination)
+    }
+
+    @Test
+    fun testFilterEquals() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+            intent!!.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        }
+        assertThat(firstDestination).isEqualTo(secondDestination)
+    }
+
+    @Test
+    fun testEqualsBothIntentNull() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+        }
+        assertThat(firstDestination).isEqualTo(secondDestination)
+    }
+
+    @Test
+    fun testNotEquals() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+            setAction(TARGET_ACTION)
+        }
+        assertThat(firstDestination).isNotEqualTo(secondDestination)
+    }
+
+    @Test
+    fun testNotEqualsFirstIntentNull() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        assertThat(firstDestination).isNotEqualTo(secondDestination)
+    }
+
+    @Test
+    fun testNotEqualsSecondIntentNull() {
+        val firstDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+            setComponentName(ComponentName(activityRule.activity, TargetActivity::class.java))
+        }
+        val secondDestination = activityNavigator.createDestination().apply {
+            id = TARGET_ID
+        }
+        assertThat(firstDestination).isNotEqualTo(secondDestination)
+    }
+
+    @Test
     fun testToString() {
         val targetDestination = activityNavigator.createDestination().apply {
             id = TARGET_ID
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
index f52061b..8d880eac 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/ActivityNavigator.kt
@@ -407,22 +407,14 @@
         override fun equals(other: Any?): Boolean {
             if (other == null || other !is Destination) return false
             return super.equals(other) &&
-                intent == other.intent &&
-                dataPattern == other.dataPattern &&
-                targetPackage == other.targetPackage &&
-                component == other.component &&
-                action == other.action &&
-                data == other.data
+                intent?.filterEquals(other.intent) ?: (other.intent == null) &&
+                dataPattern == other.dataPattern
         }
 
         override fun hashCode(): Int {
             var result = super.hashCode()
-            result = 31 * result + intent.hashCode()
+            result = 31 * result + (intent?.filterHashCode() ?: 0)
             result = 31 * result + dataPattern.hashCode()
-            result = 31 * result + targetPackage.hashCode()
-            result = 31 * result + component.hashCode()
-            result = 31 * result + action.hashCode()
-            result = 31 * result + data.hashCode()
             return result
         }
     }
diff --git a/paging/paging-common/src/test/kotlin/androidx/paging/CachedPageEventFlowLeakTest.kt b/paging/paging-common/src/test/kotlin/androidx/paging/CachedPageEventFlowLeakTest.kt
index d38b63f..415c3a4 100644
--- a/paging/paging-common/src/test/kotlin/androidx/paging/CachedPageEventFlowLeakTest.kt
+++ b/paging/paging-common/src/test/kotlin/androidx/paging/CachedPageEventFlowLeakTest.kt
@@ -26,6 +26,7 @@
 import kotlinx.coroutines.flow.takeWhile
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -196,6 +197,8 @@
         }
     }
 
+    // Broken: b/206981029
+    @Ignore
     @Test
     public fun dontLeakPreviousPageInfoWithCache_stillCollecting() {
         val scope = CoroutineScope(EmptyCoroutineContext)
diff --git a/playground-common/androidx-shared.properties b/playground-common/androidx-shared.properties
index 335fef47..958efb4 100644
--- a/playground-common/androidx-shared.properties
+++ b/playground-common/androidx-shared.properties
@@ -24,7 +24,7 @@
 # This separation is necessary to ensure gradle can read certain properties
 # at configuration time.
 
-org.gradle.jvmargs=-Xmx8g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
+org.gradle.jvmargs=-Xmx8g -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g -Dlint.nullness.ignore-deprecated=true
 android.useAndroidX=true
 # Disable features we do not use
 android.defaults.buildfeatures.aidl=false
diff --git a/playground-common/playground-plugin/build.gradle b/playground-common/playground-plugin/build.gradle
index 9fff29a..7b521cf 100644
--- a/playground-common/playground-plugin/build.gradle
+++ b/playground-common/playground-plugin/build.gradle
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- plugins {
+
+plugins {
     id "groovy-gradle-plugin"
+    alias(libs.plugins.kotlinJvm)
 }
 
 repositories {
@@ -26,6 +28,15 @@
     implementation "com.gradle:common-custom-user-data-gradle-plugin:1.5"
 }
 
+// Needed to be able to use Groovy code from Kotlin
+// https://docs.gradle.org/6.1-rc-1/release-notes.html#compilation-order
+tasks.named('compileGroovy') {
+    classpath = sourceSets.main.compileClasspath
+}
+tasks.named('compileKotlin') {
+    classpath += files(sourceSets.main.groovy.classesDirectory)
+}
+
 gradlePlugin {
     plugins {
         playgroundConventions {
diff --git a/playground-common/playground-plugin/settings.gradle b/playground-common/playground-plugin/settings.gradle
index 9c18267..cb8499c 100644
--- a/playground-common/playground-plugin/settings.gradle
+++ b/playground-common/playground-plugin/settings.gradle
@@ -33,3 +33,12 @@
         }
     }
 }
+
+enableFeaturePreview("VERSION_CATALOGS")
+dependencyResolutionManagement {
+    versionCatalogs {
+        libs {
+            from(files("../../gradle/libs.versions.toml"))
+        }
+    }
+}
\ No newline at end of file
diff --git a/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleEnterpriseConventionsPlugin.groovy b/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleEnterpriseConventionsPlugin.groovy
deleted file mode 100644
index 566904b..0000000
--- a/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleEnterpriseConventionsPlugin.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package androidx.playground
-
-import org.gradle.api.Plugin
-import org.gradle.api.initialization.Settings
-import org.gradle.caching.http.HttpBuildCache
-
-class GradleEnterpriseConventionsPlugin implements Plugin<Settings> {
-    void apply(Settings settings) {
-        settings.apply(plugin: "com.gradle.enterprise")
-        settings.apply(plugin: "com.gradle.common-custom-user-data-gradle-plugin")
-
-        // Github Actions always sets a "CI" environment variable
-        var isCI = System.getenv("CI") != null
-
-        settings.gradleEnterprise {
-            server = "https://ge.androidx.dev"
-
-            buildScan {
-                publishAlways()
-                publishIfAuthenticated()
-
-                uploadInBackground = !isCI
-
-                capture {
-                    taskInputFiles = true
-                }
-                obfuscation {
-                    hostname { host -> "unset" }
-                    ipAddresses { addresses -> addresses.collect { address -> "0.0.0.0"} }
-                }
-            }
-        }
-
-        settings.buildCache {
-            remote(HttpBuildCache) {
-                url = "https://ge.androidx.dev/cache/"
-                var buildCachePassword = System.getenv("GRADLE_BUILD_CACHE_PASSWORD")
-                if (isCI && buildCachePassword != null && !buildCachePassword.empty) {
-                    push = true
-                    credentials {
-                        username = "ci"
-                        password = buildCachePassword
-                    }
-                } else {
-                    push = false
-                }
-            }
-        }
-    }
-}
diff --git a/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleWorkaround.groovy b/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleWorkaround.groovy
new file mode 100644
index 0000000..d85061c
--- /dev/null
+++ b/playground-common/playground-plugin/src/main/groovy/androidx/playground/GradleWorkaround.groovy
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.playground
+
+import com.gradle.scan.plugin.BuildScanDataObfuscation
+
+class GradleWorkaround {
+    /**
+     * This is needed because Gradle configuration caching fails to serialize these lambdas
+     * if they are written in Kotlin
+     * https://github.com/gradle/gradle/issues/19047
+     */
+    static void obfuscate(BuildScanDataObfuscation obfuscation) {
+        obfuscation.hostname {"unset" }
+        obfuscation.ipAddresses { addresses -> addresses.collect { address -> "0.0.0.0"} }
+    }
+}
\ No newline at end of file
diff --git a/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundExtension.groovy b/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundExtension.groovy
deleted file mode 100644
index ab9daac..0000000
--- a/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundExtension.groovy
+++ /dev/null
@@ -1,177 +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.playground
-
-import javax.inject.Inject
-import org.gradle.api.GradleException
-import org.gradle.api.model.ObjectFactory
-import org.gradle.api.initialization.Settings
-
-class PlaygroundExtension {
-    private final ObjectFactory objectFactory
-    private final Settings settings
-
-    private File supportRootDir
-
-    @Inject
-    PlaygroundExtension(Settings settings, ObjectFactory objectFactory) {
-        this.settings = settings
-        this.objectFactory = objectFactory
-    }
-
-    /**
-     * Includes the project if it does not already exist.
-     * This is invoked from `includeProject` to ensure all parent projects are included. If they are
-     * not, gradle will use the root project path to set the projectDir, which might conflict in
-     * playground. Instead, this method checks if another project in that path exists and if so,
-     * changes the project dir to avoid the conflict.
-     * see b/197253160 for details.
-     */
-    private includeFakeParentProjectIfNotExists(String name, File projectDir) {
-        if (name.isEmpty()) return
-        if (settings.findProject(name)) {
-            return
-        }
-        if (settings.findProject(projectDir) != null) {
-            // Project directory conflicts with an existing project (possibly root). Move it
-            // to another directory to avoid the conflict.
-            projectDir = new File(projectDir.getParentFile(), ".ignore-${projectDir.name}")
-        }
-        includeProjectAt(name, projectDir)
-        // Set it to a gradle file that does not exist.
-        // We must always include projects starting with root, if we are including nested projects.
-        settings.project(name).buildFileName = "ignored.gradle"
-    }
-
-    private includeProjectAt(String name, File projectDir) {
-        if (settings.findProject(name) != null) {
-            throw new GradleException("Cannot include project twice: $name is already included.")
-        }
-        def parentPath = name.substring(0, name.lastIndexOf(":"))
-        def parentDir = projectDir.getParentFile()
-        // Make sure parent is created first. see: b/197253160 for details
-        includeFakeParentProjectIfNotExists(
-            parentPath,
-            parentDir
-        )
-        settings.include(name)
-        settings.project(name).projectDir = projectDir
-    }
-
-    /**
-     * Includes a project by name, with a path relative to the root of AndroidX.
-     */
-    def includeProject(String name, String filePath) {
-        if (supportRootDir == null) {
-            throw new GradleException("Must call setupPlayground() first.")
-        }
-        includeProjectAt(name, new File(supportRootDir, filePath))
-    }
-
-    /**
-    * Initializes the playground project to use public repositories as well as other internal projects
-    * that cannot be found in public repositories.
-    *
-    * @param settings The reference to the settings script
-    * @param relativePathToRoot The relative path of the project to the root AndroidX project
-    */
-    def setupPlayground(String relativePathToRoot) {
-        def projectDir = settings.rootProject.getProjectDir()
-        def supportRoot = new File(projectDir, relativePathToRoot).getCanonicalFile()
-        this.supportRootDir = supportRoot
-        def buildFile = new File(supportRoot, "playground-common/playground-build.gradle")
-        def relativePathToBuild = projectDir.toPath().relativize(buildFile.toPath()).toString()
-
-        Properties playgroundProperties = new Properties()
-        File propertiesFile = new File(supportRoot, "playground-common/playground.properties")
-        propertiesFile.withInputStream {
-            playgroundProperties.load(it)
-        }
-        settings.gradle.beforeProject { project ->
-            // load playground properties. These are not kept in the playground projects to prevent
-            // AndroidX build from reading them.
-            playgroundProperties.each {
-                project.ext[it.key] = it.value
-            }
-        }
-
-        settings.rootProject.buildFileName = relativePathToBuild
-        settings.enableFeaturePreview("VERSION_CATALOGS")
-
-        def catalogFiles = objectFactory.fileCollection().from("$supportRoot/gradle/libs.versions.toml")
-        settings.dependencyResolutionManagement {
-            versionCatalogs {
-                libs {
-                    from(catalogFiles)
-                }
-            }
-        }
-
-        includeProject(":lint-checks", "lint-checks")
-        includeProject(":lint-checks:integration-tests", "lint-checks/integration-tests")
-        includeProject(":fakeannotations", "fakeannotations")
-        includeProject(":internal-testutils-common", "testutils/testutils-common")
-        includeProject(":internal-testutils-gradle-plugin", "testutils/testutils-gradle-plugin")
-
-        // allow public repositories
-        System.setProperty("ALLOW_PUBLIC_REPOS", "true")
-
-        // specify out dir location
-        System.setProperty("CHECKOUT_ROOT", supportRoot.path)
-    }
-
-
-    /**
-    * A convenience method to include projects from the main AndroidX build using a filter.
-    *
-    * @param filter This filter will be called with the project name (project path in gradle).
-    *               If filter returns true, it will be included in the build.
-    */
-    def selectProjectsFromAndroidX(filter) {
-        if (supportRootDir == null) {
-            throw new RuntimeException("Must call setupPlayground() first.")
-        }
-
-        // Multiline matcher for anything of the form:
-        //  includeProject(name, path, ...)
-        // where '...' is anything except the ')' character.
-        def includeProjectPattern = ~/(?m)^[\n\r\s]*includeProject\("(?<name>[a-z0-9-:]*)",[\n\r\s]*"(?<path>[a-z0-9-\/]+)[^)]+\)$/
-        def supportSettingsFile = new File(supportRootDir, "settings.gradle")
-        def matcher = includeProjectPattern.matcher(supportSettingsFile.text)
-
-        while (matcher.find()) {
-            // check if is an include project line, if so, extract project gradle path and
-            // file system path and call the filter
-            def projectGradlePath = matcher.group("name")
-            def projectFilePath = matcher.group("path")
-            if (filter(projectGradlePath)) {
-                includeProject(projectGradlePath, projectFilePath)
-            }
-        }
-    }
-
-    /**
-    * Checks if a project is necessary for playground projects that involve compose.
-    */
-    def isNeededForComposePlayground(name) {
-        if (name == ":compose:lint:common") return true
-        if (name == ":compose:lint:internal-lint-checks") return true
-        if (name == ":compose:test-utils") return true
-        if (name == ":compose:lint:common-test") return true
-        if (name == ":test:screenshot:screenshot") return true
-        return false
-    }
-}
\ No newline at end of file
diff --git a/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundPlugin.groovy b/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundPlugin.groovy
deleted file mode 100644
index 4208b82..0000000
--- a/playground-common/playground-plugin/src/main/groovy/androidx/playground/PlaygroundPlugin.groovy
+++ /dev/null
@@ -1,50 +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.playground
-
-import org.gradle.api.Plugin
-import org.gradle.api.initialization.Settings
-
-class PlaygroundPlugin implements Plugin<Settings> {
-    void apply(Settings settings) {
-        settings.apply(plugin: "playground-ge-conventions")
-
-        settings.extensions.create("playground", PlaygroundExtension, settings)
-
-        validateJvm(settings)
-    }
-
-    def validateJvm(Settings settings) {
-        // validate JVM version to print an understandable error if it is not set to the
-        // required value (11)
-        def jvmVersion = System.getProperty("java.vm.specification.version")
-        if (jvmVersion != "11") {
-            def guidance;
-            if (settings.gradle.startParameter.projectProperties.containsKey("android.injected.invoked.from.ide")) {
-                guidance = "Make sure to set the gradle JDK to JDK 11 in the project settings." +
-                        "(File -> Other Settings -> Default Project Structure)"
-            } else {
-                guidance = "Make sure your JAVA_HOME environment variable points to Java 11 JDK."
-            }
-            throw new IllegalStateException("""
-                    AndroidX build must be invoked with JDK 11.
-                    $guidance
-                    Current version: $jvmVersion
-                    Current JAVA HOME: ${System.getProperty("java.home")}""".stripIndent());
-        }
-
-    }
-}
diff --git a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/GradleEnterpriseConventionsPlugin.kt b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/GradleEnterpriseConventionsPlugin.kt
new file mode 100644
index 0000000..ef5a878
--- /dev/null
+++ b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/GradleEnterpriseConventionsPlugin.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.playground
+
+import com.gradle.enterprise.gradleplugin.internal.extension.BuildScanExtensionWithHiddenFeatures
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+import org.gradle.caching.http.HttpBuildCache
+import org.gradle.kotlin.dsl.gradleEnterprise
+import java.net.URI
+
+class GradleEnterpriseConventionsPlugin : Plugin<Settings> {
+    override fun apply(settings: Settings) {
+        settings.apply(mapOf("plugin" to "com.gradle.enterprise"))
+        settings.apply(mapOf("plugin" to "com.gradle.common-custom-user-data-gradle-plugin"))
+
+        // Github Actions always sets a "CI" environment variable
+        val isCI = System.getenv("CI") != null
+
+        settings.gradleEnterprise {
+            server = "https://ge.androidx.dev"
+
+            buildScan.apply {
+                publishAlways()
+                (this as BuildScanExtensionWithHiddenFeatures).publishIfAuthenticated()
+                isUploadInBackground = !isCI
+                capture.isTaskInputFiles = true
+
+                GradleWorkaround.obfuscate(obfuscation)
+            }
+        }
+
+        settings.buildCache.remote(HttpBuildCache::class.java) { remote ->
+            remote.url = URI("https://ge.androidx.dev/cache/")
+            val buildCachePassword = System.getenv("GRADLE_BUILD_CACHE_PASSWORD")
+            if (isCI && !buildCachePassword.isNullOrEmpty()) {
+                remote.isPush = true
+                remote.credentials { credentials ->
+                    credentials.username = "ci"
+                    credentials.password = buildCachePassword
+                }
+            } else {
+                remote.isPush = false
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
new file mode 100644
index 0000000..90a699a
--- /dev/null
+++ b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
@@ -0,0 +1,173 @@
+/*
+ * 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.playground
+
+import org.gradle.api.GradleException
+import org.gradle.api.initialization.Settings
+import org.gradle.api.model.ObjectFactory
+import java.io.File
+import java.util.Properties
+import javax.inject.Inject
+
+open class PlaygroundExtension @Inject constructor(
+    private val settings: Settings,
+    private val objectFactory: ObjectFactory
+) {
+    private var supportRootDir: File? = null
+
+    /**
+     * Includes the project if it does not already exist.
+     * This is invoked from `includeProject` to ensure all parent projects are included. If they are
+     * not, gradle will use the root project path to set the projectDir, which might conflict in
+     * playground. Instead, this method checks if another project in that path exists and if so,
+     * changes the project dir to avoid the conflict.
+     * see b/197253160 for details.
+     */
+    private fun includeFakeParentProjectIfNotExists(name: String, projectDir: File) {
+        if (name.isEmpty()) return
+        if (settings.findProject(name) != null) {
+            return
+        }
+        val actualProjectDir: File = if (settings.findProject(projectDir) != null) {
+            // Project directory conflicts with an existing project (possibly root). Move it
+            // to another directory to avoid the conflict.
+            File(projectDir.parentFile, ".ignore-${projectDir.name}")
+        } else {
+            projectDir
+        }
+        includeProjectAt(name, actualProjectDir)
+        // Set it to a gradle file that does not exist.
+        // We must always include projects starting with root, if we are including nested projects.
+        settings.project(name).buildFileName = "ignored.gradle"
+    }
+
+    private fun includeProjectAt(name: String, projectDir: File) {
+        if (settings.findProject(name) != null) {
+            throw GradleException("Cannot include project twice: $name is already included.")
+        }
+        val parentPath = name.substring(0, name.lastIndexOf(":"))
+        val parentDir = projectDir.parentFile
+        // Make sure parent is created first. see: b/197253160 for details
+        includeFakeParentProjectIfNotExists(
+            parentPath,
+            parentDir
+        )
+        settings.include(name)
+        settings.project(name).projectDir = projectDir
+    }
+
+    /**
+     * Includes a project by name, with a path relative to the root of AndroidX.
+     */
+    fun includeProject(name: String, filePath: String) {
+        if (supportRootDir == null) {
+            throw GradleException("Must call setupPlayground() first.")
+        }
+        includeProjectAt(name, File(supportRootDir, filePath))
+    }
+
+    /**
+     * Initializes the playground project to use public repositories as well as other internal
+     * projects that cannot be found in public repositories.
+     *
+     * @param relativePathToRoot The relative path of the project to the root AndroidX project
+     */
+    fun setupPlayground(relativePathToRoot: String) {
+        val projectDir = settings.rootProject.projectDir
+        val supportRoot = File(projectDir, relativePathToRoot).canonicalFile
+        this.supportRootDir = supportRoot
+        val buildFile = File(supportRoot, "playground-common/playground-build.gradle")
+        val relativePathToBuild = projectDir.toPath().relativize(buildFile.toPath()).toString()
+
+        val playgroundProperties = Properties()
+        val propertiesFile = File(supportRoot, "playground-common/playground.properties")
+        playgroundProperties.load(propertiesFile.inputStream())
+        settings.gradle.beforeProject { project ->
+            // load playground properties. These are not kept in the playground projects to prevent
+            // AndroidX build from reading them.
+            playgroundProperties.forEach {
+                project.extensions.extraProperties[it.key as String] = it.value
+            }
+        }
+
+        settings.rootProject.buildFileName = relativePathToBuild
+        settings.enableFeaturePreview("VERSION_CATALOGS")
+
+        val catalogFiles =
+            objectFactory.fileCollection().from("$supportRoot/gradle/libs.versions.toml")
+        settings.dependencyResolutionManagement {
+            it.versionCatalogs.create("libs").from(catalogFiles)
+        }
+
+        includeProject(":lint-checks", "lint-checks")
+        includeProject(":lint-checks:integration-tests", "lint-checks/integration-tests")
+        includeProject(":fakeannotations", "fakeannotations")
+        includeProject(":internal-testutils-common", "testutils/testutils-common")
+        includeProject(":internal-testutils-gradle-plugin", "testutils/testutils-gradle-plugin")
+
+        // allow public repositories
+        System.setProperty("ALLOW_PUBLIC_REPOS", "true")
+
+        // specify out dir location
+        System.setProperty("CHECKOUT_ROOT", supportRoot.path)
+    }
+
+    /**
+     * A convenience method to include projects from the main AndroidX build using a filter.
+     *
+     * @param filter This filter will be called with the project name (project path in gradle).
+     *               If filter returns true, it will be included in the build.
+     */
+    fun selectProjectsFromAndroidX(filter: (String) -> Boolean) {
+        if (supportRootDir == null) {
+            throw RuntimeException("Must call setupPlayground() first.")
+        }
+
+        // Multiline matcher for anything of the form:
+        //  includeProject(name, path, ...)
+        // where '...' is anything except the ')' character.
+        /* ktlint-disable max-line-length */
+        val includeProjectPattern = Regex(
+            """[\n\r\s]*includeProject\("(?<name>[a-z0-9-:]*)",[\n\r\s]*"(?<path>[a-z0-9-\/]+)[^)]+\)$""",
+            setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE)
+        ).toPattern()
+        val supportSettingsFile = File(supportRootDir, "settings.gradle")
+        val matcher = includeProjectPattern.matcher(supportSettingsFile.readText())
+
+        while (matcher.find()) {
+            // check if is an include project line, if so, extract project gradle path and
+            // file system path and call the filter
+            val projectGradlePath = matcher.group("name")
+            val projectFilePath = matcher.group("path")
+            if (filter(projectGradlePath)) {
+                includeProject(projectGradlePath, projectFilePath)
+            }
+        }
+    }
+
+    /**
+     * Checks if a project is necessary for playground projects that involve compose.
+     */
+    fun isNeededForComposePlayground(name: String): Boolean {
+        if (name == ":compose:lint:common") return true
+        if (name == ":compose:lint:internal-lint-checks") return true
+        if (name == ":compose:test-utils") return true
+        if (name == ":compose:lint:common-test") return true
+        if (name == ":test:screenshot:screenshot") return true
+        return false
+    }
+}
\ No newline at end of file
diff --git a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundPlugin.kt b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundPlugin.kt
new file mode 100644
index 0000000..ff190ae
--- /dev/null
+++ b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundPlugin.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.playground
+
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+
+class PlaygroundPlugin : Plugin<Settings> {
+    override fun apply(settings: Settings) {
+        settings.apply(mapOf("plugin" to "playground-ge-conventions"))
+        settings.extensions.create("playground", PlaygroundExtension::class.java, settings)
+        validateJvm(settings)
+    }
+
+    private fun validateJvm(settings: Settings) {
+        // validate JVM version to print an understandable error if it is not set to the
+        // required value (11)
+        val jvmVersion = System.getProperty("java.vm.specification.version")
+        check(jvmVersion == "11") {
+            """
+                AndroidX build must be invoked with JDK 11.
+                ${
+                    if (settings.gradle.startParameter.projectProperties.containsKey(
+                            "android.injected.invoked.from.ide"
+                        )
+                    ) {
+                        """
+                            Make sure to set the Gradle JDK to JDK 11 in the project settings.
+                            File -> Settings -> Build, Execution, Deployment -> Build Tools ->
+                            Gradle -> Gradle JDK"
+                        """
+                        } else {
+                        "Make sure your JAVA_HOME environment variable points to Java 11 JDK."
+                    }
+                }
+                Current version: $jvmVersion
+                Current JAVA HOME: ${System.getProperty("java.home")}
+            """.trimIndent()
+        }
+    }
+}
\ No newline at end of file
diff --git a/preference/OWNERS b/preference/OWNERS
index 50b530e..cc4dc56 100644
--- a/preference/OWNERS
+++ b/preference/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 lpf@google.com
diff --git a/profileinstaller/integration-tests/init-macrobenchmark/src/androidTest/java/androidx/profileinstaller/integration/macrobenchmark/ProfileinstallerStartupBenchmark.kt b/profileinstaller/integration-tests/init-macrobenchmark/src/androidTest/java/androidx/profileinstaller/integration/macrobenchmark/ProfileinstallerStartupBenchmark.kt
index 83d0a926..4ece2c3 100644
--- a/profileinstaller/integration-tests/init-macrobenchmark/src/androidTest/java/androidx/profileinstaller/integration/macrobenchmark/ProfileinstallerStartupBenchmark.kt
+++ b/profileinstaller/integration-tests/init-macrobenchmark/src/androidTest/java/androidx/profileinstaller/integration/macrobenchmark/ProfileinstallerStartupBenchmark.kt
@@ -20,6 +20,7 @@
 import androidx.benchmark.macro.StartupMode
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 import androidx.test.filters.LargeTest
+import androidx.testutils.BASIC_COMPILATION_MODES
 import androidx.testutils.createStartupCompilationParams
 import androidx.testutils.measureStartup
 import org.junit.Rule
@@ -48,6 +49,8 @@
     companion object {
         @Parameterized.Parameters(name = "startup={0},compilation={1}")
         @JvmStatic
-        fun parameters() = createStartupCompilationParams()
+        fun parameters() = createStartupCompilationParams(
+            compilationModes = BASIC_COMPILATION_MODES
+        )
     }
 }
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
index 60e92ca..a644cdd 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
@@ -20,7 +20,7 @@
 import androidx.room.compiler.processing.ksp.KSFileAsOriginatingElement
 import androidx.room.compiler.processing.ksp.KspElement
 import androidx.room.compiler.processing.ksp.KspMemberContainer
-import androidx.room.compiler.processing.ksp.containingFileAsOriginatingElement
+import androidx.room.compiler.processing.ksp.wrapAsOriginatingElement
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
 import javax.lang.model.element.Element
 import kotlin.contracts.contract
@@ -129,13 +129,13 @@
     return when (this) {
         is JavacElement -> element
         is KspElement -> {
-            declaration.containingFileAsOriginatingElement()
+            declaration.wrapAsOriginatingElement()
         }
         is KspSyntheticPropertyMethodElement -> {
-            field.declaration.containingFileAsOriginatingElement()
+            field.declaration.wrapAsOriginatingElement()
         }
         is KspMemberContainer -> {
-            declaration?.containingFileAsOriginatingElement()
+            declaration?.wrapAsOriginatingElement()
         }
         else -> error("Originating element is not implemented for ${this.javaClass}")
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
index f10956c..20f735b 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSAnnotatedExt.kt
@@ -17,6 +17,7 @@
 package androidx.room.compiler.processing.ksp
 
 import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSDeclaration
 
 private fun KSAnnotated.hasAnnotationWithQName(qName: String) = annotations.any {
@@ -33,11 +34,15 @@
 internal fun KSAnnotated.hasJvmDefaultAnnotation() = hasAnnotationWithQName("kotlin.jvm.JvmDefault")
 
 /**
- * Return a reference to the containing file that implements the
+ * Return a reference to the containing file or class declaration via a wrapper that implements the
  * [javax.lang.model.element.Element] API so that we can report it to JavaPoet.
  */
-internal fun KSAnnotated.containingFileAsOriginatingElement(): KSFileAsOriginatingElement? {
-    return (this as? KSDeclaration)?.containingFile?.let {
+internal fun KSAnnotated.wrapAsOriginatingElement(): OriginatingElementWrapper? {
+    val ksDeclaration = this as? KSDeclaration ?: return null
+
+    return ksDeclaration.containingFile?.let {
         KSFileAsOriginatingElement(it)
+    } ?: (ksDeclaration as? KSClassDeclaration)?.let {
+        KSClassDeclarationAsOriginatingElement(it)
     }
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
index e2a0758..373d9607 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFiler.kt
@@ -21,6 +21,7 @@
 import androidx.room.compiler.processing.util.ISSUE_TRACKER_LINK
 import com.google.devtools.ksp.processing.CodeGenerator
 import com.google.devtools.ksp.processing.Dependencies
+import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSFile
 import com.squareup.javapoet.JavaFile
 import com.squareup.kotlinpoet.FileSpec
@@ -34,11 +35,11 @@
     private val messager: XMessager,
 ) : XFiler {
     override fun write(javaFile: JavaFile, mode: XFiler.Mode) {
-        val originatingFiles = javaFile.typeSpec.originatingElements
-            .map(::originatingFileFor)
+        val originatingElements = javaFile.typeSpec.originatingElements
+            .toOriginatingElements()
 
         createNewFile(
-            originatingFiles = originatingFiles,
+            originatingElements = originatingElements,
             packageName = javaFile.packageName,
             fileName = javaFile.typeSpec.name,
             extensionName = "java",
@@ -51,13 +52,13 @@
     }
 
     override fun write(fileSpec: FileSpec, mode: XFiler.Mode) {
-        val originatingFiles = fileSpec.members
+        val originatingElements = fileSpec.members
             .filterIsInstance<OriginatingElementsHolder>()
             .flatMap { it.originatingElements }
-            .map(::originatingFileFor)
+            .toOriginatingElements()
 
         createNewFile(
-            originatingFiles = originatingFiles,
+            originatingElements = originatingElements,
             packageName = fileSpec.packageName,
             fileName = fileSpec.name,
             extensionName = "kt",
@@ -69,21 +70,14 @@
         }
     }
 
-    private fun originatingFileFor(element: Element): KSFile {
-        check(element is KSFileAsOriginatingElement) {
-            "Unexpected element type in originating elements. $element"
-        }
-        return element.ksFile
-    }
-
     private fun createNewFile(
-        originatingFiles: List<KSFile>,
+        originatingElements: OriginatingElements,
         packageName: String,
         fileName: String,
         extensionName: String,
         aggregating: Boolean
     ): OutputStream {
-        val dependencies = if (originatingFiles.isEmpty()) {
+        val dependencies = if (originatingElements.isEmpty()) {
             messager.printMessage(
                 Diagnostic.Kind.WARNING,
                 """
@@ -96,7 +90,16 @@
         } else {
             Dependencies(
                 aggregating = aggregating,
-                sources = originatingFiles.distinct().toTypedArray()
+                sources = originatingElements.files.distinct().toTypedArray()
+            )
+        }
+
+        if (originatingElements.classes.isNotEmpty()) {
+            delegate.associateWithClasses(
+                classes = originatingElements.classes,
+                packageName = packageName,
+                fileName = fileName,
+                extensionName = extensionName
             )
         }
 
@@ -107,4 +110,26 @@
             extensionName = extensionName
         )
     }
+
+    private data class OriginatingElements(
+        val files: List<KSFile>,
+        val classes: List<KSClassDeclaration>,
+    ) {
+        fun isEmpty(): Boolean = files.isEmpty() && classes.isEmpty()
+    }
+
+    private fun List<Element>.toOriginatingElements(): OriginatingElements {
+        val files = mutableListOf<KSFile>()
+        val classes = mutableListOf<KSClassDeclaration>()
+
+        forEach { element ->
+            when (element) {
+                is KSFileAsOriginatingElement -> files.add(element.ksFile)
+                is KSClassDeclarationAsOriginatingElement -> classes.add(element.ksClassDeclaration)
+                else -> error("Unexpected element type in originating elements. $element")
+            }
+        }
+
+        return OriginatingElements(files, classes)
+    }
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSFileAsOriginatingElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OriginatingElementWrappers.kt
similarity index 72%
rename from room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSFileAsOriginatingElement.kt
rename to room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OriginatingElementWrappers.kt
index ec05ba1..30aaa85 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSFileAsOriginatingElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/OriginatingElementWrappers.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing.ksp
 
+import com.google.devtools.ksp.symbol.KSClassDeclaration
 import com.google.devtools.ksp.symbol.KSFile
 import javax.lang.model.element.AnnotationMirror
 import javax.lang.model.element.Element
@@ -26,12 +27,27 @@
 import javax.lang.model.type.TypeMirror
 
 /**
- * When generating java code, JavaPoet only provides an API that receives Element.
- * This wrapper class helps us wrap a KSFile as an originating element and KspFiler unwraps it to
- * get the actual KSFile out of it.
+ * Implementation of [OriginatingElementWrapper] to wrap a [KSFile] for the case of a dependency
+ * within the sources being processed.
  */
 internal data class KSFileAsOriginatingElement(
     val ksFile: KSFile
+) : OriginatingElementWrapper(ksFile.fileName)
+
+/**
+ * Implementation of [OriginatingElementWrapper] to wrap a [KSClassDeclaration] for the case of
+ * a dependency in the classpath, in which case a [KSFile] is not available.
+ */
+internal data class KSClassDeclarationAsOriginatingElement(
+    val ksClassDeclaration: KSClassDeclaration
+) : OriginatingElementWrapper(ksClassDeclaration.simpleName.asString())
+
+/**
+ * When generating java code, JavaPoet only provides an API that receives Element.
+ * This wrapper class helps us wrap KSP constructs which KspFiler can unwrap later.
+ */
+internal sealed class OriginatingElementWrapper(
+    val elementSimpleName: String
 ) : Element {
     override fun getAnnotationMirrors(): List<AnnotationMirror> {
         return emptyList()
@@ -48,7 +64,7 @@
 
     override fun asType(): TypeMirror {
         throw UnsupportedOperationException(
-            "KSFileAsOriginatingElement cannot be converted to a type"
+            "${this::class.simpleName} cannot be converted to a type"
         )
     }
 
@@ -61,7 +77,7 @@
     }
 
     override fun getSimpleName(): Name {
-        return NameImpl(ksFile.fileName)
+        return NameImpl(elementSimpleName)
     }
 
     override fun getEnclosingElement(): Element? {
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/OriginatingElementsTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/OriginatingElementsTest.kt
index e32fb9a..1c18366 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/OriginatingElementsTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/OriginatingElementsTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.room.compiler.processing
 
+import androidx.room.compiler.processing.ksp.KSClassDeclarationAsOriginatingElement
 import androidx.room.compiler.processing.ksp.KSFileAsOriginatingElement
 import androidx.room.compiler.processing.ksp.KspTypeElement
 import androidx.room.compiler.processing.ksp.synthetic.KspSyntheticPropertyMethodElement
@@ -72,6 +73,34 @@
     }
 
     @Test
+    fun classPathTypeIsConvertedToOriginatingElement() {
+        runProcessorTest {
+            val element = it.processingEnv
+                .requireTypeElement("com.google.devtools.ksp.processing.SymbolProcessor")
+
+            val originatingElement = element.originatingElementForPoet()
+            assertThat(originatingElement).isNotNull()
+
+            if (it.isKsp) {
+                assertThat(originatingElement)
+                    .isInstanceOf(KSClassDeclarationAsOriginatingElement::class.java)
+
+                val ksClassDeclaration =
+                    (originatingElement as KSClassDeclarationAsOriginatingElement)
+                        .ksClassDeclaration
+                assertThat(ksClassDeclaration)
+                    .isEqualTo(
+                        (element as KspTypeElement).declaration
+                    )
+            } else {
+                assertThat(originatingElement).isInstanceOf(TypeElement::class.java)
+                assertThat((originatingElement as TypeElement).qualifiedName.toString())
+                    .isEqualTo("com.google.devtools.ksp.processing.SymbolProcessor")
+            }
+        }
+    }
+
+    @Test
     fun syntheticPropertyElementConvertedToOriginatingElement() {
         runProcessorTest(
             sources = listOf(
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFilerTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFilerTest.kt
index 252acfc..e3cbe2f 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFilerTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspFilerTest.kt
@@ -93,6 +93,56 @@
         }
     }
 
+    @Test
+    fun originatingClassAddedForClassPathAndFileType() {
+        runKspTest(sources = listOf(simpleKotlinClass)) { invocation ->
+            val sourceElement = invocation.processingEnv.requireTypeElement("foo.bar.Baz")
+            val classPathElement = invocation.processingEnv
+                .requireTypeElement("com.google.devtools.ksp.processing.SymbolProcessor")
+
+            val fileWithType = FileSpec.builder("foo", "Bar.kt").apply {
+                addType(
+                    TypeSpec.classBuilder("Bar").apply {
+                        addOriginatingElement(sourceElement)
+                        addOriginatingElement(classPathElement)
+                    }.build()
+                )
+            }.build()
+
+            val codeGenerator = DependencyTrackingCodeGenerator()
+            KspFiler(codeGenerator, TestMessager()).write(fileWithType)
+            codeGenerator.fileDependencies[fileWithType.name]
+                .containsExactlySimpleKotlinClass()
+            val (file, classDeclarations) = codeGenerator.classDependencies.entries.single()
+            assertThat(file).isEqualTo("Bar.kt")
+            assertThat(classDeclarations.single())
+                .isEqualTo((classPathElement as KspTypeElement).declaration)
+        }
+    }
+
+    @Test
+    fun originatingClassAddedForClassPathType() {
+        runKspTest(sources = listOf()) { invocation ->
+            val classPathElement = invocation.processingEnv
+                .requireTypeElement("com.google.devtools.ksp.processing.SymbolProcessor")
+
+            val fileWithType = FileSpec.builder("foo", "Bar.kt").apply {
+                addType(
+                    TypeSpec.classBuilder("Bar").apply {
+                        addOriginatingElement(classPathElement)
+                    }.build()
+                )
+            }.build()
+
+            val codeGenerator = DependencyTrackingCodeGenerator()
+            KspFiler(codeGenerator, TestMessager()).write(fileWithType)
+            val (file, classDeclarations) = codeGenerator.classDependencies.entries.single()
+            assertThat(file).isEqualTo("Bar.kt")
+            assertThat(classDeclarations.single())
+                .isEqualTo((classPathElement as KspTypeElement).declaration)
+        }
+    }
+
     private fun Dependencies?.containsExactlySimpleKotlinClass() {
         assertThat(this).isNotNull()
         val originatingFiles = this!!.originatingFiles.map { it.fileName }
@@ -122,6 +172,7 @@
     class DependencyTrackingCodeGenerator : CodeGenerator {
 
         val fileDependencies = mutableMapOf<String, Dependencies>()
+        val classDependencies = mutableMapOf<String, MutableSet<KSClassDeclaration>>()
 
         override val generatedFile: Collection<File>
             get() = emptyList()
@@ -141,7 +192,7 @@
             fileName: String,
             extensionName: String
         ) {
-            // no-op required override.
+            classDependencies.getOrPut(fileName) { mutableSetOf() }.addAll(classes)
         }
 
         override fun createNewFile(
diff --git a/room/room-paging/build.gradle b/room/room-paging/build.gradle
index 42d90c5..b25cd0d 100644
--- a/room/room-paging/build.gradle
+++ b/room/room-paging/build.gradle
@@ -47,7 +47,7 @@
 
     implementation(project(":room:room-runtime"))
     implementation(project(":room:room-ktx"))
-    api("androidx.paging:paging-common:3.1.0-beta01")
+    api("androidx.paging:paging-common:3.1.0")
 
     androidTestImplementation(libs.kotlinCoroutinesTest)
     androidTestImplementation(libs.multidex)
diff --git a/room/room-runtime/build.gradle b/room/room-runtime/build.gradle
index 44afc76..48cdb86 100644
--- a/room/room-runtime/build.gradle
+++ b/room/room-runtime/build.gradle
@@ -34,8 +34,8 @@
 
 dependencies {
     api(project(":room:room-common"))
-    api("androidx.sqlite:sqlite-framework:2.2.0-beta01")
-    api("androidx.sqlite:sqlite:2.2.0-beta01")
+    api(project(":sqlite:sqlite-framework"))
+    api(project(":sqlite:sqlite"))
     implementation("androidx.arch.core:core-runtime:2.0.1")
     compileOnly("androidx.paging:paging-common:2.0.0")
     compileOnly("androidx.lifecycle:lifecycle-livedata-core:2.0.0")
diff --git a/room/room-testing/build.gradle b/room/room-testing/build.gradle
index d665ee7..1c0acde 100644
--- a/room/room-testing/build.gradle
+++ b/room/room-testing/build.gradle
@@ -25,8 +25,8 @@
 dependencies {
     api(project(":room:room-common"))
     api(project(":room:room-runtime"))
-    api("androidx.sqlite:sqlite:2.2.0-beta01")
-    api("androidx.sqlite:sqlite-framework:2.2.0-beta01")
+    api(project(":sqlite:sqlite"))
+    api(project(":sqlite:sqlite-framework"))
     api(project(":room:room-migration"))
     implementation("androidx.arch.core:core-runtime:2.0.1")
     api(libs.junit)
diff --git a/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java b/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java
index bc37aa5..25a6bbc 100644
--- a/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java
+++ b/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityDelegateSupportActivity.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 
+import androidx.annotation.NonNull;
 import androidx.core.view.AccessibilityDelegateCompat;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
@@ -73,7 +74,8 @@
             // introduced the delegate off the developer.
             ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegateCompat() {
                 @Override
-                public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+                public void onPopulateAccessibilityEvent(
+                        @NonNull View host, @NonNull AccessibilityEvent event) {
                     super.onPopulateAccessibilityEvent(host, event);
                     // Note that View.onPopulateAccessibilityEvent was introduced in
                     // ICS and we would like to tweak a bit the text that is reported to
@@ -83,8 +85,8 @@
                 }
 
                 @Override
-                public void onInitializeAccessibilityNodeInfo(View host,
-                        AccessibilityNodeInfoCompat info) {
+                public void onInitializeAccessibilityNodeInfo(@NonNull View host,
+                        @NonNull AccessibilityNodeInfoCompat info) {
                     super.onInitializeAccessibilityNodeInfo(host, info);
                     // Note that View.onInitializeAccessibilityNodeInfo was introduced in
                     // ICS and we would like to tweak a bit the text that is reported to
diff --git a/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityRoleDescriptionSupportActivity.java b/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityRoleDescriptionSupportActivity.java
index 963690a..2dbb078 100644
--- a/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityRoleDescriptionSupportActivity.java
+++ b/samples/Support4Demos/src/main/java/com/example/android/supportv4/accessibility/AccessibilityRoleDescriptionSupportActivity.java
@@ -22,6 +22,7 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
 import androidx.core.view.AccessibilityDelegateCompat;
 import androidx.core.view.ViewCompat;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
@@ -86,8 +87,8 @@
         }
 
         @Override
-        public void onInitializeAccessibilityNodeInfo(View host,
-                AccessibilityNodeInfoCompat info) {
+        public void onInitializeAccessibilityNodeInfo(@NonNull View host,
+                @NonNull AccessibilityNodeInfoCompat info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
             // This call will succeed on all platforms, but it will only set the role description
             // on devices running KitKat (API 19) or later. On older platforms the method call
diff --git a/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java b/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
index dc5253e..6f72b20 100644
--- a/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
+++ b/samples/Support7Demos/src/main/java/com/example/android/supportv7/media/SampleMediaRouterActivity.java
@@ -756,7 +756,7 @@
         @Override
         public MediaRouterParams getRouterParams() {
             return new MediaRouterParams.Builder(super.getRouterParams())
-                    .setMediaTransferReceiverDisabled(true)
+                    .setMediaTransferReceiverEnabled(false)
                     .build();
         }
     }
diff --git a/samples/SupportPreferenceDemos/OWNERS b/samples/SupportPreferenceDemos/OWNERS
index f1b8c7e..b2c38b4 100644
--- a/samples/SupportPreferenceDemos/OWNERS
+++ b/samples/SupportPreferenceDemos/OWNERS
@@ -1,2 +1 @@
-pavlis@google.com
 lpf@google.com
\ No newline at end of file
diff --git a/savedstate/OWNERS b/savedstate/OWNERS
index 8f61468..cf853fe 100644
--- a/savedstate/OWNERS
+++ b/savedstate/OWNERS
@@ -1,3 +1,5 @@
 ilake@google.com
+jbwoods@google.com
+sanura@google.com
 sergeyv@google.com
 yboyar@google.com
diff --git a/savedstate/savedstate/src/androidTest/java/androidx/savedstate/SavedStateRegistryTest.kt b/savedstate/savedstate/src/androidTest/java/androidx/savedstate/SavedStateRegistryTest.kt
index 702bb98..0bac387 100644
--- a/savedstate/savedstate/src/androidTest/java/androidx/savedstate/SavedStateRegistryTest.kt
+++ b/savedstate/savedstate/src/androidTest/java/androidx/savedstate/SavedStateRegistryTest.kt
@@ -24,6 +24,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -172,6 +173,17 @@
 
     @UiThreadTest
     @Test
+    fun emptyBundle() {
+        val owner = FakeSavedStateRegistryOwner()
+        val outBundle = Bundle()
+        owner.savedStateRegistryController.performSave(outBundle)
+        assertWithMessage("Bundle $outBundle should be empty")
+            .that(outBundle.isEmpty)
+            .isTrue()
+    }
+
+    @UiThreadTest
+    @Test
     fun runOnNextRecreationFromEarlyRegisteredObserver() {
         val owner = FakeSavedStateRegistryOwner()
         owner.savedStateRegistryController.performAttach()
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.java b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.java
index a8a4ef2..adeae54 100644
--- a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.java
+++ b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.java
@@ -239,7 +239,9 @@
             Map.Entry<String, SavedStateProvider> entry1 = it.next();
             components.putBundle(entry1.getKey(), entry1.getValue().saveState());
         }
-        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
+        if (!components.isEmpty()) {
+            outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
+        }
     }
 
     /**
diff --git a/settings.gradle b/settings.gradle
index 40046e4..7d8f07b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -427,6 +427,7 @@
 includeProject(":core:core-google-shortcuts", "core/core-google-shortcuts", [BuildType.MAIN])
 includeProject(":core:core-ktx", "core/core-ktx", [BuildType.MAIN])
 includeProject(":core:core-performance", "core/core-performance", [BuildType.MAIN])
+includeProject(":core:core-performance:core-performance-samples", "core/core-performance/samples", [BuildType.MAIN])
 includeProject(":core:core-remoteviews", "core/core-remoteviews", [BuildType.MAIN])
 includeProject(":core:core-remoteviews:integration-tests:demos", "core/core-remoteviews/integration-tests/demos", [BuildType.MAIN])
 includeProject(":core:core-splashscreen", "core/core-splashscreen", [BuildType.MAIN])
diff --git a/slice/slice-view/src/main/res/values-it/strings.xml b/slice/slice-view/src/main/res/values-it/strings.xml
index 9087d7a..62c8052 100644
--- a/slice/slice-view/src/main/res/values-it/strings.xml
+++ b/slice/slice-view/src/main/res/values-it/strings.xml
@@ -22,16 +22,16 @@
     <string name="abc_slice_show_more" msgid="1112789899890391107">"Mostra altro"</string>
     <string name="abc_slice_updated" msgid="7932359091871934205">"Ultimo aggiornamento: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <plurals name="abc_slice_duration_min" formatted="false" msgid="7664017844210142826">
+      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> min fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min fa</item>
     </plurals>
     <plurals name="abc_slice_duration_years" formatted="false" msgid="2628491538787454021">
+      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> anno fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> anni fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> anno fa</item>
     </plurals>
     <plurals name="abc_slice_duration_days" formatted="false" msgid="8356547162075064530">
+      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> giorno fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> giorni fa</item>
-      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> giorno fa</item>
     </plurals>
     <string name="abc_slice_error" msgid="1794214973158263497">"Impossibile collegarsi"</string>
 </resources>
diff --git a/slice/slice-view/src/main/res/values-pt-rPT/strings.xml b/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
index 34a67ff..08c5c19 100644
--- a/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
+++ b/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
@@ -22,16 +22,16 @@
     <string name="abc_slice_show_more" msgid="1112789899890391107">"Mostrar mais"</string>
     <string name="abc_slice_updated" msgid="7932359091871934205">"Atualização: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <plurals name="abc_slice_duration_min" formatted="false" msgid="7664017844210142826">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> min</item>
       <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> min</item>
+      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> min</item>
     </plurals>
     <plurals name="abc_slice_duration_years" formatted="false" msgid="2628491538787454021">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> anos</item>
       <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> ano</item>
+      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> anos</item>
     </plurals>
     <plurals name="abc_slice_duration_days" formatted="false" msgid="8356547162075064530">
-      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> dias</item>
       <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> dia</item>
+      <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> dias</item>
     </plurals>
     <string name="abc_slice_error" msgid="1794214973158263497">"Não foi possível ligar"</string>
 </resources>
diff --git a/testutils/testutils-macrobenchmark/src/main/java/androidx/testutils/MacrobenchUtils.kt b/testutils/testutils-macrobenchmark/src/main/java/androidx/testutils/MacrobenchUtils.kt
index ad1ce6b..42a98af 100644
--- a/testutils/testutils-macrobenchmark/src/main/java/androidx/testutils/MacrobenchUtils.kt
+++ b/testutils/testutils-macrobenchmark/src/main/java/androidx/testutils/MacrobenchUtils.kt
@@ -27,14 +27,33 @@
 import androidx.benchmark.macro.junit4.MacrobenchmarkRule
 
 /**
- * Default compilation modes to test for all AndroidX macrobenchmarks.
+ * Basic, always-usable compilation modes, when baseline profiles aren't available.
+ *
+ * Over time, it's expected very few macrobenchmarks will reference this directly, as more libraries
+ * gain baseline profiles.
  */
-val COMPILATION_MODES = listOf(
-    CompilationMode.None,
-    CompilationMode.Interpreted,
-    CompilationMode.BaselineProfile,
-    CompilationMode.SpeedProfile()
-)
+val BASIC_COMPILATION_MODES = if (Build.VERSION.SDK_INT < 24) {
+    // other modes aren't supported
+    listOf(CompilationMode.None)
+} else {
+    listOf(
+        CompilationMode.None,
+        CompilationMode.Interpreted,
+        CompilationMode.SpeedProfile()
+    )
+}
+
+/**
+ * Default compilation modes to test for all AndroidX macrobenchmarks.
+ *
+ * Baseline profiles are only supported from Nougat (API 24),
+ * currently through Android 11 (API 30)
+ */
+val COMPILATION_MODES = if (Build.VERSION.SDK_INT in 24..30) {
+    listOf(CompilationMode.BaselineProfile)
+} else {
+    emptyList()
+} + BASIC_COMPILATION_MODES
 
 /**
  * Temporary, while transitioning to new metrics
@@ -73,7 +92,11 @@
         StartupMode.HOT,
         StartupMode.WARM,
         StartupMode.COLD
-    ),
+    ).filter {
+        // skip StartupMode.HOT on Angler, API 23 - it works locally with same build on Bullhead,
+        // but not in Jetpack CI (b/204572406)
+        !(Build.VERSION.SDK_INT == 23 && it == StartupMode.HOT && Build.DEVICE == "angler")
+    },
     compilationModes: List<CompilationMode> = COMPILATION_MODES
 ): List<Array<Any>> = mutableListOf<Array<Any>>().apply {
     for (startupMode in startupModes) {
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt b/text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt
index 2de2410..982d05c 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt
@@ -24,6 +24,10 @@
 /**
  * Iterates through a [List] using the index and calls [action] for each item.
  * This does not allocate an iterator like [Iterable.forEach].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
@@ -37,6 +41,10 @@
 /**
  * Applies the given [transform] function to each element of the original collection
  * and appends the results to the given [destination].
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R, C : MutableCollection<in R>> List<T>.fastMapTo(
@@ -55,6 +63,10 @@
  * to each pair of two adjacent elements in this collection.
  *
  * The returned list is empty if this collection contains less than two elements.
+ *
+ * **Do not use for collections that come from public APIs**, since they may not support random
+ * access in an efficient way, and this method may actually be a lot slower. Only use for
+ * collections that are created by code we control and are known to support random access.
  */
 @OptIn(ExperimentalContracts::class)
 internal inline fun <T, R> List<T>.fastZipWithNext(transform: (T, T) -> R): List<R> {
diff --git a/wear/benchmark/integration-tests/macrobenchmark-target/build.gradle b/wear/benchmark/integration-tests/macrobenchmark-target/build.gradle
index 78ff9ef..8b165bb 100644
--- a/wear/benchmark/integration-tests/macrobenchmark-target/build.gradle
+++ b/wear/benchmark/integration-tests/macrobenchmark-target/build.gradle
@@ -40,5 +40,6 @@
     implementation projectOrArtifact(":activity:activity-ktx")
     implementation 'androidx.core:core-ktx'
     implementation(libs.material)
+    implementation(project(":profileinstaller:profileinstaller"))
     implementation 'androidx.wear:wear:1.1.0'
 }
diff --git a/wear/compose/compose-material/api/current.txt b/wear/compose/compose-material/api/current.txt
index a63d79c..8eab278 100644
--- a/wear/compose/compose-material/api/current.txt
+++ b/wear/compose/compose-material/api/current.txt
@@ -145,15 +145,15 @@
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getButtonsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getChipsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getConfirmationContentPadding();
-    method public long getIndefiniteDuration();
-    method public long getLongDuration();
-    method public long getShortDuration();
+    method public long getIndefiniteDurationMillis();
+    method public long getLongDurationMillis();
+    method public long getShortDurationMillis();
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ButtonsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ChipsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ConfirmationContentPadding;
-    property public final long IndefiniteDuration;
-    property public final long LongDuration;
-    property public final long ShortDuration;
+    property public final long IndefiniteDurationMillis;
+    property public final long LongDurationMillis;
+    property public final long ShortDurationMillis;
     field public static final androidx.wear.compose.material.DialogDefaults INSTANCE;
   }
 
@@ -178,7 +178,9 @@
   public final class InlineSliderDefaults {
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material.InlineSliderColors colors(optional long backgroundColor, optional long spacerColor, optional long selectedBarColor, optional long unselectedBarColor, optional long disabledBackgroundColor, optional long disabledSpacerColor, optional long disabledSelectedBarColor, optional long disabledUnselectedBarColor);
     method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
     property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
     field public static final androidx.wear.compose.material.InlineSliderDefaults INSTANCE;
   }
 
@@ -233,7 +235,7 @@
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.ScrollState scrollState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.ScalingLazyListState scalingLazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.lazy.LazyListState lazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
-    method @androidx.compose.runtime.Composable public static void PositionIndicator(float rsbRatio, optional androidx.compose.ui.Modifier modifier, optional long color, optional boolean reverseDirection);
+    method @androidx.compose.runtime.Composable public static void PositionIndicator(kotlin.jvm.functions.Function0<java.lang.Float> value, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> range, optional long color, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.PositionIndicatorState state, float indicatorHeight, float indicatorWidth, float paddingRight, optional androidx.compose.ui.Modifier modifier, optional long color, optional long background, optional boolean autoHide, optional boolean reverseDirection);
   }
 
@@ -243,6 +245,9 @@
     property public abstract float positionFraction;
   }
 
+  public final class RangeDefaultsKt {
+  }
+
   public final class Resources_androidKt {
   }
 
@@ -366,6 +371,18 @@
     method @androidx.compose.runtime.Composable public static void InlineSlider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional boolean segmented, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional androidx.wear.compose.material.InlineSliderColors colors);
   }
 
+  public final class StepperDefaults {
+    method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
+    property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
+    field public static final androidx.wear.compose.material.StepperDefaults INSTANCE;
+  }
+
+  public final class StepperKt {
+    method @androidx.compose.runtime.Composable public static void Stepper(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional long backgroundColor, optional long contentColor, optional long iconTintColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class SwipeToDismissBoxKt {
   }
 
diff --git a/wear/compose/compose-material/api/public_plus_experimental_current.txt b/wear/compose/compose-material/api/public_plus_experimental_current.txt
index 8855f3c..789634c 100644
--- a/wear/compose/compose-material/api/public_plus_experimental_current.txt
+++ b/wear/compose/compose-material/api/public_plus_experimental_current.txt
@@ -145,15 +145,15 @@
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getButtonsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getChipsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getConfirmationContentPadding();
-    method public long getIndefiniteDuration();
-    method public long getLongDuration();
-    method public long getShortDuration();
+    method public long getIndefiniteDurationMillis();
+    method public long getLongDurationMillis();
+    method public long getShortDurationMillis();
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ButtonsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ChipsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ConfirmationContentPadding;
-    property public final long IndefiniteDuration;
-    property public final long LongDuration;
-    property public final long ShortDuration;
+    property public final long IndefiniteDurationMillis;
+    property public final long LongDurationMillis;
+    property public final long ShortDurationMillis;
     field public static final androidx.wear.compose.material.DialogDefaults INSTANCE;
   }
 
@@ -193,7 +193,9 @@
   public final class InlineSliderDefaults {
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material.InlineSliderColors colors(optional long backgroundColor, optional long spacerColor, optional long selectedBarColor, optional long unselectedBarColor, optional long disabledBackgroundColor, optional long disabledSpacerColor, optional long disabledSelectedBarColor, optional long disabledUnselectedBarColor);
     method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
     property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
     field public static final androidx.wear.compose.material.InlineSliderDefaults INSTANCE;
   }
 
@@ -248,7 +250,7 @@
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.ScrollState scrollState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.ScalingLazyListState scalingLazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.lazy.LazyListState lazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
-    method @androidx.compose.runtime.Composable public static void PositionIndicator(float rsbRatio, optional androidx.compose.ui.Modifier modifier, optional long color, optional boolean reverseDirection);
+    method @androidx.compose.runtime.Composable public static void PositionIndicator(kotlin.jvm.functions.Function0<java.lang.Float> value, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> range, optional long color, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.PositionIndicatorState state, float indicatorHeight, float indicatorWidth, float paddingRight, optional androidx.compose.ui.Modifier modifier, optional long color, optional long background, optional boolean autoHide, optional boolean reverseDirection);
   }
 
@@ -258,6 +260,9 @@
     property public abstract float positionFraction;
   }
 
+  public final class RangeDefaultsKt {
+  }
+
   @androidx.compose.runtime.Immutable @androidx.wear.compose.material.ExperimentalWearMaterialApi public final class ResistanceConfig {
     ctor public ResistanceConfig(float basis, optional float factorAtMin, optional float factorAtMax);
     method public float computeResistance(float overflow);
@@ -392,6 +397,18 @@
     method @androidx.compose.runtime.Composable public static void InlineSlider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional boolean segmented, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional androidx.wear.compose.material.InlineSliderColors colors);
   }
 
+  public final class StepperDefaults {
+    method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
+    property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
+    field public static final androidx.wear.compose.material.StepperDefaults INSTANCE;
+  }
+
+  public final class StepperKt {
+    method @androidx.compose.runtime.Composable public static void Stepper(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional long backgroundColor, optional long contentColor, optional long iconTintColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   @androidx.wear.compose.material.ExperimentalWearMaterialApi public enum SwipeDismissTarget {
     enum_constant public static final androidx.wear.compose.material.SwipeDismissTarget Dismissal;
     enum_constant public static final androidx.wear.compose.material.SwipeDismissTarget Original;
diff --git a/wear/compose/compose-material/api/restricted_current.txt b/wear/compose/compose-material/api/restricted_current.txt
index a63d79c..8eab278 100644
--- a/wear/compose/compose-material/api/restricted_current.txt
+++ b/wear/compose/compose-material/api/restricted_current.txt
@@ -145,15 +145,15 @@
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getButtonsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getChipsContentPadding();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues getConfirmationContentPadding();
-    method public long getIndefiniteDuration();
-    method public long getLongDuration();
-    method public long getShortDuration();
+    method public long getIndefiniteDurationMillis();
+    method public long getLongDurationMillis();
+    method public long getShortDurationMillis();
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ButtonsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ChipsContentPadding;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.PaddingValues ConfirmationContentPadding;
-    property public final long IndefiniteDuration;
-    property public final long LongDuration;
-    property public final long ShortDuration;
+    property public final long IndefiniteDurationMillis;
+    property public final long LongDurationMillis;
+    property public final long ShortDurationMillis;
     field public static final androidx.wear.compose.material.DialogDefaults INSTANCE;
   }
 
@@ -178,7 +178,9 @@
   public final class InlineSliderDefaults {
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material.InlineSliderColors colors(optional long backgroundColor, optional long spacerColor, optional long selectedBarColor, optional long unselectedBarColor, optional long disabledBackgroundColor, optional long disabledSpacerColor, optional long disabledSelectedBarColor, optional long disabledUnselectedBarColor);
     method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
     property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
     field public static final androidx.wear.compose.material.InlineSliderDefaults INSTANCE;
   }
 
@@ -233,7 +235,7 @@
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.ScrollState scrollState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.ScalingLazyListState scalingLazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.compose.foundation.lazy.LazyListState lazyListState, optional androidx.compose.ui.Modifier modifier, optional boolean reverseDirection);
-    method @androidx.compose.runtime.Composable public static void PositionIndicator(float rsbRatio, optional androidx.compose.ui.Modifier modifier, optional long color, optional boolean reverseDirection);
+    method @androidx.compose.runtime.Composable public static void PositionIndicator(kotlin.jvm.functions.Function0<java.lang.Float> value, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> range, optional long color, optional boolean reverseDirection);
     method @androidx.compose.runtime.Composable public static void PositionIndicator(androidx.wear.compose.material.PositionIndicatorState state, float indicatorHeight, float indicatorWidth, float paddingRight, optional androidx.compose.ui.Modifier modifier, optional long color, optional long background, optional boolean autoHide, optional boolean reverseDirection);
   }
 
@@ -243,6 +245,9 @@
     property public abstract float positionFraction;
   }
 
+  public final class RangeDefaultsKt {
+  }
+
   public final class Resources_androidKt {
   }
 
@@ -366,6 +371,18 @@
     method @androidx.compose.runtime.Composable public static void InlineSlider(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional boolean segmented, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional androidx.wear.compose.material.InlineSliderColors colors);
   }
 
+  public final class StepperDefaults {
+    method public androidx.compose.ui.graphics.vector.ImageVector getDecreaseIcon();
+    method public androidx.compose.ui.graphics.vector.ImageVector getIncreaseIcon();
+    property public final androidx.compose.ui.graphics.vector.ImageVector DecreaseIcon;
+    property public final androidx.compose.ui.graphics.vector.ImageVector IncreaseIcon;
+    field public static final androidx.wear.compose.material.StepperDefaults INSTANCE;
+  }
+
+  public final class StepperKt {
+    method @androidx.compose.runtime.Composable public static void Stepper(float value, kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit> onValueChange, int steps, optional androidx.compose.ui.Modifier modifier, optional kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> valueRange, optional kotlin.jvm.functions.Function0<kotlin.Unit> decreaseIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit> increaseIcon, optional long backgroundColor, optional long contentColor, optional long iconTintColor, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+  }
+
   public final class SwipeToDismissBoxKt {
   }
 
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
index c5aab1b..7f6b6ed 100644
--- a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/DialogSample.kt
@@ -19,6 +19,8 @@
 import androidx.annotation.Sampled
 import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi
 import androidx.compose.animation.graphics.res.animatedVectorResource
+import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
+import androidx.compose.animation.graphics.vector.AnimatedImageVector
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -114,7 +116,7 @@
 @Sampled
 @Composable
 fun ConfirmationDialogWithAnimation() {
-    val animation = animatedVectorResource(id = R.drawable.open_on_phone_animation)
+    val animation = AnimatedImageVector.animatedVectorResource(R.drawable.open_on_phone_animation)
     ConfirmationDialog(
         onTimeout = {
             /* Do something e.g. navController.popBackStack() */
@@ -129,7 +131,7 @@
                 onDispose {}
             }
             Image(
-                painter = animation.painterFor(atEnd),
+                painter = rememberAnimatedVectorPainter(animation, atEnd),
                 contentDescription = "Open on phone",
                 modifier = Modifier.size(64.dp)
             )
diff --git a/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt
new file mode 100644
index 0000000..61b3ea8
--- /dev/null
+++ b/wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/StepperSample.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.wear.compose.material.Stepper
+import androidx.wear.compose.material.Text
+
+@Sampled
+@Composable
+fun StepperSample() {
+    var value by remember { mutableStateOf(2f) }
+    Stepper(
+        value = value,
+        onValueChange = { value = it },
+        valueRange = 1f..4f,
+        steps = 7
+    ) { Text("Value: $value") }
+}
diff --git a/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt b/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
index 73fee0d..dd701f6 100644
--- a/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
+++ b/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/PositionIndicatorTest.kt
@@ -17,15 +17,14 @@
 package androidx.wear.compose.material
 
 import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.gestures.scrollBy
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.ui.Modifier
 import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.scrollBy
 import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.requiredHeight
+import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListLayoutInfo
 import androidx.compose.foundation.lazy.LazyListState
@@ -34,6 +33,7 @@
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -41,13 +41,13 @@
 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 kotlinx.coroutines.runBlocking
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.runBlocking
-import org.junit.Ignore
 
 @MediumTest
 @RunWith(AndroidJUnit4::class)
@@ -805,7 +805,7 @@
                     .background(Color.Black),
                 verticalArrangement = Arrangement.spacedBy(itemSpacingDp),
 
-            ) {
+                ) {
                 Box(Modifier.requiredSize(itemSizeDp))
                 Box(Modifier.requiredSize(itemSizeDp))
                 Box(Modifier.requiredSize(itemSizeDp))
@@ -885,7 +885,7 @@
     @Test
     fun rsbPositionIndicatorGivesCorrectPositionAndSize() {
         val state = mutableStateOf(0f)
-        val positionIndicatorState = RsbPositionIndicatorState(state)
+        val positionIndicatorState = FractionPositionIndicatorState { state.value }
 
         rule.setContent {
             PositionIndicator(
diff --git a/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/InlineSliderScreenshotTest.kt b/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
similarity index 99%
rename from wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/InlineSliderScreenshotTest.kt
rename to wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
index 66062fe..1a05807 100644
--- a/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/InlineSliderScreenshotTest.kt
+++ b/wear/compose/compose-material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/SliderScreenshotTest.kt
@@ -39,7 +39,7 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-class InlineSliderScreenshotTest {
+class SliderScreenshotTest {
 
     @get:Rule
     val rule = createComposeRule()
diff --git a/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/Resources.android.kt b/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/Resources.android.kt
index 38b945e..992f1dd 100644
--- a/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/Resources.android.kt
+++ b/wear/compose/compose-material/src/androidMain/kotlin/androidx/wear/compose/material/Resources.android.kt
@@ -27,18 +27,15 @@
 internal actual fun isRoundDevice(): Boolean = LocalConfiguration.current.isScreenRound
 
 @Composable
-internal actual fun imageResource(res: String): Painter {
-    val id = drawableId(res)
-    return painterResource(id)
-}
-
-// TODO: improve resource loading
-private fun drawableId(res: String): Int {
-    val imageName = res.substringAfterLast("/").substringBeforeLast(".")
-    val drawableClass = R.drawable::class.java
-    val field = drawableClass.getDeclaredField(imageName)
-    return field.get(drawableClass) as Int
-}
+internal actual fun imageResource(image: ImageResources): Painter =
+    painterResource(
+        when (image) {
+            ImageResources.CircularVignetteBottom -> R.drawable.circular_vignette_bottom
+            ImageResources.CircularVignetteTop -> R.drawable.circular_vignette_top
+            ImageResources.RectangularVignetteBottom -> R.drawable.rectangular_vignette_bottom
+            ImageResources.RectangularVignetteTop -> R.drawable.rectangular_vignette_top
+        }
+    )
 
 @Composable
 internal actual fun is24HourFormat(): Boolean = DateFormat.is24HourFormat(LocalContext.current)
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Dialog.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Dialog.kt
index 2916b1d..ec24d8e 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Dialog.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Dialog.kt
@@ -196,8 +196,8 @@
  * @param scrollState The scroll state for the dialog so that the scroll position can be displayed
  * e.g. by the [PositionIndicator] passed to [Scaffold].
  * @param durationMillis The number of milliseconds for which the dialog is displayed,
- * must be positive. Expected to be [DialogDefaults.ShortDuration], [DialogDefaults.LongDuration],
- * or [DialogDefaults.IndefiniteDuration].
+ * must be positive. Suggested values are [DialogDefaults.ShortDurationMillis],
+ * [DialogDefaults.LongDurationMillis] or [DialogDefaults.IndefiniteDurationMillis].
  * @param backgroundColor [Color] representing the background color for this dialog.
  * @param contentColor [Color] representing the content color for this dialog.
  * @param iconTintColor Icon [Color] that defaults to the [contentColor],
@@ -211,7 +211,7 @@
     modifier: Modifier = Modifier,
     icon: @Composable (() -> Unit)? = null,
     scrollState: ScrollState = rememberScrollState(),
-    durationMillis: Long = DialogDefaults.ShortDuration,
+    durationMillis: Long = DialogDefaults.ShortDurationMillis,
     backgroundColor: Color = MaterialTheme.colors.background,
     contentColor: Color = contentColorFor(backgroundColor),
     iconTintColor: Color = contentColor,
@@ -286,17 +286,17 @@
     /**
      * Short duration for showing [ConfirmationDialog].
      */
-    val ShortDuration = 4000L
+    val ShortDurationMillis = 4000L
 
     /**
      * Long duration for showing [ConfirmationDialog].
      */
-    val LongDuration = 10000L
+    val LongDurationMillis = 10000L
 
     /**
      * Show [ConfirmationDialog] indefinitely (supports swipe-to-dismiss).
      */
-    val IndefiniteDuration = Long.MAX_VALUE
+    val IndefiniteDurationMillis = Long.MAX_VALUE
 
     /**
      * Spacing between [Button]s.
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PositionIndicator.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PositionIndicator.kt
index 96f1798d..1625ff2 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PositionIndicator.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/PositionIndicator.kt
@@ -16,7 +16,6 @@
 
 package androidx.wear.compose.material
 
-import androidx.compose.ui.geometry.lerp
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.fadeIn
 import androidx.compose.animation.fadeOut
@@ -28,24 +27,24 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Stable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawWithContent
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.geometry.lerp
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.StrokeCap
 import androidx.compose.ui.graphics.drawscope.ContentDrawScope
 import androidx.compose.ui.graphics.drawscope.Stroke
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import kotlin.math.asin
-import kotlin.math.max
 import kotlinx.coroutines.delay
 import kotlin.math.PI
 import kotlin.math.abs
+import kotlin.math.asin
+import kotlin.math.max
 
 /**
  * An object representing the relative position of a scrollbar or rolling side button or rotating
@@ -92,8 +91,9 @@
  * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
  * guide.
  *
- * @param scrollState the scrollState to use as the basis for the PositionIndicatorState.
+ * @param scrollState The scrollState to use as the basis for the PositionIndicatorState.
  * @param modifier The modifier to be applied to the component
+ * @param reverseDirection Reverses direction of PositionIndicator if true
  */
 @Composable
 public fun PositionIndicator(
@@ -120,6 +120,7 @@
  * @param scalingLazyListState the [ScalingLazyListState] to use as the basis for the
  * PositionIndicatorState.
  * @param modifier The modifier to be applied to the component
+ * @param reverseDirection Reverses direction of PositionIndicator if true
  */
 @Composable
 public fun PositionIndicator(
@@ -148,6 +149,7 @@
  * @param lazyListState the [LazyListState] to use as the basis for the
  * PositionIndicatorState.
  * @param modifier The modifier to be applied to the component
+ * @param reverseDirection Reverses direction of PositionIndicator if true
  */
 @Composable
 public fun PositionIndicator(
@@ -166,26 +168,31 @@
 )
 
 /**
- * Creates an [PositionIndicator] for a rotating side button or rotating bezel style indicator.
+ * Creates a [PositionIndicator] for controls like rotating side button, rotating bezel or slider.
  *
  * For more information, see the
  * [Scroll indicators](https://developer.android.com/training/wearables/components/scroll)
  * guide.
  *
- * @param rsbRatio the value of the rsb/bezel indicator in the range 0..1 where 1 represents the
- * maximum value. E.g. If displaying a volume value say from 0..11 then the rsbRatio would be
+ * @param value Value of the indicator in the [range] where 1 represents the
+ * maximum value. E.g. If displaying a volume value from 0..11 then the [value] will be
  * volume/11.
- * @param modifier The modifier to be applied to the component
- * @param color the color to draw the indicator on.
+ * @param range range of values that [value] can take
+ * @param modifier Modifier to be applied to the component
+ * @param color Color to draw the indicator on.
+ * @param reverseDirection Reverses direction of PositionIndicator if true
  */
 @Composable
 public fun PositionIndicator(
-    rsbRatio: Float,
+    value: () -> Float,
     modifier: Modifier = Modifier,
+    range: ClosedFloatingPointRange<Float> = 0f..1f,
     color: Color = MaterialTheme.colors.onBackground,
     reverseDirection: Boolean = false
 ) = PositionIndicator(
-    state = RsbPositionIndicatorState(remember { mutableStateOf(rsbRatio) }),
+    state = FractionPositionIndicatorState {
+        (value() - range.start) / (range.endInclusive - range.start)
+    },
     indicatorHeight = 76.dp,
     indicatorWidth = 6.dp,
     paddingRight = 5.dp,
@@ -223,6 +230,7 @@
  * @param color the color to draw the active part of the indicator in
  * @param background the color to draw the non-active part of the position indicator.
  * @param autoHide whether the indicator should be automatically hidden after showing the change in
+ * @param reverseDirection Reverses direction of PositionIndicator if true
  */
 @Composable
 public fun PositionIndicator(
@@ -305,27 +313,26 @@
 }
 
 /**
- * An implementation of [PositionIndicatorState] to display the a value that is being incremented or
- * decremented with a rolling side button or rotating bezel, e.g. A volume control.
+ * An implementation of [PositionIndicatorState] to display a value that is being incremented or
+ * decremented with a rolling side button, rotating bezel or a slider e.g. a volume control.
  *
- * @param rsbRatio the value of the rsb/bezel indicator in the range 0..1 where 1 represents the
- * maximum value. E.g. If displaying a volume value say from 0..11 then the rsbRatio would be
+ * @param fraction Value of the indicator in the range 0..1 where 1 represents the
+ * maximum value. E.g. If displaying a volume value from 0..11 then the [fraction] will be
  * volume/11.
  *
  * @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
  */
-internal class RsbPositionIndicatorState(
-    private val rsbRatio: State<Float>
+internal class FractionPositionIndicatorState(
+    private val fraction: () -> Float
 ) : PositionIndicatorState {
-    override val positionFraction = 1f
+    override val positionFraction = 1f // Position indicator always starts at the bottom|end
 
-    override fun sizeFraction(scrollableContainerSizePx: Float) = rsbRatio.value
+    override fun sizeFraction(scrollableContainerSizePx: Float) = fraction()
 
-    override fun equals(other: Any?) = (other as? RsbPositionIndicatorState)?.rsbRatio == rsbRatio
+    override fun equals(other: Any?) =
+        (other as? FractionPositionIndicatorState)?.fraction?.invoke() == fraction()
 
-    override fun hashCode(): Int {
-        return rsbRatio.hashCode()
-    }
+    override fun hashCode(): Int = fraction().hashCode()
 }
 
 /**
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/RangeDefaults.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/RangeDefaults.kt
new file mode 100644
index 0000000..706cc65
--- /dev/null
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/RangeDefaults.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material
+
+import androidx.compose.foundation.progressSemantics
+import androidx.compose.material.icons.materialIcon
+import androidx.compose.material.icons.materialPath
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.semantics.disabled
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.setProgress
+import androidx.compose.ui.util.lerp
+import kotlin.math.roundToInt
+
+/**
+ * Icons which are used by Range controls like slider and stepper
+ */
+internal object RangeIcons {
+
+    /**
+     * An [Icon] with a minus sign.
+     */
+    val MinusIcon: ImageVector
+        get() = if (_minusIcon != null) _minusIcon!!
+        else {
+            _minusIcon = materialIcon(name = "MinusIcon") {
+                materialPath {
+                    moveTo(19.0f, 13.0f)
+                    horizontalLineTo(5.0f)
+                    verticalLineToRelative(-2.0f)
+                    horizontalLineToRelative(14.0f)
+                    verticalLineToRelative(2.0f)
+                    close()
+                }
+            }
+            _minusIcon!!
+        }
+
+    private var _minusIcon: ImageVector? = null
+}
+
+/**
+ * Defaults used by range controls like slider and stepper
+ */
+internal object RangeDefaults {
+    /**
+     * Calculates value of [currentStep] in [valueRange] depending on number of [steps]
+     */
+    fun calculateCurrentStepValue(
+        currentStep: Int,
+        steps: Int,
+        valueRange: ClosedFloatingPointRange<Float>
+    ): Float = lerp(
+        valueRange.start, valueRange.endInclusive,
+        currentStep.toFloat() / (steps + 1).toFloat()
+    ).coerceIn(valueRange)
+
+    /**
+     * Snaps [value] to the closest [step] in the [valueRange]
+     */
+    fun snapValueToStep(
+        value: Float,
+        valueRange: ClosedFloatingPointRange<Float>,
+        steps: Int
+    ): Int = ((value - valueRange.start) /
+        (valueRange.endInclusive - valueRange.start) * (steps + 1))
+        .roundToInt().coerceIn(0, steps + 1)
+}
+
+internal fun Modifier.rangeSemantics(
+    step: Int,
+    enabled: Boolean,
+    onValueChange: (Float) -> Unit,
+    valueRange: ClosedFloatingPointRange<Float>,
+    steps: Int
+): Modifier = semantics(mergeDescendants = true) {
+    if (!enabled) disabled()
+    setProgress(
+        action = { targetValue ->
+            val newStepIndex = RangeDefaults.snapValueToStep(targetValue, valueRange, steps)
+            if (step == newStepIndex) {
+                false
+            } else {
+                onValueChange(targetValue)
+                true
+            }
+        }
+    )
+}.progressSemantics(
+    RangeDefaults.calculateCurrentStepValue(step, steps, valueRange),
+    valueRange, steps
+)
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Resources.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Resources.kt
index e5a01e9..8891cd3 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Resources.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Resources.kt
@@ -19,8 +19,15 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.painter.Painter
 
+internal enum class ImageResources {
+    CircularVignetteBottom,
+    CircularVignetteTop,
+    RectangularVignetteBottom,
+    RectangularVignetteTop,
+}
+
 @Composable
-internal expect fun imageResource(res: String): Painter
+internal expect fun imageResource(image: ImageResources): Painter
 
 @Composable
 internal expect fun isRoundDevice(): Boolean
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Slider.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Slider.kt
index 3877a46..b8a52fc 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Slider.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Slider.kt
@@ -28,11 +28,8 @@
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.progressSemantics
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
-import androidx.compose.material.icons.materialIcon
-import androidx.compose.material.icons.materialPath
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Immutable
@@ -48,13 +45,10 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.semantics.disabled
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.semantics.setProgress
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.lerp
-import kotlin.math.roundToInt
+import androidx.wear.compose.material.RangeDefaults.calculateCurrentStepValue
+import androidx.wear.compose.material.RangeDefaults.snapValueToStep
 
 /**
  * [InlineSlider] allows users to make a selection from a range of values. The range of selections
@@ -66,9 +60,9 @@
  * accordingly to the start and end of the control. Buttons can have custom icons -
  * [decreaseIcon] and [increaseIcon].
  *
- * The selection bar in the middle of control can have separators if [segmented] flag is set to true.
+ * The bar in the middle of control can have separators if [segmented] flag is set to true.
  * A single step value is calculated as the difference between min and max values of [valueRange]
- * divided by [steps] value.
+ * divided by [steps] + 1 value.
  *
  * A continuous non-segmented slider sample:
  * @sample androidx.wear.compose.material.samples.InlineSliderSample
@@ -112,7 +106,7 @@
     },
     increaseIcon: @Composable () -> Unit = {
         Icon(
-            imageVector = Icons.Filled.Add,
+            imageVector = InlineSliderDefaults.IncreaseIcon,
             contentDescription = "Increase" // TODO(b/204187777) i18n
         )
     },
@@ -124,7 +118,7 @@
     Box(
         modifier = modifier
             .fillMaxWidth()
-            .inlineSliderSemantics(
+            .rangeSemantics(
                 currentStep,
                 enabled,
                 onValueChange,
@@ -150,7 +144,7 @@
             horizontalArrangement = Arrangement.Start,
             modifier = Modifier.fillMaxWidth().background(backgroundColor.value)
         ) {
-            ActionButton(
+            InlineSliderButton(
                 enabled = enabled,
                 onClick = { updateValue(-1) },
                 contentAlignment = Alignment.CenterStart,
@@ -189,7 +183,7 @@
                     .background(colors.spacerColor(enabled).value)
             )
 
-            ActionButton(
+            InlineSliderButton(
                 enabled = enabled,
                 onClick = { updateValue(1) },
                 contentAlignment = Alignment.CenterEnd,
@@ -233,7 +227,7 @@
 }
 
 /**
- * Defaults used by [InlineSlider]
+ * Defaults used by slider
  */
 object InlineSliderDefaults {
 
@@ -291,25 +285,16 @@
     )
 
     /**
-     * An [Icon] with a minus sign.
+     * A decrease [Icon].
      */
     val DecreaseIcon: ImageVector
-        get() = if (_decreaseIcon != null) _decreaseIcon!!
-        else {
-            _decreaseIcon = materialIcon(name = "DecreaseIcon") {
-                materialPath {
-                    moveTo(19.0f, 13.0f)
-                    horizontalLineTo(5.0f)
-                    verticalLineToRelative(-2.0f)
-                    horizontalLineToRelative(14.0f)
-                    verticalLineToRelative(2.0f)
-                    close()
-                }
-            }
-            _decreaseIcon!!
-        }
+        get() = RangeIcons.MinusIcon
 
-    private var _decreaseIcon: ImageVector? = null
+    /**
+     * An increase [Icon].
+     */
+    val IncreaseIcon: ImageVector
+        get() = Icons.Filled.Add
 }
 
 @Immutable
@@ -375,7 +360,7 @@
 }
 
 @Composable
-private fun ActionButton(
+private fun InlineSliderButton(
     enabled: Boolean,
     onClick: () -> Unit,
     contentAlignment: Alignment,
@@ -397,43 +382,6 @@
     }
 }
 
-private fun calculateCurrentStepValue(
-    currentStep: Int,
-    steps: Int,
-    valueRange: ClosedFloatingPointRange<Float>
-): Float = lerp(
-    valueRange.start, valueRange.endInclusive,
-    currentStep.toFloat() / (steps + 1).toFloat()
-).coerceIn(valueRange)
-
-private fun snapValueToStep(
-    value: Float,
-    valueRange: ClosedFloatingPointRange<Float>,
-    steps: Int
-): Int = ((value - valueRange.start) / (valueRange.endInclusive - valueRange.start) * (steps + 1))
-    .roundToInt().coerceIn(0, steps + 1)
-
-private fun Modifier.inlineSliderSemantics(
-    step: Int,
-    enabled: Boolean,
-    onValueChange: (Float) -> Unit,
-    valueRange: ClosedFloatingPointRange<Float>,
-    steps: Int
-): Modifier = semantics(mergeDescendants = true) {
-    if (!enabled) disabled()
-    setProgress(
-        action = { targetValue ->
-            val newStepIndex = snapValueToStep(targetValue, valueRange, steps)
-            if (step == newStepIndex) {
-                false
-            } else {
-                onValueChange(targetValue)
-                true
-            }
-        }
-    )
-}.progressSemantics(calculateCurrentStepValue(step, steps, valueRange), valueRange, steps)
-
 private fun Modifier.drawProgressBar(
     selectedBarColor: State<Color>,
     unselectedBarColor: State<Color>,
@@ -474,4 +422,4 @@
 }
 
 private fun <T> directedValue(layoutDirection: LayoutDirection, ltrValue: T, rtlValue: T): T =
-    if (layoutDirection == LayoutDirection.Ltr) ltrValue else rtlValue
\ No newline at end of file
+    if (layoutDirection == LayoutDirection.Ltr) ltrValue else rtlValue
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Stepper.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Stepper.kt
new file mode 100644
index 0000000..fa71cb1
--- /dev/null
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Stepper.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.material
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.indication
+import androidx.compose.foundation.interaction.MutableInteractionSource
+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.ColumnScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.RangeDefaults.calculateCurrentStepValue
+import androidx.wear.compose.material.RangeDefaults.snapValueToStep
+
+/**
+ * [Stepper] allows users to make a selection from a range of values.
+ * It's a full-screen control with increase button on the top, decrease button on the bottom and
+ * a slot (expected to have either [Text] or [Chip]) in the middle.
+ * Value can be increased and decreased by clicking on the increase and decrease buttons.
+ * Buttons can have custom icons - [decreaseIcon] and [increaseIcon].
+ * Step value is calculated as the difference between min and max values divided by [steps]+1.
+ * Stepper itself doesn't show the current value but can be displayed via the content slot or
+ * [PositionIndicator] if required.
+ *
+ * @sample androidx.wear.compose.material.samples.StepperSample
+ *
+ * @param value Current value of the Stepper. If outside of [valueRange] provided, value will be
+ * coerced to this range.
+ * @param onValueChange Lambda in which value should be updated
+ * @param steps Specifies the number of discrete values, evenly distributed
+ * between across the whole value range. Must not be negative. If 0, stepper will have only
+ * min and max values and no steps in between
+ * @param modifier Modifiers for the Stepper layout
+ * @param valueRange Range of values that Stepper value can take. Passed [value] will be coerced to
+ * this range
+ * @param decreaseIcon A slot for an icon which is placed on the decrease (bottom) button
+ * @param increaseIcon A slot for an icon which is placed on the increase (top) button
+ * @param backgroundColor [Color] representing the background color for the stepper.
+ * @param contentColor [Color] representing the color for [content] in the middle.
+ * @param iconTintColor Icon tint [Color] which used by [increaseIcon] and [decreaseIcon]
+ * that defaults to [contentColor], unless specifically overridden.
+ */
+@Composable
+fun Stepper(
+    value: Float,
+    onValueChange: (Float) -> Unit,
+    steps: Int,
+    modifier: Modifier = Modifier,
+    valueRange: ClosedFloatingPointRange<Float> = 0f..(steps + 1).toFloat(),
+    decreaseIcon: @Composable () -> Unit = {
+        Icon(
+            imageVector = StepperDefaults.DecreaseIcon,
+            contentDescription = "Decrease", // TODO(b/204187777) i18n
+            modifier = Modifier.padding(14.dp)
+        )
+    },
+    increaseIcon: @Composable () -> Unit = {
+        Icon(
+            imageVector = StepperDefaults.IncreaseIcon,
+            contentDescription = "Increase", // TODO(b/204187777) i18n
+            modifier = Modifier.padding(14.dp)
+        )
+    },
+    backgroundColor: Color = MaterialTheme.colors.background,
+    contentColor: Color = contentColorFor(backgroundColor),
+    iconTintColor: Color = contentColor,
+    content: @Composable BoxScope.() -> Unit
+) {
+    require(steps >= 0) { "steps should be >= 0" }
+    val currentStep =
+        remember(value, valueRange, steps) { snapValueToStep(value, valueRange, steps) }
+
+    val updateValue: (Int) -> Unit = { stepDiff ->
+        val newValue = calculateCurrentStepValue(currentStep + stepDiff, steps, valueRange)
+        if (newValue != value) onValueChange(newValue)
+    }
+
+    Column(
+        modifier = modifier
+            .fillMaxSize()
+            .background(backgroundColor)
+            .rangeSemantics(
+                currentStep,
+                true,
+                onValueChange,
+                valueRange,
+                steps
+            ),
+        verticalArrangement = Arrangement.spacedBy(8.dp)
+    ) {
+        FullScreenButton(
+            onClick = { updateValue(1) },
+            contentAlignment = Alignment.TopCenter,
+            paddingValues = PaddingValues(top = StepperDefaults.BorderPadding),
+            iconTintColor = iconTintColor,
+            content = increaseIcon
+        )
+        Box(
+            modifier = Modifier
+                .fillMaxWidth()
+                .weight(StepperDefaults.ContentWeight),
+            contentAlignment = Alignment.Center,
+        ) {
+            CompositionLocalProvider(LocalContentColor provides contentColor) {
+                content()
+            }
+        }
+        FullScreenButton(
+            onClick = { updateValue(-1) },
+            contentAlignment = Alignment.BottomCenter,
+            paddingValues = PaddingValues(bottom = StepperDefaults.BorderPadding),
+            content = decreaseIcon,
+            iconTintColor = iconTintColor
+        )
+    }
+}
+
+@Composable
+private fun ColumnScope.FullScreenButton(
+    onClick: () -> Unit,
+    contentAlignment: Alignment,
+    paddingValues: PaddingValues,
+    iconTintColor: Color,
+    content: @Composable () -> Unit
+) {
+    val interactionSource = remember { MutableInteractionSource() }
+    Box(
+        modifier = Modifier
+            .fillMaxWidth()
+            .weight(StepperDefaults.ButtonWeight)
+            .clickable(interactionSource, null, onClick = onClick)
+            .wrapContentWidth()
+            .indication(interactionSource, rememberRipple(bounded = false))
+            .padding(paddingValues),
+        contentAlignment = contentAlignment,
+    ) {
+        CompositionLocalProvider(LocalContentColor provides iconTintColor, content = content)
+    }
+}
+
+/**
+ * Defaults used by stepper
+ */
+object StepperDefaults {
+    internal const val ButtonWeight = 0.35f
+    internal const val ContentWeight = 0.3f
+    internal val BorderPadding = 8.dp
+
+    /**
+     * A decrease [Icon].
+     */
+    val DecreaseIcon: ImageVector
+        get() = RangeIcons.MinusIcon
+
+    /**
+     * An increase [Icon].
+     */
+    val IncreaseIcon: ImageVector
+        get() = Icons.Filled.Add
+}
diff --git a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Vignette.kt b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Vignette.kt
index 2f19da1..568f715 100644
--- a/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Vignette.kt
+++ b/wear/compose/compose-material/src/commonMain/kotlin/androidx/wear/compose/material/Vignette.kt
@@ -98,8 +98,8 @@
         if (vignettePosition.drawTop()) {
             Image(
                 painter = imageResource(
-                    if (isRoundDevice()) "circular_vignette_top"
-                    else "rectangular_vignette_top"
+                    if (isRoundDevice()) ImageResources.CircularVignetteTop
+                    else ImageResources.RectangularVignetteTop
                 ),
                 contentScale = ContentScale.FillWidth,
                 contentDescription = null,
@@ -109,8 +109,8 @@
         if (vignettePosition.drawBottom()) {
             Image(
                 painter = imageResource(
-                    if (isRoundDevice()) "circular_vignette_bottom"
-                    else "rectangular_vignette_bottom"
+                    if (isRoundDevice()) ImageResources.CircularVignetteBottom
+                    else ImageResources.RectangularVignetteBottom
                 ),
                 contentScale = ContentScale.FillWidth,
                 contentDescription = null,
diff --git a/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/Resources.desktop.kt b/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/Resources.desktop.kt
index 003eca7..8b15984 100644
--- a/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/Resources.desktop.kt
+++ b/wear/compose/compose-material/src/desktopMain/kotlin/androidx/wear/compose/material/Resources.desktop.kt
@@ -26,8 +26,15 @@
 }
 
 @Composable
-internal actual fun imageResource(res: String): Painter =
-    painterResource(res)
+internal actual fun imageResource(image: ImageResources): Painter =
+    painterResource(
+        when (image) {
+            ImageResources.CircularVignetteBottom -> "circular_vignette_bottom"
+            ImageResources.CircularVignetteTop -> "circular_vignette_top"
+            ImageResources.RectangularVignetteBottom -> "rectangular_vignette_bottom"
+            ImageResources.RectangularVignetteTop -> "rectangular_vignette_top"
+        }
+    )
 
 @Composable
 internal actual fun is24HourFormat(): Boolean {
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 4d38b8f..2049ef7 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
@@ -40,6 +40,7 @@
 import androidx.wear.compose.material.samples.SimpleSwipeToDismissBox
 import androidx.wear.compose.material.samples.SplitToggleChipWithCheckbox
 import androidx.wear.compose.material.samples.StatefulSwipeToDismissBox
+import androidx.wear.compose.material.samples.StepperSample
 import androidx.wear.compose.material.samples.TimeTextWithCustomSeparator
 import androidx.wear.compose.material.samples.TimeTextWithFullDateAndTimeFormat
 import androidx.wear.compose.material.samples.TitleCardStandard
@@ -105,6 +106,31 @@
             )
         ),
         DemoCategory(
+            "Stepper",
+            listOf(
+                DemoCategory(
+                    "Samples",
+                    listOf(
+                        ComposableDemo("Stepper") {
+                            Centralize({ StepperSample() })
+                        },
+                    )
+                ),
+                DemoCategory(
+                    "Demos",
+                    listOf(
+                        ComposableDemo("Simple stepper") { StepperDemo() },
+                        ComposableDemo("With scrollbar") {
+                            StepperWithScrollBarDemo()
+                        },
+                        ComposableDemo("With custom colors") {
+                            StepperWithCustomColors()
+                        },
+                    )
+                )
+            )
+        ),
+        DemoCategory(
             "TimeText",
             listOf(
                 DemoCategory(
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
index 768565c..1118ea7 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/SliderDemo.kt
@@ -122,4 +122,4 @@
             steps = numberOfSegments.toInt()
         )
     }
-}
\ No newline at end of file
+}
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt
new file mode 100644
index 0000000..cbde90a
--- /dev/null
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/StepperDemo.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.integration.demos
+
+import androidx.compose.foundation.layout.width
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.Chip
+import androidx.wear.compose.material.ChipDefaults
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.PositionIndicator
+import androidx.wear.compose.material.Stepper
+import androidx.wear.compose.material.Text
+
+@Composable
+fun StepperDemo() {
+    var value by remember { mutableStateOf(2f) }
+    Stepper(
+        value = value,
+        onValueChange = { value = it },
+        valueRange = 1f..4f,
+        steps = 2
+    ) { Text("Value: $value") }
+}
+
+@Composable
+fun StepperWithScrollBarDemo() {
+    val valueState = remember { mutableStateOf(4f) }
+    val range = 0f..10f
+
+    Stepper(
+        value = valueState.value,
+        onValueChange = {
+            valueState.value = it
+        },
+        valueRange = range,
+        steps = 9
+    ) {
+        Chip(
+            onClick = { valueState.value = if (valueState.value == 0f) 4f else 0f },
+            modifier = Modifier.width(146.dp),
+            colors = ChipDefaults.secondaryChipColors(),
+            label = { Text("Volume : ${valueState.value}") },
+            icon = {
+                Icon(
+                    painter = painterResource(
+                        id = if (valueState.value > 0)
+                            R.drawable.ic_volume_up_24px
+                        else R.drawable.ic_volume_off_24px
+                    ),
+                    contentDescription = null,
+                )
+            }
+        )
+    }
+
+    PositionIndicator(
+        value = { valueState.value },
+        range = range
+    )
+}
+
+@Composable
+fun StepperWithCustomColors() {
+    val valueState = remember { mutableStateOf(4f) }
+    val range = 0f..10f
+
+    Stepper(
+        value = valueState.value,
+        onValueChange = {
+            valueState.value = it
+        },
+        valueRange = range,
+        steps = 9,
+        backgroundColor = Color.Blue,
+        contentColor = Color.Red,
+        iconTintColor = Color.Green
+    ) {
+        Text("Volume : ${valueState.value}")
+    }
+
+    PositionIndicator(
+        value = { valueState.value },
+        range = range
+    )
+}
diff --git a/wear/watchface/watchface-client-guava/api/current.txt b/wear/watchface/watchface-client-guava/api/current.txt
index 5115180..d17f246 100644
--- a/wear/watchface/watchface-client-guava/api/current.txt
+++ b/wear/watchface/watchface-client-guava/api/current.txt
@@ -18,5 +18,14 @@
     method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.ListenableWatchFaceControlClient> createWatchFaceControlClient(android.content.Context context, String watchFacePackageName);
   }
 
+  public final class ListenableWatchFaceMetadataClient {
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
+    field public static final androidx.wear.watchface.client.ListenableWatchFaceMetadataClient.Companion Companion;
+  }
+
+  public static final class ListenableWatchFaceMetadataClient.Companion {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
+  }
+
 }
 
diff --git a/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt b/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
index 030cf28..d17f246 100644
--- a/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-client-guava/api/public_plus_experimental_current.txt
@@ -18,14 +18,13 @@
     method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.ListenableWatchFaceControlClient> createWatchFaceControlClient(android.content.Context context, String watchFacePackageName);
   }
 
-  @androidx.wear.watchface.client.WatchFaceClientExperimental public final class ListenableWatchFaceMetadataClient {
-    ctor public ListenableWatchFaceMetadataClient();
-    method public static com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> createListenableWatchFaceMetadataClient(android.content.Context context, android.content.ComponentName watchFaceName);
+  public final class ListenableWatchFaceMetadataClient {
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
     field public static final androidx.wear.watchface.client.ListenableWatchFaceMetadataClient.Companion Companion;
   }
 
   public static final class ListenableWatchFaceMetadataClient.Companion {
-    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> createListenableWatchFaceMetadataClient(android.content.Context context, android.content.ComponentName watchFaceName);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
   }
 
 }
diff --git a/wear/watchface/watchface-client-guava/api/restricted_current.txt b/wear/watchface/watchface-client-guava/api/restricted_current.txt
index 5115180..d17f246 100644
--- a/wear/watchface/watchface-client-guava/api/restricted_current.txt
+++ b/wear/watchface/watchface-client-guava/api/restricted_current.txt
@@ -18,5 +18,14 @@
     method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.ListenableWatchFaceControlClient> createWatchFaceControlClient(android.content.Context context, String watchFacePackageName);
   }
 
+  public final class ListenableWatchFaceMetadataClient {
+    method public static com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
+    field public static final androidx.wear.watchface.client.ListenableWatchFaceMetadataClient.Companion Companion;
+  }
+
+  public static final class ListenableWatchFaceMetadataClient.Companion {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.watchface.client.WatchFaceMetadataClient> create(android.content.Context context, android.content.ComponentName watchFaceName);
+  }
+
 }
 
diff --git a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
index aac5ad0..9dca287 100644
--- a/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
+++ b/wear/watchface/watchface-client-guava/src/androidTest/java/androidx/wear/watchface/client/guava/ListenableWatchFaceMetadataClientTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.wear.watchface.client.ListenableWatchFaceMetadataClient
-import androidx.wear.watchface.client.WatchFaceClientExperimental
 import androidx.wear.watchface.client.WatchFaceMetadataClient
 import androidx.wear.watchface.control.IWatchFaceInstanceServiceStub
 import androidx.wear.watchface.control.WatchFaceControlService
@@ -61,7 +60,6 @@
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
-@OptIn(WatchFaceClientExperimental::class)
 public class ListenableWatchFaceMetadataClientTest {
     private val exampleWatchFaceComponentName = ComponentName(
         "androidx.wear.watchface.samples.test",
@@ -73,7 +71,7 @@
     @Test
     public fun getSchema() {
         val listenableFuture =
-            ListenableWatchFaceMetadataClient.createListenableWatchFaceMetadataClientImpl(
+            ListenableWatchFaceMetadataClient.createImpl(
                 context,
                 Intent(context, WatchFaceControlTestService::class.java).apply {
                     action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
diff --git a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
index d1f4dbb..5799282 100644
--- a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
@@ -182,6 +182,7 @@
     override fun getEditorServiceClient(): EditorServiceClient =
         watchFaceControlClient.getEditorServiceClient()
 
+    @Suppress("DEPRECATION")
     override fun getDefaultComplicationDataSourcePoliciesAndType(
         watchFaceName: ComponentName
     ): Map<Int, DefaultComplicationDataSourcePolicyAndType> =
diff --git a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
index 66c2ee8..6a1d13b 100644
--- a/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
+++ b/wear/watchface/watchface-client-guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceMetadataClient.kt
@@ -25,11 +25,9 @@
 import com.google.common.util.concurrent.ListenableFuture
 
 /**
- * [ListenableFuture]-based compatibility wrapper around
- * [WatchFaceMetadataClient.createWatchFaceMetadataClient].
+ * [ListenableFuture]-based compatibility wrapper around [WatchFaceMetadataClient.create].
  */
-@WatchFaceClientExperimental
-public class ListenableWatchFaceMetadataClient {
+public class ListenableWatchFaceMetadataClient private constructor() {
     public companion object {
         /**
          * Constructs a [WatchFaceMetadataClient] for fetching metadata for the specified watch
@@ -44,20 +42,19 @@
          */
         @Suppress("AsyncSuffixFuture")
         @JvmStatic
-        public fun createListenableWatchFaceMetadataClient(
+        public fun create(
             context: Context,
             watchFaceName: ComponentName
-        ): ListenableFuture<WatchFaceMetadataClient> =
-            createListenableWatchFaceMetadataClientImpl(
-                context,
-                Intent(WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE).apply {
-                    setPackage(watchFaceName.packageName)
-                },
-                watchFaceName,
-                WatchFaceMetadataClient.Companion.ParserProvider()
-            )
+        ): ListenableFuture<WatchFaceMetadataClient> = createImpl(
+            context,
+            Intent(WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE).apply {
+                setPackage(watchFaceName.packageName)
+            },
+            watchFaceName,
+            WatchFaceMetadataClient.Companion.ParserProvider()
+        )
 
-        internal fun createListenableWatchFaceMetadataClientImpl(
+        internal fun createImpl(
             context: Context,
             intent: Intent,
             watchFaceName: ComponentName,
@@ -65,7 +62,7 @@
         ) = ListenableWatchFaceControlClient.launchFutureCoroutine(
             "ListenableWatchFaceMetadataClient.listenableCreateWatchFaceMetadataClient"
         ) {
-            WatchFaceMetadataClient.createWatchFaceMetadataClientImpl(
+            WatchFaceMetadataClient.createImpl(
                 context,
                 intent,
                 watchFaceName,
diff --git a/wear/watchface/watchface-client/api/current.txt b/wear/watchface/watchface-client/api/current.txt
index ae220e2..421504b 100644
--- a/wear/watchface/watchface-client/api/current.txt
+++ b/wear/watchface/watchface-client/api/current.txt
@@ -1,14 +1,33 @@
 // Signature format: 4.0
 package androidx.wear.watchface.client {
 
+  public final class ComplicationSlotMetadata {
+    ctor public ComplicationSlotMetadata(androidx.wear.watchface.complications.ComplicationSlotBounds? bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isInitiallyEnabled, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    method public androidx.wear.watchface.complications.ComplicationSlotBounds? getBounds();
+    method public int getBoundsType();
+    method public android.os.Bundle getComplicationConfigExtras();
+    method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
+    method public boolean getFixedComplicationDataSource();
+    method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
+    method public boolean isInitiallyEnabled();
+    property public final androidx.wear.watchface.complications.ComplicationSlotBounds? bounds;
+    property public final int boundsType;
+    property public final android.os.Bundle complicationConfigExtras;
+    property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
+    property public final boolean fixedComplicationDataSource;
+    property public final boolean isInitiallyEnabled;
+    property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
+  }
+
   public final class ComplicationSlotState {
-    ctor public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor @Deprecated public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
     method public android.graphics.Rect getBounds();
     method public int getBoundsType();
     method public android.os.Bundle getComplicationConfigExtras();
     method public androidx.wear.watchface.complications.data.ComplicationType getCurrentType();
     method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
     method public boolean isEnabled();
@@ -18,17 +37,17 @@
     property public final android.os.Bundle complicationConfigExtras;
     property public final androidx.wear.watchface.complications.data.ComplicationType currentType;
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property public final boolean fixedComplicationDataSource;
     property public final boolean isEnabled;
     property public final boolean isInitiallyEnabled;
     property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
   }
 
-  public final class DefaultComplicationDataSourcePolicyAndType {
-    ctor public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
-    method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getType();
+  @Deprecated public final class DefaultComplicationDataSourcePolicyAndType {
+    ctor @Deprecated public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
+    method @Deprecated public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getType();
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy;
     property public final androidx.wear.watchface.complications.data.ComplicationType type;
   }
@@ -147,7 +166,7 @@
   public interface WatchFaceControlClient extends java.lang.AutoCloseable {
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.HeadlessWatchFaceClient? createHeadlessWatchFaceClient(android.content.ComponentName watchFaceName, androidx.wear.watchface.client.DeviceConfig deviceConfig, @Px int surfaceWidth, @Px int surfaceHeight) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class}) public default static suspend Object? createWatchFaceControlClient(android.content.Context context, String watchFacePackageName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceControlClient> p) throws androidx.wear.watchface.client.WatchFaceControlClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceControlClient.ServiceStartFailureException;
-    method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
+    method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient> p) throws android.os.RemoteException;
@@ -172,6 +191,24 @@
     property public final String id;
   }
 
+  public interface WatchFaceMetadataClient extends java.lang.AutoCloseable {
+    method public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.ComplicationSlotMetadata> getComplicationSlotMetadataMap();
+    method public androidx.wear.watchface.style.UserStyleSchema getUserStyleSchema();
+    field public static final androidx.wear.watchface.client.WatchFaceMetadataClient.Companion Companion;
+  }
+
+  public static final class WatchFaceMetadataClient.Companion {
+    method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class, PackageManager.NameNotFoundException::class}) public suspend Object? create(android.content.Context context, android.content.ComponentName watchFaceName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceMetadataClient> p) throws android.content.pm.PackageManager.NameNotFoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceStartFailureException;
+  }
+
+  public static final class WatchFaceMetadataClient.ServiceNotBoundException extends java.lang.Exception {
+    ctor public WatchFaceMetadataClient.ServiceNotBoundException();
+  }
+
+  public static final class WatchFaceMetadataClient.ServiceStartFailureException extends java.lang.Exception {
+    ctor public WatchFaceMetadataClient.ServiceStartFailureException(optional String message);
+  }
+
   public final class WatchUiState {
     ctor public WatchUiState(boolean inAmbientMode, int interruptionFilter);
     method public boolean getInAmbientMode();
diff --git a/wear/watchface/watchface-client/api/public_plus_experimental_current.txt b/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
index 95b4f76..15c1cc1 100644
--- a/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-client/api/public_plus_experimental_current.txt
@@ -1,13 +1,12 @@
 // Signature format: 4.0
 package androidx.wear.watchface.client {
 
-  @androidx.wear.watchface.client.WatchFaceClientExperimental public final class ComplicationSlotMetadata {
-    ctor public ComplicationSlotMetadata(androidx.wear.watchface.complications.ComplicationSlotBounds? bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isInitiallyEnabled, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+  public final class ComplicationSlotMetadata {
+    ctor public ComplicationSlotMetadata(androidx.wear.watchface.complications.ComplicationSlotBounds? bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isInitiallyEnabled, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
     method public androidx.wear.watchface.complications.ComplicationSlotBounds? getBounds();
     method public int getBoundsType();
     method public android.os.Bundle getComplicationConfigExtras();
     method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
     method public boolean isInitiallyEnabled();
@@ -15,20 +14,20 @@
     property public final int boundsType;
     property public final android.os.Bundle complicationConfigExtras;
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property public final boolean fixedComplicationDataSource;
     property public final boolean isInitiallyEnabled;
     property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
   }
 
   public final class ComplicationSlotState {
-    ctor public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor @Deprecated public ComplicationSlotState(android.graphics.Rect bounds, int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
     method public android.graphics.Rect getBounds();
     method public int getBoundsType();
     method public android.os.Bundle getComplicationConfigExtras();
     method public androidx.wear.watchface.complications.data.ComplicationType getCurrentType();
     method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
     method public boolean isEnabled();
@@ -38,17 +37,17 @@
     property public final android.os.Bundle complicationConfigExtras;
     property public final androidx.wear.watchface.complications.data.ComplicationType currentType;
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property public final boolean fixedComplicationDataSource;
     property public final boolean isEnabled;
     property public final boolean isInitiallyEnabled;
     property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
   }
 
-  public final class DefaultComplicationDataSourcePolicyAndType {
-    ctor public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
-    method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getType();
+  @Deprecated public final class DefaultComplicationDataSourcePolicyAndType {
+    ctor @Deprecated public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
+    method @Deprecated public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getType();
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy;
     property public final androidx.wear.watchface.complications.data.ComplicationType type;
   }
@@ -170,7 +169,7 @@
   public interface WatchFaceControlClient extends java.lang.AutoCloseable {
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.HeadlessWatchFaceClient? createHeadlessWatchFaceClient(android.content.ComponentName watchFaceName, androidx.wear.watchface.client.DeviceConfig deviceConfig, @Px int surfaceWidth, @Px int surfaceHeight) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class}) public default static suspend Object? createWatchFaceControlClient(android.content.Context context, String watchFacePackageName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceControlClient> p) throws androidx.wear.watchface.client.WatchFaceControlClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceControlClient.ServiceStartFailureException;
-    method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
+    method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient> p) throws android.os.RemoteException;
@@ -195,15 +194,14 @@
     property public final String id;
   }
 
-  @androidx.wear.watchface.client.WatchFaceClientExperimental public interface WatchFaceMetadataClient extends java.lang.AutoCloseable {
-    method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class, PackageManager.NameNotFoundException::class}) public default static suspend Object? createWatchFaceMetadataClient(android.content.Context context, android.content.ComponentName watchFaceName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceMetadataClient> p) throws android.content.pm.PackageManager.NameNotFoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceStartFailureException;
-    method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.ComplicationSlotMetadata> getComplicationSlotMetadataMap() throws android.os.RemoteException;
-    method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.style.UserStyleSchema getUserStyleSchema() throws android.os.RemoteException;
+  public interface WatchFaceMetadataClient extends java.lang.AutoCloseable {
+    method public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.ComplicationSlotMetadata> getComplicationSlotMetadataMap();
+    method public androidx.wear.watchface.style.UserStyleSchema getUserStyleSchema();
     field public static final androidx.wear.watchface.client.WatchFaceMetadataClient.Companion Companion;
   }
 
   public static final class WatchFaceMetadataClient.Companion {
-    method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class, PackageManager.NameNotFoundException::class}) public suspend Object? createWatchFaceMetadataClient(android.content.Context context, android.content.ComponentName watchFaceName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceMetadataClient> p) throws android.content.pm.PackageManager.NameNotFoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceStartFailureException;
+    method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class, PackageManager.NameNotFoundException::class}) public suspend Object? create(android.content.Context context, android.content.ComponentName watchFaceName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceMetadataClient> p) throws android.content.pm.PackageManager.NameNotFoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceStartFailureException;
   }
 
   public static final class WatchFaceMetadataClient.ServiceNotBoundException extends java.lang.Exception {
diff --git a/wear/watchface/watchface-client/api/restricted_current.txt b/wear/watchface/watchface-client/api/restricted_current.txt
index 19c1c16..750f771 100644
--- a/wear/watchface/watchface-client/api/restricted_current.txt
+++ b/wear/watchface/watchface-client/api/restricted_current.txt
@@ -1,14 +1,33 @@
 // Signature format: 4.0
 package androidx.wear.watchface.client {
 
+  public final class ComplicationSlotMetadata {
+    ctor public ComplicationSlotMetadata(androidx.wear.watchface.complications.ComplicationSlotBounds? bounds, @androidx.wear.watchface.ComplicationSlotBoundsType int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isInitiallyEnabled, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    method public androidx.wear.watchface.complications.ComplicationSlotBounds? getBounds();
+    method public int getBoundsType();
+    method public android.os.Bundle getComplicationConfigExtras();
+    method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
+    method public boolean getFixedComplicationDataSource();
+    method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
+    method public boolean isInitiallyEnabled();
+    property public final androidx.wear.watchface.complications.ComplicationSlotBounds? bounds;
+    property public final int boundsType;
+    property public final android.os.Bundle complicationConfigExtras;
+    property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
+    property public final boolean fixedComplicationDataSource;
+    property public final boolean isInitiallyEnabled;
+    property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
+  }
+
   public final class ComplicationSlotState {
-    ctor public ComplicationSlotState(android.graphics.Rect bounds, @androidx.wear.watchface.ComplicationSlotBoundsType int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor public ComplicationSlotState(android.graphics.Rect bounds, @androidx.wear.watchface.ComplicationSlotBoundsType int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
+    ctor @Deprecated public ComplicationSlotState(android.graphics.Rect bounds, @androidx.wear.watchface.ComplicationSlotBoundsType int boundsType, java.util.List<? extends androidx.wear.watchface.complications.data.ComplicationType> supportedTypes, androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy, androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType, boolean isEnabled, boolean isInitiallyEnabled, androidx.wear.watchface.complications.data.ComplicationType currentType, boolean fixedComplicationDataSource, android.os.Bundle complicationConfigExtras);
     method public android.graphics.Rect getBounds();
     method public int getBoundsType();
     method public android.os.Bundle getComplicationConfigExtras();
     method public androidx.wear.watchface.complications.data.ComplicationType getCurrentType();
     method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public java.util.List<androidx.wear.watchface.complications.data.ComplicationType> getSupportedTypes();
     method public boolean isEnabled();
@@ -18,17 +37,17 @@
     property public final android.os.Bundle complicationConfigExtras;
     property public final androidx.wear.watchface.complications.data.ComplicationType currentType;
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property public final boolean fixedComplicationDataSource;
     property public final boolean isEnabled;
     property public final boolean isInitiallyEnabled;
     property public final java.util.List<androidx.wear.watchface.complications.data.ComplicationType> supportedTypes;
   }
 
-  public final class DefaultComplicationDataSourcePolicyAndType {
-    ctor public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
-    method public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
-    method public androidx.wear.watchface.complications.data.ComplicationType getType();
+  @Deprecated public final class DefaultComplicationDataSourcePolicyAndType {
+    ctor @Deprecated public DefaultComplicationDataSourcePolicyAndType(androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy, androidx.wear.watchface.complications.data.ComplicationType type);
+    method @Deprecated public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getPolicy();
+    method @Deprecated public androidx.wear.watchface.complications.data.ComplicationType getType();
     property public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy policy;
     property public final androidx.wear.watchface.complications.data.ComplicationType type;
   }
@@ -147,7 +166,7 @@
   public interface WatchFaceControlClient extends java.lang.AutoCloseable {
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.HeadlessWatchFaceClient? createHeadlessWatchFaceClient(android.content.ComponentName watchFaceName, androidx.wear.watchface.client.DeviceConfig deviceConfig, @Px int surfaceWidth, @Px int surfaceHeight) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class}) public default static suspend Object? createWatchFaceControlClient(android.content.Context context, String watchFacePackageName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceControlClient> p) throws androidx.wear.watchface.client.WatchFaceControlClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceControlClient.ServiceStartFailureException;
-    method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
+    method @Deprecated @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType> getDefaultComplicationDataSourcePoliciesAndType(android.content.ComponentName watchFaceName) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.EditorServiceClient getEditorServiceClient() throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public androidx.wear.watchface.client.InteractiveWatchFaceClient? getInteractiveWatchFaceClientInstance(String instanceId) throws android.os.RemoteException;
     method @kotlin.jvm.Throws(exceptionClasses=RemoteException::class) public suspend Object? getOrCreateInteractiveWatchFaceClient(String id, androidx.wear.watchface.client.DeviceConfig deviceConfig, androidx.wear.watchface.client.WatchUiState watchUiState, androidx.wear.watchface.style.UserStyleData? userStyle, java.util.Map<java.lang.Integer,? extends androidx.wear.watchface.complications.data.ComplicationData>? slotIdToComplicationData, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.InteractiveWatchFaceClient> p) throws android.os.RemoteException;
@@ -172,6 +191,24 @@
     property public final String id;
   }
 
+  public interface WatchFaceMetadataClient extends java.lang.AutoCloseable {
+    method public java.util.Map<java.lang.Integer,androidx.wear.watchface.client.ComplicationSlotMetadata> getComplicationSlotMetadataMap();
+    method public androidx.wear.watchface.style.UserStyleSchema getUserStyleSchema();
+    field public static final androidx.wear.watchface.client.WatchFaceMetadataClient.Companion Companion;
+  }
+
+  public static final class WatchFaceMetadataClient.Companion {
+    method @kotlin.jvm.Throws(exceptionClasses={ServiceNotBoundException::class, ServiceStartFailureException::class, PackageManager.NameNotFoundException::class}) public suspend Object? create(android.content.Context context, android.content.ComponentName watchFaceName, kotlin.coroutines.Continuation<? super androidx.wear.watchface.client.WatchFaceMetadataClient> p) throws android.content.pm.PackageManager.NameNotFoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceNotBoundException, androidx.wear.watchface.client.WatchFaceMetadataClient.ServiceStartFailureException;
+  }
+
+  public static final class WatchFaceMetadataClient.ServiceNotBoundException extends java.lang.Exception {
+    ctor public WatchFaceMetadataClient.ServiceNotBoundException();
+  }
+
+  public static final class WatchFaceMetadataClient.ServiceStartFailureException extends java.lang.Exception {
+    ctor public WatchFaceMetadataClient.ServiceStartFailureException(optional String message);
+  }
+
   public final class WatchUiState {
     ctor public WatchUiState(boolean inAmbientMode, int interruptionFilter);
     method public boolean getInAmbientMode();
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
index 552c556..a9a410d 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
@@ -36,6 +36,7 @@
 import androidx.test.filters.MediumTest
 import androidx.test.screenshot.AndroidXScreenshotTestRule
 import androidx.test.screenshot.assertAgainstGolden
+import androidx.wear.watchface.CanvasComplication
 import androidx.wear.watchface.complications.ComplicationSlotBounds
 import androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy
 import androidx.wear.watchface.complications.SystemDataSources
@@ -57,12 +58,13 @@
 import androidx.wear.watchface.WatchFaceService
 import androidx.wear.watchface.WatchFaceType
 import androidx.wear.watchface.WatchState
-import androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType
 import androidx.wear.watchface.client.DeviceConfig
 import androidx.wear.watchface.client.HeadlessWatchFaceClient
 import androidx.wear.watchface.client.InteractiveWatchFaceClient
 import androidx.wear.watchface.client.WatchFaceControlClient
 import androidx.wear.watchface.client.WatchUiState
+import androidx.wear.watchface.complications.data.ComplicationData
+import androidx.wear.watchface.complications.data.NoDataComplicationData
 import androidx.wear.watchface.control.WatchFaceControlService
 import androidx.wear.watchface.samples.BLUE_STYLE
 import androidx.wear.watchface.samples.COLOR_STYLE_SETTING
@@ -320,6 +322,7 @@
         headlessInstance.close()
     }
 
+    @Suppress("DEPRECATION") // defaultDataSourceType
     @Test
     fun headlessComplicationDetails() {
         val headlessInstance = service.createHeadlessWatchFaceClient(
@@ -381,6 +384,52 @@
     }
 
     @Test
+    fun complicationProviderDefaults() {
+        val wallpaperService = TestComplicationProviderDefaultsWatchFaceService(
+            context,
+            surfaceHolder
+        )
+        val deferredInteractiveInstance = handlerCoroutineScope.async {
+            service.getOrCreateInteractiveWatchFaceClient(
+                "testId",
+                deviceConfig,
+                systemState,
+                null,
+                complications
+            )
+        }
+        // Create the engine which triggers the crashing watchface.
+        handler.post {
+            engine = wallpaperService.onCreateEngine() as WatchFaceService.EngineWrapper
+        }
+
+        // Wait for the instance to be created.
+        val interactiveInstance = awaitWithTimeout(deferredInteractiveInstance)
+
+        try {
+            assertThat(interactiveInstance.complicationSlotsState.keys).containsExactly(123)
+
+            val slot = interactiveInstance.complicationSlotsState[123]!!
+            assertThat(slot.defaultDataSourcePolicy.primaryDataSource)
+                .isEqualTo(ComponentName("com.package1", "com.app1"))
+            assertThat(slot.defaultDataSourcePolicy.primaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.PHOTO_IMAGE)
+
+            assertThat(slot.defaultDataSourcePolicy.secondaryDataSource)
+                .isEqualTo(ComponentName("com.package2", "com.app2"))
+            assertThat(slot.defaultDataSourcePolicy.secondaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.LONG_TEXT)
+
+            assertThat(slot.defaultDataSourcePolicy.systemDataSourceFallback)
+                .isEqualTo(SystemDataSources.DATA_SOURCE_STEP_COUNT)
+            assertThat(slot.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType)
+                .isEqualTo(ComplicationType.SHORT_TEXT)
+        } finally {
+            interactiveInstance.close()
+        }
+    }
+
+    @Test
     fun headlessUserStyleSchema() {
         val headlessInstance = service.createHeadlessWatchFaceClient(
             exampleWatchFaceComponentName,
@@ -499,6 +548,7 @@
         }
     }
 
+    @Suppress("DEPRECATION") // defaultDataSourceType
     @Test
     fun interactiveWatchFaceClient_ComplicationDetails() {
         val deferredInteractiveInstance = handlerCoroutineScope.async {
@@ -1026,6 +1076,7 @@
         }
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Test
     fun getDefaultProviderPolicies() {
         assertThat(
@@ -1033,14 +1084,14 @@
         ).containsExactlyEntriesIn(
             mapOf(
                 EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID to
-                    DefaultComplicationDataSourcePolicyAndType(
+                    androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType(
                         DefaultComplicationDataSourcePolicy(
                             SystemDataSources.DATA_SOURCE_DAY_OF_WEEK
                         ),
                         ComplicationType.SHORT_TEXT
                     ),
                 EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID to
-                    DefaultComplicationDataSourcePolicyAndType(
+                    androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType(
                         DefaultComplicationDataSourcePolicy(
                             SystemDataSources.DATA_SOURCE_STEP_COUNT
                         ),
@@ -1050,6 +1101,7 @@
         )
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Test
     fun getDefaultProviderPoliciesOldApi() {
         WatchFaceControlTestService.apiVersionOverride = 1
@@ -1058,14 +1110,14 @@
         ).containsExactlyEntriesIn(
             mapOf(
                 EXAMPLE_CANVAS_WATCHFACE_LEFT_COMPLICATION_ID to
-                    DefaultComplicationDataSourcePolicyAndType(
+                    androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType(
                         DefaultComplicationDataSourcePolicy(
                             SystemDataSources.DATA_SOURCE_DAY_OF_WEEK
                         ),
                         ComplicationType.SHORT_TEXT
                     ),
                 EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID to
-                    DefaultComplicationDataSourcePolicyAndType(
+                    androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType(
                         DefaultComplicationDataSourcePolicy(
                             SystemDataSources.DATA_SOURCE_STEP_COUNT
                         ),
@@ -1075,6 +1127,7 @@
         )
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Test
     fun getDefaultProviderPolicies_with_TestCrashingWatchFaceService() {
         // Tests that we can retrieve the DefaultComplicationDataSourcePolicy without invoking any
@@ -1090,7 +1143,7 @@
         ).containsExactlyEntriesIn(
             mapOf(
                 TestCrashingWatchFaceService.COMPLICATION_ID to
-                    DefaultComplicationDataSourcePolicyAndType(
+                    androidx.wear.watchface.client.DefaultComplicationDataSourcePolicyAndType(
                         DefaultComplicationDataSourcePolicy(
                             SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET
                         ),
@@ -1321,10 +1374,11 @@
                     { _, _ -> throw Exception("Deliberately crashing") },
                     listOf(ComplicationType.LONG_TEXT),
                     DefaultComplicationDataSourcePolicy(
-                        SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET
+                        SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET,
+                        ComplicationType.LONG_TEXT
                     ),
                     ComplicationSlotBounds(RectF(0.1f, 0.1f, 0.4f, 0.4f))
-                ).setDefaultDataSourceType(ComplicationType.LONG_TEXT).build()
+                ).build()
             ),
             currentUserStyleRepository
         )
@@ -1444,3 +1498,96 @@
         }
     )
 }
+
+internal class TestComplicationProviderDefaultsWatchFaceService(
+    testContext: Context,
+    private var surfaceHolderOverride: SurfaceHolder
+) : WatchFaceService() {
+    internal lateinit var watchFace: WatchFace
+
+    init {
+        attachBaseContext(testContext)
+    }
+
+    override fun getWallpaperSurfaceHolderOverride() = surfaceHolderOverride
+
+    override fun createComplicationSlotsManager(
+        currentUserStyleRepository: CurrentUserStyleRepository
+    ): ComplicationSlotsManager {
+        return ComplicationSlotsManager(
+            listOf(
+                ComplicationSlot.createRoundRectComplicationSlotBuilder(
+                    123,
+                    { _, _ ->
+                        object : CanvasComplication {
+                            override fun render(
+                                canvas: Canvas,
+                                bounds: Rect,
+                                zonedDateTime: ZonedDateTime,
+                                renderParameters: RenderParameters,
+                                slotId: Int
+                            ) {}
+
+                            override fun drawHighlight(
+                                canvas: Canvas,
+                                bounds: Rect,
+                                boundsType: Int,
+                                zonedDateTime: ZonedDateTime,
+                                color: Int
+                            ) {}
+
+                            override fun getData() = NoDataComplicationData()
+
+                            override fun loadData(
+                                complicationData: ComplicationData,
+                                loadDrawablesAsynchronous: Boolean
+                            ) {}
+                        }
+                    },
+                    listOf(
+                        ComplicationType.PHOTO_IMAGE,
+                        ComplicationType.LONG_TEXT,
+                        ComplicationType.SHORT_TEXT
+                    ),
+                    DefaultComplicationDataSourcePolicy(
+                        ComponentName("com.package1", "com.app1"),
+                        ComplicationType.PHOTO_IMAGE,
+                        ComponentName("com.package2", "com.app2"),
+                        ComplicationType.LONG_TEXT,
+                        SystemDataSources.DATA_SOURCE_STEP_COUNT,
+                        ComplicationType.SHORT_TEXT
+                    ),
+                    ComplicationSlotBounds(
+                        RectF(0.1f, 0.2f, 0.3f, 0.4f)
+                    )
+                )
+                    .build()
+            ),
+            currentUserStyleRepository
+        )
+    }
+
+    override suspend fun createWatchFace(
+        surfaceHolder: SurfaceHolder,
+        watchState: WatchState,
+        complicationSlotsManager: ComplicationSlotsManager,
+        currentUserStyleRepository: CurrentUserStyleRepository
+    ) = WatchFace(
+        WatchFaceType.DIGITAL,
+        object : Renderer.CanvasRenderer(
+            surfaceHolder,
+            currentUserStyleRepository,
+            watchState,
+            CanvasType.HARDWARE,
+            16
+        ) {
+            override fun render(canvas: Canvas, bounds: Rect, zonedDateTime: ZonedDateTime) {}
+
+            override fun renderHighlightLayer(
+                canvas: Canvas,
+                bounds: Rect,
+                zonedDateTime: ZonedDateTime
+            ) {}
+        }
+    )
+}
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceMetadataServiceTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceMetadataServiceTest.kt
index 9652dd3..1db16ba 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceMetadataServiceTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceMetadataServiceTest.kt
@@ -26,7 +26,6 @@
 import androidx.test.filters.MediumTest
 import androidx.wear.watchface.complications.SystemDataSources
 import androidx.wear.watchface.complications.data.ComplicationType
-import androidx.wear.watchface.client.WatchFaceClientExperimental
 import androidx.wear.watchface.client.WatchFaceMetadataClient
 import androidx.wear.watchface.control.WatchFaceControlService
 import androidx.wear.watchface.ComplicationSlotBoundsType
@@ -40,7 +39,6 @@
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
-@OptIn(WatchFaceClientExperimental::class)
 public class WatchFaceMetadataServiceTest {
     private val exampleWatchFaceComponentName = ComponentName(
         "androidx.wear.watchface.client.test",
@@ -49,7 +47,7 @@
 
     private val context = ApplicationProvider.getApplicationContext<Context>()
     private val service = runBlocking {
-        WatchFaceMetadataClient.createWatchFaceMetadataClientImpl(
+        WatchFaceMetadataClient.createImpl(
             context,
             Intent(context, WatchFaceControlTestService::class.java).apply {
                 action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
@@ -124,9 +122,10 @@
         Truth.assertThat(
             leftComplicationMetadata.defaultDataSourcePolicy.systemDataSourceFallback
         ).isEqualTo(SystemDataSources.DATA_SOURCE_DAY_OF_WEEK)
-        Truth.assertThat(leftComplicationMetadata.defaultDataSourceType).isEqualTo(
-            ComplicationType.SHORT_TEXT
-        )
+        Truth.assertThat(
+            leftComplicationMetadata.defaultDataSourcePolicy
+                .systemDataSourceFallbackDefaultType
+        ).isEqualTo(ComplicationType.SHORT_TEXT)
         Truth.assertThat(leftComplicationMetadata.supportedTypes).containsExactly(
             ComplicationType.RANGED_VALUE,
             ComplicationType.LONG_TEXT,
@@ -148,9 +147,10 @@
         Truth.assertThat(
             rightComplicationMetadata.defaultDataSourcePolicy.systemDataSourceFallback
         ).isEqualTo(SystemDataSources.DATA_SOURCE_STEP_COUNT)
-        Truth.assertThat(rightComplicationMetadata.defaultDataSourceType).isEqualTo(
-            ComplicationType.SHORT_TEXT
-        )
+        Truth.assertThat(
+            rightComplicationMetadata.defaultDataSourcePolicy
+                .systemDataSourceFallbackDefaultType
+        ).isEqualTo(ComplicationType.SHORT_TEXT)
         Truth.assertThat(rightComplicationMetadata.supportedTypes).containsExactly(
             ComplicationType.RANGED_VALUE,
             ComplicationType.LONG_TEXT,
@@ -163,7 +163,7 @@
     @Test
     public fun getSchema_static_metadata() {
         runBlocking {
-            val client = WatchFaceMetadataClient.createWatchFaceMetadataClientImpl(
+            val client = WatchFaceMetadataClient.createImpl(
                 context,
                 Intent(context, WatchFaceControlTestService::class.java).apply {
                     action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
@@ -183,4 +183,90 @@
             )
         }
     }
+
+    @Test
+    public fun getComplicationSlotMetadataMap_static_metadata() {
+        runBlocking {
+            val client = WatchFaceMetadataClient.createImpl(
+                context,
+                Intent(context, WatchFaceControlTestService::class.java).apply {
+                    action = WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE
+                },
+                exampleWatchFaceComponentName,
+                object : WatchFaceMetadataClient.Companion.ParserProvider() {
+                    override fun getParser(
+                        context: Context,
+                        watchFaceName: ComponentName
+                    ) = context.resources.getXml(R.xml.xml_watchface)
+                }
+            )
+            val complications = client.getComplicationSlotMetadataMap()
+
+            Truth.assertThat(complications.keys).containsExactly(10, 20)
+
+            Truth.assertThat(complications[10]!!.boundsType)
+                .isEqualTo(ComplicationSlotBoundsType.ROUND_RECT)
+
+            Truth.assertThat(complications[10]!!.supportedTypes)
+                .containsExactly(
+                    ComplicationType.SHORT_TEXT,
+                    ComplicationType.RANGED_VALUE,
+                    ComplicationType.SMALL_IMAGE
+                )
+
+            Truth.assertThat(complications[10]!!.defaultDataSourcePolicy.primaryDataSource)
+                .isEqualTo(ComponentName("com.app.example1", "com.app.example1.Class"))
+
+            Truth.assertThat(
+                complications[10]!!.defaultDataSourcePolicy.primaryDataSourceDefaultType
+            ).isEqualTo(ComplicationType.SHORT_TEXT)
+
+            Truth.assertThat(complications[10]!!.defaultDataSourcePolicy.secondaryDataSource)
+                .isEqualTo(ComponentName("com.app.example2", "com.app.example2.Class"))
+
+            Truth.assertThat(
+                complications[10]!!.defaultDataSourcePolicy.secondaryDataSourceDefaultType
+            ).isEqualTo(ComplicationType.SMALL_IMAGE)
+
+            Truth.assertThat(complications[10]!!.defaultDataSourcePolicy.systemDataSourceFallback)
+                .isEqualTo(SystemDataSources.DATA_SOURCE_WATCH_BATTERY)
+
+            Truth.assertThat(
+                complications[10]!!.defaultDataSourcePolicy
+                    .systemDataSourceFallbackDefaultType
+            ).isEqualTo(ComplicationType.RANGED_VALUE)
+
+            Truth.assertThat(
+                complications[10]!!.bounds!!.perComplicationTypeBounds[ComplicationType.SHORT_TEXT]
+            ).isEqualTo(RectF(0.3f, 0.7f, 0.7f, 0.9f))
+
+            Truth.assertThat(complications[20]!!.boundsType)
+                .isEqualTo(ComplicationSlotBoundsType.BACKGROUND)
+
+            Truth.assertThat(complications[20]!!.supportedTypes)
+                .containsExactly(ComplicationType.PHOTO_IMAGE)
+
+            Truth.assertThat(complications[20]!!.defaultDataSourcePolicy.primaryDataSource)
+                .isEqualTo(ComponentName("com.package", "com.app"))
+
+            Truth.assertThat(
+                complications[20]!!.defaultDataSourcePolicy.primaryDataSourceDefaultType
+            ).isEqualTo(ComplicationType.PHOTO_IMAGE)
+
+            Truth.assertThat(complications[20]!!.defaultDataSourcePolicy.secondaryDataSource)
+                .isNull()
+
+            Truth.assertThat(
+                complications[20]!!.defaultDataSourcePolicy.secondaryDataSourceDefaultType
+            ).isNull()
+
+            Truth.assertThat(complications[20]!!.defaultDataSourcePolicy.systemDataSourceFallback)
+                .isEqualTo(SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET)
+
+            Truth.assertThat(
+                complications[20]!!.defaultDataSourcePolicy
+                    .systemDataSourceFallbackDefaultType
+            ).isEqualTo(ComplicationType.PHOTO_IMAGE)
+        }
+    }
 }
diff --git a/wear/watchface/watchface-client/src/androidTest/res/xml/xml_watchface.xml b/wear/watchface/watchface-client/src/androidTest/res/xml/xml_watchface.xml
index a8e23f3..794d4bc 100644
--- a/wear/watchface/watchface-client/src/androidTest/res/xml/xml_watchface.xml
+++ b/wear/watchface/watchface-client/src/androidTest/res/xml/xml_watchface.xml
@@ -34,17 +34,22 @@
         app:slotId="10"
         app:boundsType="ROUND_RECT"
         app:supportedTypes="SHORT_TEXT|RANGED_VALUE|SMALL_IMAGE"
-        app:defaultDataSourceType="RANGED_VALUE"
-        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY">
+        app:primaryDataSource="com.app.example1/com.app.example1.Class"
+        app:primaryDataSourceDefaultType="SHORT_TEXT"
+        app:secondaryDataSource="com.app.example2/com.app.example2.Class"
+        app:secondaryDataSourceDefaultType="SMALL_IMAGE"
+        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY"
+        app:systemDataSourceFallbackDefaultType="RANGED_VALUE">
         <ComplicationSlotBounds app:left="0.3" app:top="0.7" app:right="0.7" app:bottom="0.9"/>
     </ComplicationSlot>
     <ComplicationSlot
         app:slotId="20"
         app:boundsType="BACKGROUND"
-        app:supportedTypes="LONG_TEXT"
-        app:defaultDataSourceType="LONG_TEXT"
+        app:supportedTypes="PHOTO_IMAGE"
         app:primaryDataSource="com.package/com.app"
-        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET">
+        app:primaryDataSourceDefaultType="PHOTO_IMAGE"
+        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET"
+        app:systemDataSourceFallbackDefaultType="PHOTO_IMAGE">
         <ComplicationSlotBounds app:left="0.1" app:top="0.2" app:right="0.3" app:bottom="0.4"/>
     </ComplicationSlot>
-</XmlWatchFace>
\ No newline at end of file
+</XmlWatchFace>
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/ComplicationSlotState.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/ComplicationSlotState.kt
index 135bb6a..05d92d5 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/ComplicationSlotState.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/ComplicationSlotState.kt
@@ -28,39 +28,163 @@
 import androidx.wear.watchface.style.UserStyleSetting.ComplicationSlotsUserStyleSetting.ComplicationSlotsOption
 import androidx.wear.watchface.style.UserStyleSetting.ComplicationSlotsUserStyleSetting.ComplicationSlotOverlay
 
-/**
- * State of the [ComplicationSlot].
- *
- * @param bounds Screen space bounds of the [ComplicationSlot] in pixels.
- * @param boundsType The type of the complication's bounds.
- * @param supportedTypes The [ComplicationType]s supported by this complication.
- * @param defaultDataSourcePolicy The [DefaultComplicationDataSourcePolicy] for this complication.
- * @param defaultDataSourceType The default [ComplicationType] for this complication.
- * @param isEnabled Whether or not the complication is currently enabled (i.e. it should be drawn).
- * @param isInitiallyEnabled Whether or not the complication was initially enabled before
- * considering any [ComplicationSlotsOption] whose [ComplicationSlotOverlay]s may enable or disable
- * complicationSlots.
- * @param currentType The [ComplicationType] of the complication's current [ComplicationData].
- * @param fixedComplicationDataSource Whether or not the complication data source is fixed (i.e the
- * user can't configure it).
- * @param complicationConfigExtras Extras to be merged into the Intent sent when invoking the
- * complication data source chooser activity.
- */
-public class ComplicationSlotState(
-    public val bounds: Rect,
-    @ComplicationSlotBoundsType public val boundsType: Int,
-    public val supportedTypes: List<ComplicationType>,
-    public val defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
-    public val defaultDataSourceType: ComplicationType,
+/** A snapshot of the state of a watch face [ComplicationSlot]. */
+public class ComplicationSlotState {
+    /** Screen space bounds of the [ComplicationSlot] in pixels. */
+    public val bounds: Rect
+
+    /** The type of the complication's bounds. */
+    @ComplicationSlotBoundsType
+    public val boundsType: Int
+
+    /** The [ComplicationType]s supported by this complication. */
+    public val supportedTypes: List<ComplicationType>
+
+    /** The [DefaultComplicationDataSourcePolicy] for this complication slot. */
+    public val defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy
+
+    /** The default [ComplicationType] for this complication. */
+    @Deprecated("Use defaultDataSourcePolicy.systemDataSourceFallbackDefaultType instead")
+    public val defaultDataSourceType: ComplicationType
+        get() = defaultDataSourcePolicy.systemDataSourceFallbackDefaultType
+
+    /** Whether or not the complication is currently enabled (i.e. it should be drawn. */
     @get:JvmName("isEnabled")
-    public val isEnabled: Boolean,
+    public val isEnabled: Boolean
+
+    /**
+     * Whether or not the complication was initially enabled before considering any
+     * [ComplicationSlotsOption] whose [ComplicationSlotOverlay]s may enable or disable
+     * complicationSlots.
+     */
     @get:JvmName("isInitiallyEnabled")
-    public val isInitiallyEnabled: Boolean,
-    public val currentType: ComplicationType,
-    @get:JvmName("isFixedComplicationDataSource")
-    public val fixedComplicationDataSource: Boolean,
+    public val isInitiallyEnabled: Boolean
+
+    /** The [ComplicationType] of the complication's current [ComplicationData]. */
+    public val currentType: ComplicationType
+
+    /** Whether or not the complication data source is fixed (i.e the user can't configure it). */
+    public val fixedComplicationDataSource: Boolean
+
+    /**
+     * Extras to be merged into the Intent sent when invoking the complication data source chooser
+     * activity.
+     */
     public val complicationConfigExtras: Bundle
-) {
+
+    /**
+     * @param bounds Screen space bounds of the [ComplicationSlot] in pixels.
+     * @param boundsType The type of the complication's bounds.
+     * @param supportedTypes The [ComplicationType]s supported by this complication.
+     * @param defaultDataSourcePolicy The [DefaultComplicationDataSourcePolicy] for this
+     * complication slot.
+     * @param isEnabled Whether or not the complication is currently enabled (i.e. it should be
+     * drawn).
+     * @param isInitiallyEnabled Whether or not the complication was initially enabled before
+     * considering any [ComplicationSlotsOption] whose [ComplicationSlotOverlay]s may enable or
+     * disable complicationSlots.
+     * @param currentType The [ComplicationType] of the complication's current [ComplicationData].
+     * @param fixedComplicationDataSource Whether or not the complication data source is fixed (i.e
+     * the user can't configure it).
+     * @param complicationConfigExtras Extras to be merged into the Intent sent when invoking the
+     * complication data source chooser activity.
+     */
+    public constructor(
+        bounds: Rect,
+        @ComplicationSlotBoundsType boundsType: Int,
+        supportedTypes: List<ComplicationType>,
+        defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
+        isEnabled: Boolean,
+        isInitiallyEnabled: Boolean,
+        currentType: ComplicationType,
+        fixedComplicationDataSource: Boolean,
+        complicationConfigExtras: Bundle
+    ) {
+        this.bounds = bounds
+        this.boundsType = boundsType
+        this.supportedTypes = supportedTypes
+        this.defaultDataSourcePolicy = defaultDataSourcePolicy
+        this.isEnabled = isEnabled
+        this.isInitiallyEnabled = isInitiallyEnabled
+        this.currentType = currentType
+        this.fixedComplicationDataSource = fixedComplicationDataSource
+        this.complicationConfigExtras = complicationConfigExtras
+    }
+
+    /**
+     * @param bounds Screen space bounds of the [ComplicationSlot] in pixels.
+     * @param boundsType The type of the complication's bounds.
+     * @param supportedTypes The [ComplicationType]s supported by this complication.
+     * @param defaultDataSourcePolicy The [DefaultComplicationDataSourcePolicy] for this
+     * complication slot.
+     * @param defaultDataSourceType The default [ComplicationType] for this complication.
+     * @param isEnabled Whether or not the complication is currently enabled (i.e. it should be
+     * drawn).
+     * @param isInitiallyEnabled Whether or not the complication was initially enabled before
+     * considering any [ComplicationSlotsOption] whose [ComplicationSlotOverlay]s may enable or
+     * disable complicationSlots.
+     * @param currentType The [ComplicationType] of the complication's current [ComplicationData].
+     * @param fixedComplicationDataSource Whether or not the complication data source is fixed (i.e
+     * the user can't configure it).
+     * @param complicationConfigExtras Extras to be merged into the Intent sent when invoking the
+     * complication data source chooser activity.
+     */
+    @Deprecated(
+        "defaultDataSourceType is depreciated", ReplaceWith(
+            "ComplicationSlotState(Rect, Int, List<ComplicationType>, " +
+                "DefaultComplicationDataSourcePolicy, Boolean, Boolean, ComplicationType, Boolean" +
+                ", Bundle)"
+        )
+    )
+    public constructor(
+        bounds: Rect,
+        @ComplicationSlotBoundsType boundsType: Int,
+        supportedTypes: List<ComplicationType>,
+        defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
+        defaultDataSourceType: ComplicationType,
+        isEnabled: Boolean,
+        isInitiallyEnabled: Boolean,
+        currentType: ComplicationType,
+        fixedComplicationDataSource: Boolean,
+        complicationConfigExtras: Bundle
+    ) {
+        this.bounds = bounds
+        this.boundsType = boundsType
+        this.supportedTypes = supportedTypes
+        this.defaultDataSourcePolicy = when {
+            defaultDataSourcePolicy.secondaryDataSource != null ->
+                DefaultComplicationDataSourcePolicy(
+                    defaultDataSourcePolicy.primaryDataSource!!,
+                    defaultDataSourcePolicy.primaryDataSourceDefaultType
+                        ?: defaultDataSourceType,
+                    defaultDataSourcePolicy.secondaryDataSource!!,
+                    defaultDataSourcePolicy.secondaryDataSourceDefaultType
+                        ?: defaultDataSourceType,
+                    defaultDataSourcePolicy.systemDataSourceFallback,
+                    defaultDataSourceType
+                )
+
+            defaultDataSourcePolicy.primaryDataSource != null ->
+                DefaultComplicationDataSourcePolicy(
+                    defaultDataSourcePolicy.primaryDataSource!!,
+                    defaultDataSourcePolicy.primaryDataSourceDefaultType
+                        ?: defaultDataSourceType,
+                    defaultDataSourcePolicy.systemDataSourceFallback,
+                    defaultDataSourceType
+                )
+
+            else -> DefaultComplicationDataSourcePolicy(
+                defaultDataSourcePolicy.systemDataSourceFallback,
+                defaultDataSourceType
+            )
+        }
+        this.isEnabled = isEnabled
+        this.isInitiallyEnabled = isInitiallyEnabled
+        this.currentType = currentType
+        this.fixedComplicationDataSource = fixedComplicationDataSource
+        this.complicationConfigExtras = complicationConfigExtras
+    }
+
     /** @hide */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public constructor(
@@ -70,10 +194,16 @@
         complicationStateWireFormat.boundsType,
         complicationStateWireFormat.supportedTypes.map { ComplicationType.fromWireType(it) },
         DefaultComplicationDataSourcePolicy(
-            complicationStateWireFormat.defaultProvidersToTry ?: emptyList(),
-            complicationStateWireFormat.fallbackSystemProvider
+            complicationStateWireFormat.defaultDataSourcesToTry ?: emptyList(),
+            complicationStateWireFormat.fallbackSystemProvider,
+            ComplicationType.fromWireType(
+                complicationStateWireFormat.primaryDataSourceDefaultType
+            ),
+            ComplicationType.fromWireType(
+                complicationStateWireFormat.secondaryDataSourceDefaultType
+            ),
+            ComplicationType.fromWireType(complicationStateWireFormat.defaultDataSourceType)
         ),
-        ComplicationType.fromWireType(complicationStateWireFormat.defaultProviderType),
         complicationStateWireFormat.isEnabled,
         complicationStateWireFormat.isInitiallyEnabled,
         ComplicationType.fromWireType(complicationStateWireFormat.currentType),
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
index 7bd8ca3..a0cf0ee 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
@@ -196,6 +196,8 @@
      * [DefaultComplicationDataSourcePolicyAndType]s for. It must be in the same APK the
      * WatchFaceControlClient is connected to. NB a single apk can contain multiple watch faces.
      */
+    @Deprecated("Use the WatchFaceMetadataClient instead.")
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Throws(RemoteException::class)
     public fun getDefaultComplicationDataSourcePoliciesAndType(
         watchFaceName: ComponentName
@@ -210,10 +212,12 @@
  * [androidx.wear.watchface.ComplicationSlot].
  * @param type The default [ComplicationType] for the [androidx.wear.watchface.ComplicationSlot].
  */
+@Deprecated("Use the WatchFaceMetadataClient instead.")
 public class DefaultComplicationDataSourcePolicyAndType(
     public val policy: DefaultComplicationDataSourcePolicy,
     public val type: ComplicationType
 ) {
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (javaClass != other?.javaClass) return false
@@ -351,6 +355,7 @@
         return EditorServiceClientImpl(service.editorService)
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     override fun getDefaultComplicationDataSourcePoliciesAndType(
         watchFaceName: ComponentName
     ): Map<Int, DefaultComplicationDataSourcePolicyAndType> = TraceEvent(
@@ -368,7 +373,10 @@
                         DefaultComplicationDataSourcePolicyAndType(
                             DefaultComplicationDataSourcePolicy(
                                 it.defaultProvidersToTry ?: emptyList(),
-                                it.fallbackSystemProvider
+                                it.fallbackSystemProvider,
+                                ComplicationType.fromWireType(it.defaultProviderType),
+                                ComplicationType.fromWireType(it.defaultProviderType),
+                                ComplicationType.fromWireType(it.defaultProviderType)
                             ),
                             ComplicationType.fromWireType(it.defaultProviderType)
                         )
diff --git a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceMetadataClient.kt b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceMetadataClient.kt
index 17b7ab2..a52081c 100644
--- a/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceMetadataClient.kt
+++ b/wear/watchface/watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceMetadataClient.kt
@@ -48,9 +48,8 @@
 
 /**
  * Interface for fetching watch face metadata. E.g. the [UserStyleSchema] and
- * [ComplicationSlotMetadata].
+ * [ComplicationSlotMetadata]. This must be [close]d after use to release resources.
  */
-@WatchFaceClientExperimental
 public interface WatchFaceMetadataClient : AutoCloseable {
 
     public companion object {
@@ -67,18 +66,18 @@
          * androidx.wear.watchface.XmlSchemaAndComplicationSlotsDefinition meta data node then
          * [PackageManager.NameNotFoundException] is thrown if [watchFaceName] is invalid.
          */
-        @JvmStatic
         @Throws(
             ServiceNotBoundException::class,
             ServiceStartFailureException::class,
             PackageManager.NameNotFoundException::class
         )
-        public suspend fun createWatchFaceMetadataClient(
+        @SuppressWarnings("MissingJvmstatic") // Can't really call a suspend fun from java.
+        public suspend fun create(
             context: Context,
             watchFaceName: ComponentName
         ): WatchFaceMetadataClient {
             // Fallback to binding the service (slow).
-            return createWatchFaceMetadataClientImpl(
+            return createImpl(
                 context,
                 Intent(WatchFaceControlService.ACTION_WATCHFACE_CONTROL_SERVICE).apply {
                     setPackage(watchFaceName.packageName)
@@ -107,7 +106,7 @@
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
         @Suppress("ShowingMemberInHiddenClass") // Spurious warning about exposing the
         // 'hidden' companion object, which _isn't_ hidden.
-        public suspend fun createWatchFaceMetadataClientImpl(
+        public suspend fun createImpl(
             context: Context,
             intent: Intent,
             watchFaceName: ComponentName,
@@ -164,14 +163,12 @@
     /**
      * Returns the watch face's [UserStyleSchema].
      */
-    @Throws(RemoteException::class)
     public fun getUserStyleSchema(): UserStyleSchema
 
     /**
      * Returns a map of [androidx.wear.watchface.ComplicationSlot] ID to [ComplicationSlotMetadata]
      * for each slot in the watch face's [androidx.wear.watchface.ComplicationSlotsManager].
      */
-    @Throws(RemoteException::class)
     public fun getComplicationSlotMetadataMap(): Map<Int, ComplicationSlotMetadata>
 }
 
@@ -185,8 +182,6 @@
  * during complication data source selection, this list should be non-empty.
  * @param defaultDataSourcePolicy The [DefaultComplicationDataSourcePolicy] which controls the
  * initial complication data source when the watch face is first installed.
- * @param defaultDataSourceType The default [ComplicationType] for the default  complication data
- * source.
  * @param isInitiallyEnabled At creation a complication slot is either enabled or disabled. This
  * can be overridden by a [ComplicationSlotsUserStyleSetting] (see
  * [ComplicationSlotOverlay.enabled]).
@@ -196,22 +191,19 @@
  * source is fixed (i.e. can't be changed by the user). This is useful for watch faces built
  * around specific complication  complication data sources.
  * @param complicationConfigExtras Extras to be merged into the Intent sent when invoking the
- *  complication data source chooser activity.
+ * complication data source chooser activity.
  */
-@WatchFaceClientExperimental
 public class ComplicationSlotMetadata(
     public val bounds: ComplicationSlotBounds?,
     @ComplicationSlotBoundsType public val boundsType: Int,
     public val supportedTypes: List<ComplicationType>,
     public val defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
-    public val defaultDataSourceType: ComplicationType,
     @get:JvmName("isInitiallyEnabled")
     public val isInitiallyEnabled: Boolean,
     public val fixedComplicationDataSource: Boolean,
     public val complicationConfigExtras: Bundle
 )
 
-@OptIn(WatchFaceClientExperimental::class)
 internal class WatchFaceMetadataClientImpl internal constructor(
     private val context: Context,
     private val service: IWatchFaceControlService,
@@ -254,55 +246,69 @@
 
     override fun getUserStyleSchema(): UserStyleSchema {
         requireNotClosed()
-        return if (service.apiVersion >= 3) {
-            UserStyleSchema(service.getUserStyleSchema(GetUserStyleSchemaParams(watchFaceName)))
-        } else {
-            headlessClient.userStyleSchema
+        try {
+            return if (service.apiVersion >= 3) {
+                UserStyleSchema(service.getUserStyleSchema(GetUserStyleSchemaParams(watchFaceName)))
+            } else {
+                headlessClient.userStyleSchema
+            }
+        } catch (e: RemoteException) {
+            throw RuntimeException(e)
         }
     }
 
     override fun getComplicationSlotMetadataMap(): Map<Int, ComplicationSlotMetadata> {
         requireNotClosed()
-        return if (service.apiVersion >= 3) {
-            val wireFormat = service.getComplicationSlotMetadata(
-                GetComplicationSlotMetadataParams(watchFaceName)
-            )
-            wireFormat.associateBy(
-                { it.id },
-                {
-                    val perSlotBounds = HashMap<ComplicationType, RectF>()
-                    for (i in it.complicationBoundsType.indices) {
-                        perSlotBounds[ComplicationType.fromWireType(it.complicationBoundsType[i])] =
-                            it.complicationBounds[i]
+        try {
+            return if (service.apiVersion >= 3) {
+                val wireFormat = service.getComplicationSlotMetadata(
+                    GetComplicationSlotMetadataParams(watchFaceName)
+                )
+                wireFormat.associateBy(
+                    { it.id },
+                    {
+                        val perSlotBounds = HashMap<ComplicationType, RectF>()
+                        for (i in it.complicationBoundsType.indices) {
+                            perSlotBounds[
+                                ComplicationType.fromWireType(it.complicationBoundsType[i])
+                            ] = it.complicationBounds[i]
+                        }
+                        ComplicationSlotMetadata(
+                            ComplicationSlotBounds(perSlotBounds),
+                            it.boundsType,
+                            it.supportedTypes.map { ComplicationType.fromWireType(it) },
+                            DefaultComplicationDataSourcePolicy(
+                                it.defaultDataSourcesToTry ?: emptyList(),
+                                it.fallbackSystemDataSource,
+                                ComplicationType.fromWireType(
+                                    it.primaryDataSourceDefaultType
+                                ),
+                                ComplicationType.fromWireType(
+                                    it.secondaryDataSourceDefaultType
+                                ),
+                                ComplicationType.fromWireType(it.defaultDataSourceType)
+                            ),
+                            it.isInitiallyEnabled,
+                            it.isFixedComplicationDataSource,
+                            it.complicationConfigExtras
+                        )
                     }
+                )
+            } else {
+                headlessClient.complicationSlotsState.mapValues {
                     ComplicationSlotMetadata(
-                        ComplicationSlotBounds(perSlotBounds),
-                        it.boundsType,
-                        it.supportedTypes.map { ComplicationType.fromWireType(it) },
-                        DefaultComplicationDataSourcePolicy(
-                            it.defaultDataSourcesToTry ?: emptyList(),
-                            it.fallbackSystemDataSource
-                        ),
-                        ComplicationType.fromWireType(it.defaultDataSourceType),
-                        it.isInitiallyEnabled,
-                        it.isFixedComplicationDataSource,
-                        it.complicationConfigExtras
+                        null,
+                        it.value.boundsType,
+                        it.value.supportedTypes,
+                        it.value.defaultDataSourcePolicy,
+                        it.value.isInitiallyEnabled,
+                        it.value.fixedComplicationDataSource,
+                        it.value.complicationConfigExtras
                     )
                 }
-            )
-        } else {
-            headlessClient.complicationSlotsState.mapValues {
-                ComplicationSlotMetadata(
-                    null,
-                    it.value.boundsType,
-                    it.value.supportedTypes,
-                    it.value.defaultDataSourcePolicy,
-                    it.value.defaultDataSourceType,
-                    it.value.isInitiallyEnabled,
-                    it.value.fixedComplicationDataSource,
-                    it.value.complicationConfigExtras
-                )
             }
+        } catch (e: RemoteException) {
+            throw RuntimeException(e)
         }
     }
 
@@ -315,7 +321,6 @@
     }
 }
 
-@OptIn(WatchFaceClientExperimental::class)
 internal class XmlWatchFaceMetadataClientImpl(
     private val xmlSchemaAndComplicationSlotsDefinition: XmlSchemaAndComplicationSlotsDefinition
 ) : WatchFaceMetadataClient {
@@ -331,7 +336,6 @@
                     it.boundsType,
                     it.supportedTypes,
                     it.defaultDataSourcePolicy,
-                    it.defaultDataSourceType,
                     it.initiallyEnabled,
                     it.fixedComplicationDataSource,
                     Bundle()
diff --git a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
index f2755f6..e26133a 100644
--- a/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
+++ b/wear/watchface/watchface-complications-data-source/src/main/java/androidx/wear/watchface/complications/datasource/ComplicationDataSourceService.kt
@@ -205,7 +205,8 @@
      * A request for representative preview data for the complication, for use in the editor UI.
      * Preview data is assumed to be static per type. E.g. for a complication that displays the date
      * and time of an event, rather than returning the real time it should return a fixed date and
-     * time such as 10:10 Aug 1st.
+     * time such as 10:10 Aug 1st. This data may be cached by the system and the result should be
+     * constant based on the current locale.
      *
      * This will be called on a background thread.
      *
diff --git a/wear/watchface/watchface-complications/api/current.txt b/wear/watchface/watchface-complications/api/current.txt
index 60a49fa..af0ccd0 100644
--- a/wear/watchface/watchface-complications/api/current.txt
+++ b/wear/watchface/watchface-complications/api/current.txt
@@ -47,16 +47,25 @@
 
   public final class DefaultComplicationDataSourcePolicy {
     ctor public DefaultComplicationDataSourcePolicy();
-    ctor public DefaultComplicationDataSourcePolicy(int systemProvider);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(int systemProvider);
+    ctor public DefaultComplicationDataSourcePolicy(int systemDataSource, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, android.content.ComponentName secondaryDataSource, androidx.wear.watchface.complications.data.ComplicationType secondaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
     method public android.content.ComponentName? getPrimaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getPrimaryDataSourceDefaultType();
     method public android.content.ComponentName? getSecondaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getSecondaryDataSourceDefaultType();
     method public int getSystemDataSourceFallback();
+    method public androidx.wear.watchface.complications.data.ComplicationType getSystemDataSourceFallbackDefaultType();
     method public boolean isEmpty();
     property public final android.content.ComponentName? primaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? primaryDataSourceDefaultType;
     property public final android.content.ComponentName? secondaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? secondaryDataSourceDefaultType;
     property public final int systemDataSourceFallback;
+    property public final androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType;
   }
 
   public final class SystemDataSources {
diff --git a/wear/watchface/watchface-complications/api/public_plus_experimental_current.txt b/wear/watchface/watchface-complications/api/public_plus_experimental_current.txt
index 60a49fa..af0ccd0 100644
--- a/wear/watchface/watchface-complications/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface-complications/api/public_plus_experimental_current.txt
@@ -47,16 +47,25 @@
 
   public final class DefaultComplicationDataSourcePolicy {
     ctor public DefaultComplicationDataSourcePolicy();
-    ctor public DefaultComplicationDataSourcePolicy(int systemProvider);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(int systemProvider);
+    ctor public DefaultComplicationDataSourcePolicy(int systemDataSource, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, android.content.ComponentName secondaryDataSource, androidx.wear.watchface.complications.data.ComplicationType secondaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
     method public android.content.ComponentName? getPrimaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getPrimaryDataSourceDefaultType();
     method public android.content.ComponentName? getSecondaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getSecondaryDataSourceDefaultType();
     method public int getSystemDataSourceFallback();
+    method public androidx.wear.watchface.complications.data.ComplicationType getSystemDataSourceFallbackDefaultType();
     method public boolean isEmpty();
     property public final android.content.ComponentName? primaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? primaryDataSourceDefaultType;
     property public final android.content.ComponentName? secondaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? secondaryDataSourceDefaultType;
     property public final int systemDataSourceFallback;
+    property public final androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType;
   }
 
   public final class SystemDataSources {
diff --git a/wear/watchface/watchface-complications/api/restricted_current.txt b/wear/watchface/watchface-complications/api/restricted_current.txt
index bf9465a..dbee437 100644
--- a/wear/watchface/watchface-complications/api/restricted_current.txt
+++ b/wear/watchface/watchface-complications/api/restricted_current.txt
@@ -50,16 +50,25 @@
 
   public final class DefaultComplicationDataSourcePolicy {
     ctor public DefaultComplicationDataSourcePolicy();
-    ctor public DefaultComplicationDataSourcePolicy(int systemProvider);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
-    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(int systemProvider);
+    ctor public DefaultComplicationDataSourcePolicy(int systemDataSource, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName dataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
+    ctor @Deprecated public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, android.content.ComponentName secondaryDataSource, int systemDataSourceFallback);
+    ctor public DefaultComplicationDataSourcePolicy(android.content.ComponentName primaryDataSource, androidx.wear.watchface.complications.data.ComplicationType primaryDataSourceDefaultType, android.content.ComponentName secondaryDataSource, androidx.wear.watchface.complications.data.ComplicationType secondaryDataSourceDefaultType, int systemDataSourceFallback, androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType);
     method public android.content.ComponentName? getPrimaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getPrimaryDataSourceDefaultType();
     method public android.content.ComponentName? getSecondaryDataSource();
+    method public androidx.wear.watchface.complications.data.ComplicationType? getSecondaryDataSourceDefaultType();
     method public int getSystemDataSourceFallback();
+    method public androidx.wear.watchface.complications.data.ComplicationType getSystemDataSourceFallbackDefaultType();
     method public boolean isEmpty();
     property public final android.content.ComponentName? primaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? primaryDataSourceDefaultType;
     property public final android.content.ComponentName? secondaryDataSource;
+    property public final androidx.wear.watchface.complications.data.ComplicationType? secondaryDataSourceDefaultType;
     property public final int systemDataSourceFallback;
+    property public final androidx.wear.watchface.complications.data.ComplicationType systemDataSourceFallbackDefaultType;
   }
 
   public final class SystemDataSources {
diff --git a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
index 7322082..a4137f3 100644
--- a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
+++ b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
@@ -19,6 +19,7 @@
 import android.content.ComponentName
 import androidx.annotation.RestrictTo
 import androidx.wear.watchface.complications.SystemDataSources.DataSourceId
+import androidx.wear.watchface.complications.data.ComplicationType
 import java.util.ArrayList
 
 /**
@@ -34,51 +35,140 @@
     /** First of two non-system data sources to be tried in turn. Set to null if not required. */
     public val primaryDataSource: ComponentName?
 
+    /**
+     * The default [ComplicationType] for [primaryDataSource]. Note Pre-R this will be ignored in
+     * favour of [systemDataSourceFallbackDefaultType].
+     */
+    public val primaryDataSourceDefaultType: ComplicationType?
+
     /** Second of two non-system data sources to be tried in turn. Set to null if not required. */
     public val secondaryDataSource: ComponentName?
 
+    /**
+     * The default [ComplicationType] for [secondaryDataSource]. Note Pre-R this will be ignored in
+     * favour of [systemDataSourceFallbackDefaultType].
+     */
+    public val secondaryDataSourceDefaultType: ComplicationType?
+
     /** Fallback in case none of the non-system data sources could be used. */
     @DataSourceId
     public val systemDataSourceFallback: Int
 
+    /** The default [ComplicationType] for [systemDataSourceFallback]. */
+    public val systemDataSourceFallbackDefaultType: ComplicationType
+
     /** @hide */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     public constructor(
         dataSources: List<ComponentName>,
-        @DataSourceId systemProviderFallback: Int
+        @DataSourceId systemDataSourceFallback: Int,
+        primaryDataSourceDefaultType: ComplicationType,
+        secondaryDataSourceDefaultType: ComplicationType,
+        systemDataSourceFallbackDefaultType: ComplicationType
     ) {
         this.primaryDataSource = if (dataSources.isNotEmpty()) dataSources[0] else null
+        this.primaryDataSourceDefaultType = primaryDataSourceDefaultType
+
         this.secondaryDataSource = if (dataSources.size >= 2) dataSources[1] else null
-        this.systemDataSourceFallback = systemProviderFallback
+        this.secondaryDataSourceDefaultType = secondaryDataSourceDefaultType
+
+        this.systemDataSourceFallback = systemDataSourceFallback
+        this.systemDataSourceFallbackDefaultType =
+            systemDataSourceFallbackDefaultType
     }
 
     /** No default complication data source. */
     public constructor() {
         primaryDataSource = null
+        primaryDataSourceDefaultType = null
         secondaryDataSource = null
+        secondaryDataSourceDefaultType = null
         systemDataSourceFallback = NO_DEFAULT_PROVIDER
+        systemDataSourceFallbackDefaultType = ComplicationType.NOT_CONFIGURED
     }
 
     /**
-     * Uses systemProvider as the default complication data source.
+     * Uses [systemProvider] as the default complication data source.
      */
+    @Deprecated(
+        "Use a constructor that sets the DefaultTypes",
+        ReplaceWith("DefaultComplicationDataSourcePolicy(Int, ComplicationType)")
+    )
     public constructor(@DataSourceId systemProvider: Int) {
         primaryDataSource = null
         secondaryDataSource = null
         systemDataSourceFallback = systemProvider
+        primaryDataSourceDefaultType = null
+        secondaryDataSourceDefaultType = null
+        systemDataSourceFallbackDefaultType = ComplicationType.NOT_CONFIGURED
+    }
+
+    /**
+     * Uses a system data source as the default complication data source.
+     *
+     * @param systemDataSource The system [DataSourceId] data source to use.
+     * @param systemDataSourceDefaultType The initial default [ComplicationType].
+     */
+    public constructor(
+        @DataSourceId systemDataSource: Int,
+        systemDataSourceDefaultType: ComplicationType
+    ) {
+        primaryDataSource = null
+        primaryDataSourceDefaultType = null
+        secondaryDataSource = null
+        secondaryDataSourceDefaultType = null
+        systemDataSourceFallback = systemDataSource
+        systemDataSourceFallbackDefaultType = systemDataSourceDefaultType
     }
 
     /**
      * Attempts to use [dataSource] as the default complication complication data source, if not
      * present then [systemDataSourceFallback] will be used instead.
      */
+    @Deprecated(
+        "Use a constructor that sets the DefaultTypes",
+        ReplaceWith(
+            "DefaultComplicationDataSourcePolicy(ComponentName, ComplicationType, Int," +
+                " ComplicationType)"
+        )
+    )
     public constructor(
         dataSource: ComponentName,
         @DataSourceId systemDataSourceFallback: Int
     ) {
         primaryDataSource = dataSource
+        primaryDataSourceDefaultType = null
         secondaryDataSource = null
+        secondaryDataSourceDefaultType = null
         this.systemDataSourceFallback = systemDataSourceFallback
+        systemDataSourceFallbackDefaultType = ComplicationType.NOT_CONFIGURED
+    }
+
+    /**
+     * Attempts to use [primaryDataSource] as the default complication complication data source, if
+     * not present then [systemDataSourceFallback] will be used instead.
+     *
+     * @param primaryDataSource The data source to try.
+     * @param primaryDataSourceDefaultType The default [ComplicationType] if
+     * primaryDataSource is selected. Note Pre-R this will be ignored in favour of
+     * [systemDataSourceFallbackDefaultType].
+     * @param systemDataSourceFallback The system data source to fall back on if neither provider is
+     * available.
+     * @param systemDataSourceFallbackDefaultType The default [ComplicationType] if
+     * systemDataSourceFallback is selected.
+    */
+    public constructor(
+        primaryDataSource: ComponentName,
+        primaryDataSourceDefaultType: ComplicationType,
+        @DataSourceId systemDataSourceFallback: Int,
+        systemDataSourceFallbackDefaultType: ComplicationType
+    ) {
+        this.primaryDataSource = primaryDataSource
+        this.primaryDataSourceDefaultType = primaryDataSourceDefaultType
+        secondaryDataSource = null
+        secondaryDataSourceDefaultType = null
+        this.systemDataSourceFallback = systemDataSourceFallback
+        this.systemDataSourceFallbackDefaultType = systemDataSourceFallbackDefaultType
     }
 
     /**
@@ -86,6 +176,13 @@
      * then [secondaryDataSource] will be tried and if that's not present then
      * [systemDataSourceFallback] will be used instead.
      */
+    @Deprecated(
+        "Use a constructor that sets the DefaultTypes",
+        ReplaceWith(
+            "DefaultComplicationDataSourcePolicy(ComponentName, ComplicationType, ComponentName, " +
+                "ComplicationType, Int, ComplicationType)"
+        )
+    )
     public constructor(
         primaryDataSource: ComponentName,
         secondaryDataSource: ComponentName,
@@ -94,6 +191,43 @@
         this.primaryDataSource = primaryDataSource
         this.secondaryDataSource = secondaryDataSource
         this.systemDataSourceFallback = systemDataSourceFallback
+        primaryDataSourceDefaultType = null
+        secondaryDataSourceDefaultType = null
+        systemDataSourceFallbackDefaultType = ComplicationType.NOT_CONFIGURED
+    }
+
+    /**
+     * Attempts to use [primaryDataSource] as the default complication data source, if not present
+     * then [secondaryDataSource] will be tried and if that's not present then
+     * [systemDataSourceFallback] will be used instead.
+     *
+     * @param primaryDataSource The first data source to try.
+     * @param primaryDataSourceDefaultType The default [ComplicationType] if
+     * primaryDataSource is selected. Note Pre-R this will be ignored in favour of
+     * [systemDataSourceFallbackDefaultType].
+     * @param secondaryDataSource The second data source to try.
+     * @param secondaryDataSourceDefaultType The default [ComplicationType] if
+     * secondaryDataSource is selected. Note Pre-R this will be ignored in favour of
+     * [systemDataSourceFallbackDefaultType].
+     * @param systemDataSourceFallback The system data source to fall back on if neither provider is
+     * available.
+     * @param systemDataSourceFallbackDefaultType The default [ComplicationType] if
+     * systemDataSourceFallback is selected.
+     */
+    public constructor(
+        primaryDataSource: ComponentName,
+        primaryDataSourceDefaultType: ComplicationType,
+        secondaryDataSource: ComponentName,
+        secondaryDataSourceDefaultType: ComplicationType,
+        @DataSourceId systemDataSourceFallback: Int,
+        systemDataSourceFallbackDefaultType: ComplicationType
+    ) {
+        this.primaryDataSource = primaryDataSource
+        this.primaryDataSourceDefaultType = primaryDataSourceDefaultType
+        this.secondaryDataSource = secondaryDataSource
+        this.secondaryDataSourceDefaultType = secondaryDataSourceDefaultType
+        this.systemDataSourceFallback = systemDataSourceFallback
+        this.systemDataSourceFallbackDefaultType = systemDataSourceFallbackDefaultType
     }
 
     /** Whether or not this DefaultComplicationDataSourcePolicy contains a default data source. */
diff --git a/wear/watchface/watchface-data/api/restricted_current.txt b/wear/watchface/watchface-data/api/restricted_current.txt
index 9342af9..5b22113 100644
--- a/wear/watchface/watchface-data/api/restricted_current.txt
+++ b/wear/watchface/watchface-data/api/restricted_current.txt
@@ -97,7 +97,8 @@
 package androidx.wear.watchface.data {
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class ComplicationSlotMetadataWireFormat implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
-    ctor public ComplicationSlotMetadataWireFormat(int, int[], android.graphics.RectF![], int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, android.os.Bundle);
+    ctor public ComplicationSlotMetadataWireFormat(int, int[], android.graphics.RectF![], int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, @android.support.wearable.complications.ComplicationData.ComplicationType int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, android.os.Bundle);
+    ctor @Deprecated public ComplicationSlotMetadataWireFormat(int, int[], android.graphics.RectF![], int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, android.os.Bundle);
     method public int describeContents();
     method public int getBoundsType();
     method public android.graphics.RectF![] getComplicationBounds();
@@ -107,6 +108,8 @@
     method public java.util.List<android.content.ComponentName!>? getDefaultDataSourcesToTry();
     method public int getFallbackSystemDataSource();
     method public int getId();
+    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getPrimaryDataSourceDefaultType();
+    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getSecondaryDataSourceDefaultType();
     method @android.support.wearable.complications.ComplicationData.ComplicationType public int[] getSupportedTypes();
     method public boolean isFixedComplicationDataSource();
     method public boolean isInitiallyEnabled();
@@ -115,15 +118,20 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public final class ComplicationStateWireFormat implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
-    ctor public ComplicationStateWireFormat(android.graphics.Rect, int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, android.os.Bundle);
+    ctor public ComplicationStateWireFormat(android.graphics.Rect, int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, @android.support.wearable.complications.ComplicationData.ComplicationType int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, android.os.Bundle);
+    ctor @Deprecated public ComplicationStateWireFormat(android.graphics.Rect, int, @android.support.wearable.complications.ComplicationData.ComplicationType int[], java.util.List<android.content.ComponentName!>?, int, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, boolean, @android.support.wearable.complications.ComplicationData.ComplicationType int, boolean, android.os.Bundle);
     method public int describeContents();
     method public android.graphics.Rect getBounds();
     method public int getBoundsType();
     method public android.os.Bundle getComplicationConfigExtras();
     method @android.support.wearable.complications.ComplicationData.ComplicationType public int getCurrentType();
-    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getDefaultProviderType();
-    method public java.util.List<android.content.ComponentName!>? getDefaultProvidersToTry();
+    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getDefaultDataSourceType();
+    method public java.util.List<android.content.ComponentName!>? getDefaultDataSourcesToTry();
+    method @Deprecated @android.support.wearable.complications.ComplicationData.ComplicationType public int getDefaultProviderType();
+    method @Deprecated public java.util.List<android.content.ComponentName!>? getDefaultProvidersToTry();
     method public int getFallbackSystemProvider();
+    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getPrimaryDataSourceDefaultType();
+    method @android.support.wearable.complications.ComplicationData.ComplicationType public int getSecondaryDataSourceDefaultType();
     method @android.support.wearable.complications.ComplicationData.ComplicationType public int[] getSupportedTypes();
     method public boolean isEnabled();
     method public boolean isFixedComplicationProvider();
diff --git a/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationSlotMetadataWireFormat.java b/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationSlotMetadataWireFormat.java
index ed4375f..ec0cc13 100644
--- a/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationSlotMetadataWireFormat.java
+++ b/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationSlotMetadataWireFormat.java
@@ -68,7 +68,7 @@
 
     @ParcelField(8)
     @ComplicationData.ComplicationType
-    int mDefaultDataSourceType;
+    int mDefaultType;
 
     @ParcelField(9)
     boolean mIsInitiallyEnabled;
@@ -80,6 +80,16 @@
     @NonNull
     Bundle mComplicationConfigExtras;
 
+    // Not supported in library v1.0.
+    @ParcelField(12)
+    @ComplicationData.ComplicationType
+    int mPrimaryDataSourceDefaultType = ComplicationData.TYPE_NOT_CONFIGURED;
+
+    // Not supported in library v1.0.
+    @ParcelField(13)
+    @ComplicationData.ComplicationType
+    int mSecondaryDataSourceDefaultType = ComplicationData.TYPE_NOT_CONFIGURED;
+
     /** Used by VersionedParcelable. */
     ComplicationSlotMetadataWireFormat() {
     }
@@ -93,6 +103,40 @@
             @Nullable List<ComponentName> defaultDataSourcesToTry,
             int fallbackSystemDataSource,
             @ComplicationData.ComplicationType int defaultDataSourceType,
+            @ComplicationData.ComplicationType int primaryDataSourceDefaultType,
+            @ComplicationData.ComplicationType int secondaryDataSourceDefaultType,
+            boolean isInitiallyEnabled,
+            boolean fixedComplicationDataSource,
+            @NonNull Bundle complicationConfigExtras) {
+        mId = id;
+        mComplicationBoundsType = complicationBoundsType;
+        mComplicationBounds = complicationBounds;
+        mBoundsType = boundsType;
+        mSupportedTypes = supportedTypes;
+        mDefaultDataSourcesToTry = defaultDataSourcesToTry;
+        mPrimaryDataSourceDefaultType = primaryDataSourceDefaultType;
+        mSecondaryDataSourceDefaultType = secondaryDataSourceDefaultType;
+        mFallbackSystemDataSource = fallbackSystemDataSource;
+        mDefaultType = defaultDataSourceType;
+        mIsInitiallyEnabled = isInitiallyEnabled;
+        mFixedComplicationDataSource = fixedComplicationDataSource;
+        mComplicationConfigExtras = complicationConfigExtras;
+    }
+
+    /**
+     * @deprecated Use the other constructor with primaryDataSourceDefaultType &
+     * secondaryDataSourceDefaultType instead.
+     */
+    @Deprecated
+    public ComplicationSlotMetadataWireFormat(
+            int id,
+            @NonNull int[] complicationBoundsType,
+            @NonNull RectF[] complicationBounds,
+            int boundsType,
+            @NonNull @ComplicationData.ComplicationType int[] supportedTypes,
+            @Nullable List<ComponentName> defaultDataSourcesToTry,
+            int fallbackSystemDataSource,
+            @ComplicationData.ComplicationType int defaultDataSourceType,
             boolean isInitiallyEnabled,
             boolean fixedComplicationDataSource,
             @NonNull Bundle complicationConfigExtras) {
@@ -103,7 +147,7 @@
         mSupportedTypes = supportedTypes;
         mDefaultDataSourcesToTry = defaultDataSourcesToTry;
         mFallbackSystemDataSource = fallbackSystemDataSource;
-        mDefaultDataSourceType = defaultDataSourceType;
+        mDefaultType = defaultDataSourceType;
         mIsInitiallyEnabled = isInitiallyEnabled;
         mFixedComplicationDataSource = fixedComplicationDataSource;
         mComplicationConfigExtras = complicationConfigExtras;
@@ -150,9 +194,37 @@
         return mFallbackSystemDataSource;
     }
 
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for
+     * {@link #getFallbackSystemDataSource}.
+     */
     @ComplicationData.ComplicationType
     public int getDefaultDataSourceType() {
-        return mDefaultDataSourceType;
+        return mDefaultType;
+    }
+
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for the first entry from
+     * {@link #getDefaultDataSourcesToTry}.
+     */
+    @ComplicationData.ComplicationType
+    public int getPrimaryDataSourceDefaultType() {
+        // Not supported in library v1.0. TYPE_NOT_CONFIGURED is not a valid API choice indicating
+        // and old client.
+        return (mPrimaryDataSourceDefaultType == ComplicationData.TYPE_NOT_CONFIGURED)
+                ? mDefaultType : mPrimaryDataSourceDefaultType;
+    }
+
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for the second entry from
+     * {@link #getDefaultDataSourcesToTry}.
+     */
+    @ComplicationData.ComplicationType
+    public int getSecondaryDataSourceDefaultType() {
+        // Not supported in library v1.0. TYPE_NOT_CONFIGURED is not a valid API choice indicating
+        // and old client.
+        return (mSecondaryDataSourceDefaultType == ComplicationData.TYPE_NOT_CONFIGURED)
+                ? mDefaultType : mSecondaryDataSourceDefaultType;
     }
 
     public boolean isInitiallyEnabled() {
diff --git a/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationStateWireFormat.java b/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationStateWireFormat.java
index e9c9ffd..56fa456 100644
--- a/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationStateWireFormat.java
+++ b/wear/watchface/watchface-data/src/main/java/androidx/wear/watchface/data/ComplicationStateWireFormat.java
@@ -57,14 +57,14 @@
 
     @ParcelField(4)
     @Nullable
-    List<ComponentName> mDefaultProvidersToTry;
+    List<ComponentName> mDefaultDataSourcesToTry;
 
     @ParcelField(5)
     int mFallbackSystemProvider;
 
     @ParcelField(6)
     @ComplicationData.ComplicationType
-    int mDefaultProviderType;
+    int mDefaultType;
 
     @ParcelField(7)
     boolean mIsEnabled;
@@ -83,6 +83,16 @@
     @NonNull
     Bundle mComplicationConfigExtras;
 
+    // Not supported in library v1.0.
+    @ParcelField(12)
+    @ComplicationData.ComplicationType
+    int mPrimaryDataSourceDefaultType = ComplicationData.TYPE_NOT_CONFIGURED;
+
+    // Not supported in library v1.0.
+    @ParcelField(13)
+    @ComplicationData.ComplicationType
+    int mSecondaryDataSourceDefaultType = ComplicationData.TYPE_NOT_CONFIGURED;
+
     /** Used by VersionedParcelable. */
     ComplicationStateWireFormat() {
     }
@@ -91,9 +101,11 @@
             @NonNull Rect bounds,
             int boundsType,
             @NonNull @ComplicationData.ComplicationType int[] supportedTypes,
-            @Nullable List<ComponentName> defaultProvidersToTry,
+            @Nullable List<ComponentName> defaultDataSourcesToTry,
             int fallbackSystemProvider,
-            @ComplicationData.ComplicationType int defaultProviderType,
+            @ComplicationData.ComplicationType int defaultDataSourceType,
+            @ComplicationData.ComplicationType int primaryDataSourceDefaultType,
+            @ComplicationData.ComplicationType int secondaryDataSourceDefaultType,
             boolean isEnabled,
             boolean isInitiallyEnabled,
             @ComplicationData.ComplicationType int currentType,
@@ -102,9 +114,38 @@
         mBounds = bounds;
         mBoundsType = boundsType;
         mSupportedTypes = supportedTypes;
-        mDefaultProvidersToTry = defaultProvidersToTry;
+        mDefaultDataSourcesToTry = defaultDataSourcesToTry;
         mFallbackSystemProvider = fallbackSystemProvider;
-        mDefaultProviderType = defaultProviderType;
+        mDefaultType = defaultDataSourceType;
+        mPrimaryDataSourceDefaultType = primaryDataSourceDefaultType;
+        mSecondaryDataSourceDefaultType = secondaryDataSourceDefaultType;
+        mIsEnabled = isEnabled;
+        mIsInitiallyEnabled = isInitiallyEnabled;
+        mCurrentType = currentType;
+        mFixedComplicationProvider = fixedComplicationProvider;
+        mComplicationConfigExtras = complicationConfigExtras;
+    }
+
+    /** @deprecated Use the other constructor instead. */
+    @Deprecated
+    public ComplicationStateWireFormat(
+            @NonNull Rect bounds,
+            int boundsType,
+            @NonNull @ComplicationData.ComplicationType int[] supportedTypes,
+            @Nullable List<ComponentName> defaultDataSourcesToTry,
+            int fallbackSystemProvider,
+            @ComplicationData.ComplicationType int defaultDataSourceType,
+            boolean isEnabled,
+            boolean isInitiallyEnabled,
+            @ComplicationData.ComplicationType int currentType,
+            boolean fixedComplicationProvider,
+            @NonNull Bundle complicationConfigExtras) {
+        mBounds = bounds;
+        mBoundsType = boundsType;
+        mSupportedTypes = supportedTypes;
+        mDefaultDataSourcesToTry = defaultDataSourcesToTry;
+        mFallbackSystemProvider = fallbackSystemProvider;
+        mDefaultType = defaultDataSourceType;
         mIsEnabled = isEnabled;
         mIsInitiallyEnabled = isInitiallyEnabled;
         mCurrentType = currentType;
@@ -130,23 +171,68 @@
     /**
      * Along with {@link #getFallbackSystemProvider} this is the wire format for
      * DefaultComplicationDataSourcePolicy.
+     * @deprecated Use {@link #getDefaultDataSourcesToTry} instead.
      */
+    @Deprecated
     @Nullable
     public List<ComponentName> getDefaultProvidersToTry() {
-        return mDefaultProvidersToTry;
+        return mDefaultDataSourcesToTry;
     }
 
     /**
-     * Along with {@link #getDefaultProvidersToTry} this is the wire format for
+     * Along with {@link #getFallbackSystemProvider} this is the wire format for
+     * DefaultComplicationDataSourcePolicy.
+     */
+    @Nullable
+    public List<ComponentName> getDefaultDataSourcesToTry() {
+        return mDefaultDataSourcesToTry;
+    }
+
+    /**
+     * Along with {@link #getDefaultDataSourcesToTry} this is the wire format for
      * DefaultComplicationDataSourcePolicy.
      */
     public int getFallbackSystemProvider() {
         return mFallbackSystemProvider;
     }
 
+    /** @deprecated Use {@link #getDefaultDataSourceType} instead. */
+    @Deprecated
     @ComplicationData.ComplicationType
     public int getDefaultProviderType() {
-        return mDefaultProviderType;
+        return mDefaultType;
+    }
+
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for {@link #getFallbackSystemProvider}.
+     */
+    @ComplicationData.ComplicationType
+    public int getDefaultDataSourceType() {
+        return mDefaultType;
+    }
+
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for the first entry from
+     * {@link #getDefaultDataSourcesToTry}.
+     */
+    @ComplicationData.ComplicationType
+    public int getPrimaryDataSourceDefaultType() {
+        // Not supported in library v1.0. TYPE_NOT_CONFIGURED is not a valid API choice indicating
+        // and old client.
+        return (mPrimaryDataSourceDefaultType == ComplicationData.TYPE_NOT_CONFIGURED)
+                ? mDefaultType : mPrimaryDataSourceDefaultType;
+    }
+
+    /**
+     * @return The {@link ComplicationData.ComplicationType} for the second entry from
+     * {@link #getDefaultDataSourcesToTry}.
+     */
+    @ComplicationData.ComplicationType
+    public int getSecondaryDataSourceDefaultType() {
+        // Not supported in library v1.0. TYPE_NOT_CONFIGURED is not a valid API choice indicating
+        // and old client.
+        return (mSecondaryDataSourceDefaultType == ComplicationData.TYPE_NOT_CONFIGURED)
+                ? mDefaultType : mSecondaryDataSourceDefaultType;
     }
 
     public boolean isEnabled() {
@@ -161,7 +247,6 @@
         return mFixedComplicationProvider;
     }
 
-    @NonNull
     @ComplicationData.ComplicationType
     public int getCurrentType() {
         return mCurrentType;
diff --git a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionGuavaTest.kt b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionGuavaTest.kt
index 6cff617..45ed5db 100644
--- a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionGuavaTest.kt
+++ b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionGuavaTest.kt
@@ -81,6 +81,7 @@
             mockInvalidateCallback
         )
     private val leftComplication =
+        @Suppress("DEPRECATION")
         ComplicationSlot.createRoundRectComplicationSlotBuilder(
             LEFT_COMPLICATION_ID,
             { _, _, -> mockLeftCanvasComplication },
@@ -103,6 +104,7 @@
             mockInvalidateCallback
         )
     private val rightComplication =
+        @Suppress("DEPRECATION")
         ComplicationSlot.createRoundRectComplicationSlotBuilder(
             RIGHT_COMPLICATION_ID,
             { _, _, -> mockRightCanvasComplication },
diff --git a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
index e874449..54abaae 100644
--- a/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
+++ b/wear/watchface/watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditorSessionTest.kt
@@ -34,6 +34,7 @@
 import android.os.Handler
 import android.os.HandlerThread
 import android.os.IBinder
+import android.os.Looper
 import android.support.wearable.complications.IPreviewComplicationDataCallback
 import android.support.wearable.complications.IProviderInfoService
 import android.support.wearable.watchface.Constants
@@ -485,7 +486,13 @@
                 ComplicationType.MONOCHROMATIC_IMAGE,
                 ComplicationType.SMALL_IMAGE
             ),
-            DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET),
+
+            DefaultComplicationDataSourcePolicy(
+                ComponentName("com.primary.package", "com.primary.app"),
+                ComplicationType.LONG_TEXT,
+                SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET,
+                ComplicationType.SHORT_TEXT
+            ),
             ComplicationSlotBounds(
                 ComplicationType.values().associateWith {
                     if (it == ComplicationType.LONG_TEXT) {
@@ -495,7 +502,7 @@
                     }
                 }
             )
-        ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
+        )
             .build()
 
     private val rightComplication =
@@ -509,7 +516,14 @@
                 ComplicationType.MONOCHROMATIC_IMAGE,
                 ComplicationType.SMALL_IMAGE
             ),
-            DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_DAY_OF_WEEK),
+            DefaultComplicationDataSourcePolicy(
+                ComponentName("com.primary.package", "com.primary.app"),
+                ComplicationType.LONG_TEXT,
+                ComponentName("com.secondary.package", "com.secondary.app"),
+                ComplicationType.PHOTO_IMAGE,
+                SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+                ComplicationType.SHORT_TEXT
+            ),
             ComplicationSlotBounds(
                 ComplicationType.values().associateWith {
                     if (it == ComplicationType.LONG_TEXT) {
@@ -519,7 +533,7 @@
                     }
                 }
             )
-        ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
+        )
             .setConfigExtras(
                 Bundle().apply {
                     putString(PROVIDER_CHOOSER_EXTRA_KEY, PROVIDER_CHOOSER_EXTRA_VALUE)
@@ -583,6 +597,12 @@
                 onDestroyLatch.countDown()
                 backgroundHandlerThread.quitSafely()
             }
+
+            override fun setComplicationSlotConfigExtrasChangeCallback(
+                callback: WatchFace.ComplicationSlotConfigExtrasChangeCallback?
+            ) {
+                complicationSlotsManager.configExtrasChangeCallback = callback
+            }
         }
         if (!shouldTimeout) {
             WatchFace.registerEditorDelegate(watchComponentName, editorDelegate)
@@ -758,6 +778,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION") // defaultDataSourceType
     public fun complicationState() {
         val scenario = createOnWatchFaceEditingTestActivity(
             emptyList(),
@@ -766,40 +787,54 @@
         scenario.onActivity {
             val complicationSlotsState = it.editorSession.complicationSlotsState.value
             assertThat(complicationSlotsState.size).isEqualTo(3)
-            assertThat(complicationSlotsState[LEFT_COMPLICATION_ID]!!.bounds)
-                .isEqualTo(Rect(120, 160, 160, 240))
-            assertThat(complicationSlotsState[LEFT_COMPLICATION_ID]!!.boundsType)
-                .isEqualTo(ComplicationSlotBoundsType.ROUND_RECT)
-            assertFalse(
-                complicationSlotsState[LEFT_COMPLICATION_ID]!!.fixedComplicationDataSource
+            val leftSlot = complicationSlotsState[LEFT_COMPLICATION_ID]!!
+            assertThat(leftSlot.bounds).isEqualTo(Rect(120, 160, 160, 240))
+            assertThat(leftSlot.boundsType).isEqualTo(ComplicationSlotBoundsType.ROUND_RECT)
+            assertFalse(leftSlot.fixedComplicationDataSource)
+            assertTrue(leftSlot.isInitiallyEnabled)
+            assertThat(leftSlot.defaultDataSourcePolicy.primaryDataSource)
+                .isEqualTo(ComponentName("com.primary.package", "com.primary.app"))
+            assertThat(leftSlot.defaultDataSourcePolicy.primaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.LONG_TEXT)
+            assertThat(leftSlot.defaultDataSourcePolicy.secondaryDataSource).isNull()
+            assertThat(leftSlot.defaultDataSourcePolicy.secondaryDataSourceDefaultType)
+                .isNull()
+            assertThat(leftSlot.defaultDataSourcePolicy.systemDataSourceFallback).isEqualTo(
+                SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET
             )
-            assertTrue(
-                complicationSlotsState[LEFT_COMPLICATION_ID]!!.isInitiallyEnabled
-            )
+            assertThat(
+                leftSlot.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType
+            ).isEqualTo(ComplicationType.SHORT_TEXT)
+            assertThat(leftSlot.defaultDataSourceType).isEqualTo(ComplicationType.SHORT_TEXT)
 
-            assertThat(complicationSlotsState[RIGHT_COMPLICATION_ID]!!.bounds)
-                .isEqualTo(Rect(240, 160, 280, 240))
-            assertThat(complicationSlotsState[RIGHT_COMPLICATION_ID]!!.boundsType)
-                .isEqualTo(ComplicationSlotBoundsType.ROUND_RECT)
-            assertFalse(
-                complicationSlotsState[RIGHT_COMPLICATION_ID]!!.fixedComplicationDataSource
-            )
-            assertTrue(complicationSlotsState[RIGHT_COMPLICATION_ID]!!.isInitiallyEnabled)
+            val rightSlot = complicationSlotsState[RIGHT_COMPLICATION_ID]!!
+            assertThat(rightSlot.bounds).isEqualTo(Rect(240, 160, 280, 240))
+            assertThat(rightSlot.boundsType).isEqualTo(ComplicationSlotBoundsType.ROUND_RECT)
+            assertFalse(rightSlot.fixedComplicationDataSource)
+            assertTrue(rightSlot.isInitiallyEnabled)
+            assertThat(rightSlot.defaultDataSourcePolicy.primaryDataSource)
+                .isEqualTo(ComponentName("com.primary.package", "com.primary.app"))
+            assertThat(rightSlot.defaultDataSourcePolicy.primaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.LONG_TEXT)
+            assertThat(rightSlot.defaultDataSourcePolicy.secondaryDataSource)
+                .isEqualTo(ComponentName("com.secondary.package", "com.secondary.app"))
+            assertThat(rightSlot.defaultDataSourcePolicy.secondaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.PHOTO_IMAGE)
+            assertThat(
+                rightSlot.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType
+            ).isEqualTo(ComplicationType.SHORT_TEXT)
+            assertThat(rightSlot.defaultDataSourceType).isEqualTo(ComplicationType.SHORT_TEXT)
 
-            assertThat(complicationSlotsState[BACKGROUND_COMPLICATION_ID]!!.bounds)
-                .isEqualTo(screenBounds)
-            assertThat(complicationSlotsState[BACKGROUND_COMPLICATION_ID]!!.boundsType)
-                .isEqualTo(ComplicationSlotBoundsType.BACKGROUND)
-            assertFalse(
-                complicationSlotsState[BACKGROUND_COMPLICATION_ID]!!.fixedComplicationDataSource
-            )
-            assertFalse(
-                complicationSlotsState[BACKGROUND_COMPLICATION_ID]!!.isInitiallyEnabled
-            )
+            val backgroundSlot = complicationSlotsState[BACKGROUND_COMPLICATION_ID]!!
+            assertThat(backgroundSlot.bounds).isEqualTo(screenBounds)
+            assertThat(backgroundSlot.boundsType).isEqualTo(ComplicationSlotBoundsType.BACKGROUND)
+            assertFalse(backgroundSlot.fixedComplicationDataSource)
+            assertFalse(backgroundSlot.isInitiallyEnabled)
             // We could test more state but this should be enough.
         }
     }
 
+    @Suppress("DEPRECATION") // Old DefaultComplicationDataSourcePolicy constructor
     @Test
     public fun fixedComplicationDataSource() {
         val mockLeftCanvasComplication =
@@ -1440,6 +1475,57 @@
     }
 
     @Test
+    public fun mutable_configExtras() {
+        // Invoke the test data source chooser to record the result.
+        ComplicationHelperActivity.useTestComplicationDataSourceChooserActivity = true
+        // Invoke the data source chooser without checking for permissions first.
+        ComplicationHelperActivity.skipPermissionCheck = true
+
+        val chosenComplicationDataSourceInfo = ComplicationDataSourceInfo(
+            "TestDataSource3App",
+            "TestDataSource3",
+            Icon.createWithBitmap(
+                Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+            ),
+            ComplicationType.LONG_TEXT,
+            dataSource3
+        )
+        TestComplicationDataSourceChooserActivity.lastIntent = null
+        TestComplicationDataSourceChooserActivity.resultIntent = Intent().apply {
+            putExtra(
+                ComplicationDataSourceChooserIntent.EXTRA_PROVIDER_INFO,
+                chosenComplicationDataSourceInfo.toWireComplicationProviderInfo()
+            )
+        }
+
+        val scenario = createOnWatchFaceEditingTestActivity(
+            emptyList(),
+            listOf(leftComplication, rightComplication)
+        )
+
+        lateinit var editorSession: EditorSession
+        scenario.onActivity { activity ->
+            editorSession = activity.editorSession
+        }
+
+        runBlocking {
+            rightComplication.configExtras = Bundle().apply {
+                putString(PROVIDER_CHOOSER_EXTRA_KEY, "Updated")
+            }
+
+            val chosenComplicationDataSource =
+                editorSession.openComplicationDataSourceChooser(RIGHT_COMPLICATION_ID)
+            assertThat(chosenComplicationDataSource).isNotNull()
+
+            assertThat(
+                TestComplicationDataSourceChooserActivity.lastIntent?.extras?.getString(
+                    PROVIDER_CHOOSER_EXTRA_KEY
+                )
+            ).isEqualTo("Updated")
+        }
+    }
+
+    @Test
     public fun getComplicationIdAt() {
         val scenario = createOnWatchFaceEditingTestActivity(
             emptyList(),
@@ -2118,8 +2204,8 @@
 
         scenario.onActivity { activity ->
             val mockWatchFaceHostApi = mock(WatchFaceHostApi::class.java)
-            val mockHandler = mock(Handler::class.java)
-            `when`(mockWatchFaceHostApi.getUiThreadHandler()).thenReturn(mockHandler)
+            val handler = Handler(Looper.myLooper()!!)
+            `when`(mockWatchFaceHostApi.getUiThreadHandler()).thenReturn(handler)
             `when`(mockWatchFaceHostApi.getContext()).thenReturn(
                 ApplicationProvider.getApplicationContext<Context>()
             )
@@ -2165,7 +2251,7 @@
                     watchState,
                     mockWatchFaceHostApi,
                     CompletableDeferred(),
-                    CoroutineScope(mockHandler.asCoroutineDispatcher())
+                    CoroutineScope(handler.asCoroutineDispatcher())
                 ),
                 null
             )
diff --git a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
index ab7bdf8..03bca3c 100644
--- a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
+++ b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
@@ -788,7 +788,6 @@
                 it.value.boundsType,
                 it.value.supportedTypes,
                 it.value.defaultDataSourcePolicy,
-                it.value.defaultDataSourceType,
                 it.value.enabled,
                 it.value.initiallyEnabled,
                 it.value.renderer.getData().type,
@@ -889,6 +888,7 @@
 
         // Note this has to be done last to ensure tests are not racy.
         if (this::editorDelegate.isInitialized) {
+            editorDelegate.setComplicationSlotConfigExtrasChangeCallback(null)
             editorDelegate.onDestroy()
         }
     }
@@ -910,6 +910,14 @@
         )
 
         fetchComplicationsDataJob = fetchComplicationsData(backgroundCoroutineScope)
+
+        editorDelegate.setComplicationSlotConfigExtrasChangeCallback(
+            object : WatchFace.ComplicationSlotConfigExtrasChangeCallback {
+                override fun onComplicationSlotConfigExtrasChanged() {
+                    maybeUpdateComplicationSlotsState()
+                }
+            }
+        )
     }
 
     override val showComplicationDeniedDialogIntent
diff --git a/wear/watchface/watchface-guava/src/androidTest/res/xml/xml_watchface.xml b/wear/watchface/watchface-guava/src/androidTest/res/xml/xml_watchface.xml
index d32e161..12bf5f7 100644
--- a/wear/watchface/watchface-guava/src/androidTest/res/xml/xml_watchface.xml
+++ b/wear/watchface/watchface-guava/src/androidTest/res/xml/xml_watchface.xml
@@ -33,17 +33,18 @@
         app:slotId="10"
         app:boundsType="ROUND_RECT"
         app:supportedTypes="SHORT_TEXT|RANGED_VALUE|SMALL_IMAGE"
-        app:defaultDataSourceType="RANGED_VALUE"
-        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY">
+        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY"
+        app:systemDataSourceFallbackDefaultType="RANGED_VALUE">
         <ComplicationSlotBounds app:left="0.3" app:top="0.7" app:right="0.7" app:bottom="0.9"/>
     </ComplicationSlot>
     <ComplicationSlot
         app:slotId="20"
         app:boundsType="BACKGROUND"
         app:supportedTypes="LONG_TEXT"
-        app:defaultDataSourceType="LONG_TEXT"
         app:primaryDataSource="com.package/com.app"
-        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET">
+        app:primaryDataSourceDefaultType="LONG_TEXT"
+        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET"
+        app:systemDataSourceFallbackDefaultType="LONG_TEXT">
         <ComplicationSlotBounds app:left="0.1" app:top="0.2" app:right="0.3" app:bottom="0.4"/>
     </ComplicationSlot>
 </XmlWatchFace>
\ No newline at end of file
diff --git a/wear/watchface/watchface-samples-minimal-complications/src/main/res/xml/xml_watchface.xml b/wear/watchface/watchface-samples-minimal-complications/src/main/res/xml/xml_watchface.xml
index 0113968..4bfae43 100644
--- a/wear/watchface/watchface-samples-minimal-complications/src/main/res/xml/xml_watchface.xml
+++ b/wear/watchface/watchface-samples-minimal-complications/src/main/res/xml/xml_watchface.xml
@@ -19,8 +19,8 @@
         app:slotId="1"
         app:boundsType="ROUND_RECT"
         app:supportedTypes="SHORT_TEXT|RANGED_VALUE|SMALL_IMAGE"
-        app:defaultDataSourceType="RANGED_VALUE"
-        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY">
+        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY"
+        app:systemDataSourceFallbackDefaultType="RANGED_VALUE">
         <ComplicationSlotBounds app:left="0.3" app:top="0.7" app:right="0.7" app:bottom="0.9"/>
     </ComplicationSlot>
 </XmlWatchFace>
diff --git a/wear/watchface/watchface/api/current.txt b/wear/watchface/watchface/api/current.txt
index a8af996..1685908 100644
--- a/wear/watchface/watchface/api/current.txt
+++ b/wear/watchface/watchface/api/current.txt
@@ -34,7 +34,7 @@
     method @UiThread public androidx.wear.watchface.complications.ComplicationSlotBounds getComplicationSlotBounds();
     method public android.os.Bundle getConfigExtras();
     method @UiThread public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public int getId();
     method public boolean getInitiallyEnabled();
@@ -45,6 +45,7 @@
     method @UiThread public boolean isEnabled();
     method @UiThread public void render(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
     method @UiThread public void renderHighlightLayer(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
+    method public void setConfigExtras(android.os.Bundle value);
     property @UiThread public final int accessibilityTraversalIndex;
     property public final int boundsType;
     property public final androidx.wear.watchface.CanvasComplicationFactory canvasComplicationFactory;
@@ -52,7 +53,7 @@
     property @UiThread public final androidx.wear.watchface.complications.ComplicationSlotBounds complicationSlotBounds;
     property public final android.os.Bundle configExtras;
     property @UiThread public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property @UiThread public final boolean enabled;
     property public final boolean fixedComplicationDataSource;
     property public final int id;
@@ -67,7 +68,7 @@
     method public androidx.wear.watchface.ComplicationSlot build();
     method public androidx.wear.watchface.ComplicationSlot.Builder setAccessibilityTraversalIndex(int accessibilityTraversalIndex);
     method public androidx.wear.watchface.ComplicationSlot.Builder setConfigExtras(android.os.Bundle extras);
-    method public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
+    method @Deprecated public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
     method public androidx.wear.watchface.ComplicationSlot.Builder setEnabled(boolean enabled);
     method public androidx.wear.watchface.ComplicationSlot.Builder setFixedComplicationDataSource(boolean fixedComplicationDataSource);
   }
diff --git a/wear/watchface/watchface/api/public_plus_experimental_current.txt b/wear/watchface/watchface/api/public_plus_experimental_current.txt
index a8af996..1685908 100644
--- a/wear/watchface/watchface/api/public_plus_experimental_current.txt
+++ b/wear/watchface/watchface/api/public_plus_experimental_current.txt
@@ -34,7 +34,7 @@
     method @UiThread public androidx.wear.watchface.complications.ComplicationSlotBounds getComplicationSlotBounds();
     method public android.os.Bundle getConfigExtras();
     method @UiThread public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public int getId();
     method public boolean getInitiallyEnabled();
@@ -45,6 +45,7 @@
     method @UiThread public boolean isEnabled();
     method @UiThread public void render(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
     method @UiThread public void renderHighlightLayer(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
+    method public void setConfigExtras(android.os.Bundle value);
     property @UiThread public final int accessibilityTraversalIndex;
     property public final int boundsType;
     property public final androidx.wear.watchface.CanvasComplicationFactory canvasComplicationFactory;
@@ -52,7 +53,7 @@
     property @UiThread public final androidx.wear.watchface.complications.ComplicationSlotBounds complicationSlotBounds;
     property public final android.os.Bundle configExtras;
     property @UiThread public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property @UiThread public final boolean enabled;
     property public final boolean fixedComplicationDataSource;
     property public final int id;
@@ -67,7 +68,7 @@
     method public androidx.wear.watchface.ComplicationSlot build();
     method public androidx.wear.watchface.ComplicationSlot.Builder setAccessibilityTraversalIndex(int accessibilityTraversalIndex);
     method public androidx.wear.watchface.ComplicationSlot.Builder setConfigExtras(android.os.Bundle extras);
-    method public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
+    method @Deprecated public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
     method public androidx.wear.watchface.ComplicationSlot.Builder setEnabled(boolean enabled);
     method public androidx.wear.watchface.ComplicationSlot.Builder setFixedComplicationDataSource(boolean fixedComplicationDataSource);
   }
diff --git a/wear/watchface/watchface/api/restricted_current.txt b/wear/watchface/watchface/api/restricted_current.txt
index 958905b..4b8c715 100644
--- a/wear/watchface/watchface/api/restricted_current.txt
+++ b/wear/watchface/watchface/api/restricted_current.txt
@@ -34,7 +34,7 @@
     method @UiThread public androidx.wear.watchface.complications.ComplicationSlotBounds getComplicationSlotBounds();
     method public android.os.Bundle getConfigExtras();
     method @UiThread public androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy getDefaultDataSourcePolicy();
-    method @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
+    method @Deprecated @UiThread public androidx.wear.watchface.complications.data.ComplicationType getDefaultDataSourceType();
     method public boolean getFixedComplicationDataSource();
     method public int getId();
     method public boolean getInitiallyEnabled();
@@ -45,6 +45,7 @@
     method @UiThread public boolean isEnabled();
     method @UiThread public void render(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
     method @UiThread public void renderHighlightLayer(android.graphics.Canvas canvas, java.time.ZonedDateTime zonedDateTime, androidx.wear.watchface.RenderParameters renderParameters);
+    method public void setConfigExtras(android.os.Bundle value);
     property @UiThread public final int accessibilityTraversalIndex;
     property public final int boundsType;
     property public final androidx.wear.watchface.CanvasComplicationFactory canvasComplicationFactory;
@@ -52,7 +53,7 @@
     property @UiThread public final androidx.wear.watchface.complications.ComplicationSlotBounds complicationSlotBounds;
     property public final android.os.Bundle configExtras;
     property @UiThread public final androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy defaultDataSourcePolicy;
-    property @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
+    property @Deprecated @UiThread public final androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType;
     property @UiThread public final boolean enabled;
     property public final boolean fixedComplicationDataSource;
     property public final int id;
@@ -67,7 +68,7 @@
     method public androidx.wear.watchface.ComplicationSlot build();
     method public androidx.wear.watchface.ComplicationSlot.Builder setAccessibilityTraversalIndex(int accessibilityTraversalIndex);
     method public androidx.wear.watchface.ComplicationSlot.Builder setConfigExtras(android.os.Bundle extras);
-    method public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
+    method @Deprecated public androidx.wear.watchface.ComplicationSlot.Builder setDefaultDataSourceType(androidx.wear.watchface.complications.data.ComplicationType defaultDataSourceType);
     method public androidx.wear.watchface.ComplicationSlot.Builder setEnabled(boolean enabled);
     method public androidx.wear.watchface.ComplicationSlot.Builder setFixedComplicationDataSource(boolean fixedComplicationDataSource);
   }
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasAnalogWatchFaceService.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasAnalogWatchFaceService.kt
index 5dfd948d..e569a54 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasAnalogWatchFaceService.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasAnalogWatchFaceService.kt
@@ -257,10 +257,13 @@
                 ComplicationType.MONOCHROMATIC_IMAGE,
                 ComplicationType.SMALL_IMAGE
             ),
-            DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_DAY_OF_WEEK),
+            DefaultComplicationDataSourcePolicy(
+                SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+                ComplicationType.SHORT_TEXT
+            ),
             ComplicationSlotBounds(RectF(0.2f, 0.4f, 0.4f, 0.6f))
-        ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-            .build()
+        ).build()
+
         val rightComplication = ComplicationSlot.createRoundRectComplicationSlotBuilder(
             EXAMPLE_CANVAS_WATCHFACE_RIGHT_COMPLICATION_ID,
             canvasComplicationFactory,
@@ -271,10 +274,12 @@
                 ComplicationType.MONOCHROMATIC_IMAGE,
                 ComplicationType.SMALL_IMAGE
             ),
-            DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_STEP_COUNT),
+            DefaultComplicationDataSourcePolicy(
+                SystemDataSources.DATA_SOURCE_STEP_COUNT,
+                ComplicationType.SHORT_TEXT
+            ),
             ComplicationSlotBounds(RectF(0.6f, 0.4f, 0.8f, 0.6f))
-        ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-            .build()
+        ).build()
         return ComplicationSlotsManager(
             listOf(leftComplication, rightComplication),
             currentUserStyleRepository
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasDigitalWatchFaceService.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasDigitalWatchFaceService.kt
index c4218f2..74939e4e 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasDigitalWatchFaceService.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleCanvasDigitalWatchFaceService.kt
@@ -95,10 +95,6 @@
 internal val MARGIN_FRACTION_WITHOUT_COMPLICATION = Vec2f(0.2f, 0.2f)
 internal val MARGIN_FRACTION_WITH_COMPLICATION = Vec2f(0.4f, 0.4f)
 
-// If the lightness in HSL color space is greater than this threshold, this color would be regarded
-// as a light color.
-internal const val BACKGROUND_COLOR_LIGHTNESS_THRESHOLD = 0.5f
-
 enum class ComplicationID {
     UPPER,
     RIGHT,
@@ -465,10 +461,6 @@
     )
 }
 
-fun Byte.toUnsigned(): Int {
-    return if (this < 0) this + 256 else this.toInt()
-}
-
 /** A simple example canvas based digital watch face. */
 class ExampleCanvasDigitalWatchFaceService : WatchFaceService() {
     // Lazy because the context isn't initialized til later.
@@ -527,15 +519,17 @@
             ComplicationType.MONOCHROMATIC_IMAGE,
             ComplicationType.SMALL_IMAGE
         ),
-        DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_WATCH_BATTERY),
+        DefaultComplicationDataSourcePolicy(
+            SystemDataSources.DATA_SOURCE_WATCH_BATTERY,
+            ComplicationType.SHORT_TEXT
+        ),
         ComplicationSlotBounds(
             createBoundsRect(
                 LEFT_CIRCLE_COMPLICATION_CENTER_FRACTION,
                 CIRCLE_COMPLICATION_DIAMETER_FRACTION
             )
         )
-    ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-        .build()
+    ).build()
 
     private val rightComplication = ComplicationSlot.createRoundRectComplicationSlotBuilder(
         ComplicationID.RIGHT.ordinal,
@@ -546,15 +540,17 @@
             ComplicationType.MONOCHROMATIC_IMAGE,
             ComplicationType.SMALL_IMAGE
         ),
-        DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_DATE),
+        DefaultComplicationDataSourcePolicy(
+            SystemDataSources.DATA_SOURCE_DATE,
+            ComplicationType.SHORT_TEXT
+        ),
         ComplicationSlotBounds(
             createBoundsRect(
                 RIGHT_CIRCLE_COMPLICATION_CENTER_FRACTION,
                 CIRCLE_COMPLICATION_DIAMETER_FRACTION
             )
         )
-    ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-        .build()
+    ).build()
 
     private val upperAndLowerComplicationTypes = listOf(
         ComplicationType.LONG_TEXT,
@@ -568,7 +564,10 @@
         ComplicationID.UPPER.ordinal,
         canvasComplicationFactory,
         upperAndLowerComplicationTypes,
-        DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_WORLD_CLOCK),
+        DefaultComplicationDataSourcePolicy(
+            SystemDataSources.DATA_SOURCE_WORLD_CLOCK,
+            ComplicationType.LONG_TEXT
+        ),
         ComplicationSlotBounds(
             ComplicationType.values().associateWith {
                 if (it == ComplicationType.LONG_TEXT) {
@@ -584,14 +583,16 @@
                 }
             }
         )
-    ).setDefaultDataSourceType(ComplicationType.LONG_TEXT)
-        .build()
+    ).build()
 
     private val lowerComplication = ComplicationSlot.createRoundRectComplicationSlotBuilder(
         ComplicationID.LOWER.ordinal,
         canvasComplicationFactory,
         upperAndLowerComplicationTypes,
-        DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_NEXT_EVENT),
+        DefaultComplicationDataSourcePolicy(
+            SystemDataSources.DATA_SOURCE_NEXT_EVENT,
+            ComplicationType.LONG_TEXT
+        ),
         ComplicationSlotBounds(
             ComplicationType.values().associateWith {
                 if (it == ComplicationType.LONG_TEXT) {
@@ -607,8 +608,7 @@
                 }
             }
         )
-    ).setDefaultDataSourceType(ComplicationType.LONG_TEXT)
-        .build()
+    ).build()
 
     private val backgroundComplication = ComplicationSlot.createBackgroundComplicationSlotBuilder(
         ComplicationID.BACKGROUND.ordinal,
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
index 518482f..1745784 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/ExampleOpenGLWatchFaceService.kt
@@ -127,10 +127,12 @@
             ComplicationType.MONOCHROMATIC_IMAGE,
             ComplicationType.SMALL_IMAGE
         ),
-        DefaultComplicationDataSourcePolicy(SystemDataSources.DATA_SOURCE_DAY_OF_WEEK),
+        DefaultComplicationDataSourcePolicy(
+            SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+            ComplicationType.SHORT_TEXT
+        ),
         ComplicationSlotBounds(RectF(0.2f, 0.7f, 0.4f, 0.9f))
-    ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-        .build()
+    ).build()
 
     public override fun createUserStyleSchema() = UserStyleSchema(listOf(colorStyleSetting))
 
diff --git a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
index 44805cb..dd33dc2 100644
--- a/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
+++ b/wear/watchface/watchface/samples/src/main/java/androidx/wear/watchface/samples/KDocExampleWatchFace.kt
@@ -127,11 +127,11 @@
                             ComplicationType.SMALL_IMAGE
                         ),
                         DefaultComplicationDataSourcePolicy(
-                            SystemDataSources.DATA_SOURCE_DAY_OF_WEEK
+                            SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
+                            ComplicationType.SHORT_TEXT
                         ),
                         ComplicationSlotBounds(RectF(0.15625f, 0.1875f, 0.84375f, 0.3125f))
-                    ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-                        .build(),
+                    ).build(),
                     ComplicationSlot.createRoundRectComplicationSlotBuilder(
                         /*id */ 1,
                         canvasComplicationFactory,
@@ -143,11 +143,11 @@
                             ComplicationType.SMALL_IMAGE
                         ),
                         DefaultComplicationDataSourcePolicy(
-                            SystemDataSources.DATA_SOURCE_STEP_COUNT
+                            SystemDataSources.DATA_SOURCE_STEP_COUNT,
+                            ComplicationType.SHORT_TEXT
                         ),
                         ComplicationSlotBounds(RectF(0.1f, 0.5625f, 0.35f, 0.8125f))
-                    ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
-                        .build()
+                    ).build()
                 ),
                 currentUserStyleRepository
             )
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
index c2abc4f..75fb8bb 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
@@ -237,12 +237,17 @@
                 ComplicationType.RANGED_VALUE,
                 ComplicationType.SMALL_IMAGE
             )
-            assertThat(slotA.defaultDataSourceType).isEqualTo(ComplicationType.RANGED_VALUE)
             assertThat(slotA.defaultDataSourcePolicy.primaryDataSource).isNull()
+            assertThat(slotA.defaultDataSourcePolicy.primaryDataSourceDefaultType)
+                .isNull()
             assertThat(slotA.defaultDataSourcePolicy.secondaryDataSource).isNull()
+            assertThat(slotA.defaultDataSourcePolicy.secondaryDataSourceDefaultType)
+                .isNull()
             assertThat(slotA.defaultDataSourcePolicy.systemDataSourceFallback).isEqualTo(
                 SystemDataSources.DATA_SOURCE_WATCH_BATTERY
             )
+            assertThat(slotA.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType)
+                .isEqualTo(ComplicationType.RANGED_VALUE)
             assertThat(
                 slotA.complicationSlotBounds.perComplicationTypeBounds[
                     ComplicationType.SHORT_TEXT
@@ -254,16 +259,21 @@
             val slotB = watchFaceImpl.complicationSlotsManager.complicationSlots[20]!!
             assertThat(slotB.boundsType).isEqualTo(ComplicationSlotBoundsType.BACKGROUND)
             assertThat(slotB.supportedTypes).containsExactly(
-                ComplicationType.LONG_TEXT
+                ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT
             )
-            assertThat(slotB.defaultDataSourceType).isEqualTo(ComplicationType.LONG_TEXT)
             assertThat(slotB.defaultDataSourcePolicy.primaryDataSource).isEqualTo(
                 ComponentName("com.package", "com.app")
             )
+            assertThat(slotB.defaultDataSourcePolicy.primaryDataSourceDefaultType)
+                .isEqualTo(ComplicationType.SHORT_TEXT)
             assertThat(slotB.defaultDataSourcePolicy.secondaryDataSource).isNull()
+            assertThat(slotB.defaultDataSourcePolicy.secondaryDataSourceDefaultType)
+                .isNull()
             assertThat(slotB.defaultDataSourcePolicy.systemDataSourceFallback).isEqualTo(
                 SystemDataSources.DATA_SOURCE_SUNRISE_SUNSET
             )
+            assertThat(slotB.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType)
+                .isEqualTo(ComplicationType.LONG_TEXT)
             assertThat(
                 slotB.complicationSlotBounds.perComplicationTypeBounds[
                     ComplicationType.SHORT_TEXT
diff --git a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface.xml b/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface.xml
index fdf7dbe..240fec6 100644
--- a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface.xml
+++ b/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface.xml
@@ -33,17 +33,18 @@
         app:slotId="10"
         app:boundsType="ROUND_RECT"
         app:supportedTypes="SHORT_TEXT|RANGED_VALUE|SMALL_IMAGE"
-        app:defaultDataSourceType="RANGED_VALUE"
-        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY">
+        app:systemDataSourceFallback="DATA_SOURCE_WATCH_BATTERY"
+        app:systemDataSourceFallbackDefaultType="RANGED_VALUE">
         <ComplicationSlotBounds app:left="0.3" app:top="0.7" app:right="0.7" app:bottom="0.9"/>
     </ComplicationSlot>
     <ComplicationSlot
         app:slotId="20"
         app:boundsType="BACKGROUND"
-        app:supportedTypes="LONG_TEXT"
-        app:defaultDataSourceType="LONG_TEXT"
+        app:supportedTypes="LONG_TEXT|SHORT_TEXT"
         app:primaryDataSource="com.package/com.app"
-        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET">
+        app:primaryDataSourceDefaultType="SHORT_TEXT"
+        app:systemDataSourceFallback="DATA_SOURCE_SUNRISE_SUNSET"
+        app:systemDataSourceFallbackDefaultType="LONG_TEXT">
         <ComplicationSlotBounds app:left="0.1" app:top="0.2" app:right="0.3" app:bottom="0.4"/>
     </ComplicationSlot>
 </XmlWatchFace>
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
index 6411050..5e60d2d 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
@@ -184,6 +184,7 @@
         context.unregisterReceiver(actionBatteryLowReceiver)
         context.unregisterReceiver(actionBatteryOkayReceiver)
         context.unregisterReceiver(actionPowerConnectedReceiver)
+        context.unregisterReceiver(actionPowerDisconnectedReceiver)
         context.unregisterReceiver(mockTimeReceiver)
     }
 }
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
index 8e16e8c..0b9ca50 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
@@ -208,7 +208,8 @@
  * Editors need to know the initial state of a complication slot to predict the effects of making a
  * style change.
  * @param configExtras Extras to be merged into the Intent sent when invoking the complication data
- * source chooser activity.
+ * source chooser activity. This features is intended for OEM watch faces where they have elements
+ * that behave like a complication but are in fact entirely watch face specific.
  * @param fixedComplicationDataSource  Whether or not the complication data source is fixed (i.e.
  * can't be changed by the user).  This is useful for watch faces built around specific
  * complications.
@@ -226,7 +227,7 @@
     defaultDataSourceType: ComplicationType,
     @get:JvmName("isInitiallyEnabled")
     public val initiallyEnabled: Boolean,
-    public val configExtras: Bundle,
+    configExtras: Bundle,
     @get:JvmName("isFixedComplicationDataSource")
     public val fixedComplicationDataSource: Boolean,
     public val tapFilter: ComplicationTapFilter
@@ -238,6 +239,17 @@
     internal lateinit var complicationSlotsManager: ComplicationSlotsManager
 
     /**
+     * Extras to be merged into the Intent sent when invoking the complication data source chooser
+     * activity.
+     */
+    public var configExtras: Bundle = configExtras
+        set(value) {
+            field = value
+            complicationSlotsManager.configExtrasChangeCallback
+                ?.onComplicationSlotConfigExtrasChanged()
+        }
+
+    /**
      * The [CanvasComplication] used to render the complication. This can't be used until after
      * [WatchFaceService.createWatchFace] has completed.
      */
@@ -395,7 +407,7 @@
         private val id: Int,
         private val canvasComplicationFactory: CanvasComplicationFactory,
         private val supportedTypes: List<ComplicationType>,
-        private val defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
+        private var defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
         @ComplicationSlotBoundsType private val boundsType: Int,
         private val bounds: ComplicationSlotBounds,
         private val complicationTapFilter: ComplicationTapFilter
@@ -427,9 +439,38 @@
          * Note care should be taken to ensure [defaultDataSourceType] is compatible with the
          * [DefaultComplicationDataSourcePolicy].
          */
+        @Deprecated("Instead set DefaultComplicationDataSourcePolicy" +
+            ".systemDataSourceFallbackDefaultType.")
         public fun setDefaultDataSourceType(
             defaultDataSourceType: ComplicationType
         ): Builder {
+            defaultDataSourcePolicy = when {
+                defaultDataSourcePolicy.secondaryDataSource != null ->
+                    DefaultComplicationDataSourcePolicy(
+                        defaultDataSourcePolicy.primaryDataSource!!,
+                        defaultDataSourcePolicy.primaryDataSourceDefaultType
+                            ?: defaultDataSourceType,
+                        defaultDataSourcePolicy.secondaryDataSource!!,
+                        defaultDataSourcePolicy.secondaryDataSourceDefaultType
+                            ?: defaultDataSourceType,
+                        defaultDataSourcePolicy.systemDataSourceFallback,
+                        defaultDataSourceType
+                    )
+
+                defaultDataSourcePolicy.primaryDataSource != null ->
+                    DefaultComplicationDataSourcePolicy(
+                        defaultDataSourcePolicy.primaryDataSource!!,
+                        defaultDataSourcePolicy.primaryDataSourceDefaultType
+                            ?: defaultDataSourceType,
+                        defaultDataSourcePolicy.systemDataSourceFallback,
+                        defaultDataSourceType
+                    )
+
+                else -> DefaultComplicationDataSourcePolicy(
+                    defaultDataSourcePolicy.systemDataSourceFallback,
+                    defaultDataSourceType
+                )
+            }
             this.defaultDataSourceType = defaultDataSourceType
             return this
         }
@@ -561,6 +602,8 @@
     /**
      * The default [ComplicationType] to use alongside [defaultDataSourcePolicy].
      */
+    @Deprecated("Use DefaultComplicationDataSourcePolicy." +
+        "systemDataSourceFallbackDefaultType instead")
     public var defaultDataSourceType: ComplicationType = defaultDataSourceType
         @UiThread
         get
@@ -740,14 +783,20 @@
         writer.println(
             "defaultDataSourcePolicy.primaryDataSource=${defaultDataSourcePolicy.primaryDataSource}"
         )
+        writer.println("defaultDataSourcePolicy.primaryDataSourceDefaultDataSourceType=" +
+            defaultDataSourcePolicy.primaryDataSourceDefaultType)
         writer.println(
             "defaultDataSourcePolicy.secondaryDataSource=" +
                 defaultDataSourcePolicy.secondaryDataSource
         )
+        writer.println("defaultDataSourcePolicy.secondaryDataSourceDefaultDataSourceType=" +
+            defaultDataSourcePolicy.secondaryDataSourceDefaultType)
         writer.println(
             "defaultDataSourcePolicy.systemDataSourceFallback=" +
                 defaultDataSourcePolicy.systemDataSourceFallback
         )
+        writer.println("defaultDataSourcePolicy.systemDataSourceFallbackDefaultType=" +
+            defaultDataSourcePolicy.systemDataSourceFallbackDefaultType)
         writer.println("data=${renderer.getData()}")
         val bounds = complicationSlotBounds.perComplicationTypeBounds.map {
             "${it.key} -> ${it.value}"
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
index 5def43e..a51976f 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
@@ -118,6 +118,11 @@
 
     private val complicationListeners = HashSet<TapCallback>()
 
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public var configExtrasChangeCallback: WatchFace.ComplicationSlotConfigExtrasChangeCallback? =
+        null
+
     @VisibleForTesting
     internal constructor(
         complicationSlotCollection: Collection<ComplicationSlot>,
@@ -234,11 +239,13 @@
                 if (complication.defaultDataSourcePolicyDirty ||
                     complication.defaultDataSourceTypeDirty
                 ) {
+                    // Note this is a NOP in the androidx flow.
                     watchFaceHostApi.setDefaultComplicationDataSourceWithFallbacks(
                         complication.id,
                         complication.defaultDataSourcePolicy.dataSourcesAsList(),
                         complication.defaultDataSourcePolicy.systemDataSourceFallback,
-                        complication.defaultDataSourceType.toWireComplicationType()
+                        complication.defaultDataSourcePolicy
+                            .systemDataSourceFallbackDefaultType.toWireComplicationType()
                     )
                 }
 
@@ -405,7 +412,8 @@
                 it.key,
                 it.value.defaultDataSourcePolicy.dataSourcesAsList(),
                 it.value.defaultDataSourcePolicy.systemDataSourceFallback,
-                it.value.defaultDataSourceType.toWireComplicationType()
+                it.value.defaultDataSourcePolicy
+                    .systemDataSourceFallbackDefaultType.toWireComplicationType()
             )
         }.toTypedArray()
 }
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index d8e9b4e..0154045 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -254,6 +254,21 @@
 
         /** Signals that the activity is going away and resources should be released. */
         public fun onDestroy()
+
+        /** Sets a callback to observe an y changes to [ComplicationSlot.configExtras]. */
+        public fun setComplicationSlotConfigExtrasChangeCallback(
+            callback: ComplicationSlotConfigExtrasChangeCallback?
+        )
+    }
+
+    /**
+     * Used to inform EditorSession about changes to [ComplicationSlot.configExtras].
+     *
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public interface ComplicationSlotConfigExtrasChangeCallback {
+      public fun onComplicationSlotConfigExtrasChanged()
     }
 
     /**
@@ -656,6 +671,7 @@
 
         if (!watchState.isHeadless) {
             WatchFace.registerEditorDelegate(componentName, WFEditorDelegate())
+            registerReceivers()
         }
 
         val mainScope = CoroutineScope(Dispatchers.Main.immediate)
@@ -758,6 +774,12 @@
             return screenShot
         }
 
+        override fun setComplicationSlotConfigExtrasChangeCallback(
+            callback: WatchFace.ComplicationSlotConfigExtrasChangeCallback?
+        ) {
+            complicationSlotsManager.configExtrasChangeCallback = callback
+        }
+
         override fun onDestroy(): Unit = TraceEvent("WFEditorDelegate.onDestroy").use {
             if (watchState.isHeadless) {
                 this@WatchFaceImpl.onDestroy()
@@ -785,10 +807,10 @@
 
     @UiThread
     private fun registerReceivers() {
+        // Looper can be null in some tests.
         require(watchFaceHostApi.getUiThreadHandler().looper.isCurrentThread) {
             "registerReceivers must be called the UiThread"
         }
-
         // There's no point registering BroadcastsReceiver for headless instances.
         if (broadcastsReceiver == null && !watchState.isHeadless) {
             broadcastsReceiver =
@@ -798,6 +820,7 @@
 
     @UiThread
     private fun unregisterReceivers() {
+        // Looper can be null in some tests.
         require(watchFaceHostApi.getUiThreadHandler().looper.isCurrentThread) {
             "unregisterReceivers must be called the UiThread"
         }
@@ -979,6 +1002,9 @@
 
     @UiThread
     internal fun getComplicationState() = complicationSlotsManager.complicationSlots.map {
+        val systemDataSourceFallbackDefaultType =
+            it.value.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType
+                .toWireComplicationType()
         IdAndComplicationStateWireFormat(
             it.key,
             ComplicationStateWireFormat(
@@ -987,7 +1013,11 @@
                 ComplicationType.toWireTypes(it.value.supportedTypes),
                 it.value.defaultDataSourcePolicy.dataSourcesAsList(),
                 it.value.defaultDataSourcePolicy.systemDataSourceFallback,
-                it.value.defaultDataSourceType.toWireComplicationType(),
+                systemDataSourceFallbackDefaultType,
+                it.value.defaultDataSourcePolicy.primaryDataSourceDefaultType
+                    ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
+                it.value.defaultDataSourcePolicy.secondaryDataSourceDefaultType
+                    ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
                 it.value.enabled,
                 it.value.initiallyEnabled,
                 it.value.renderer.getData().type.toWireComplicationType(),
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceHostApi.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceHostApi.kt
index 9802a0d..098c657 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceHostApi.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceHostApi.kt
@@ -78,6 +78,8 @@
     public fun setActiveComplicationSlots(complicationSlotIds: IntArray)
 
     /**
+     * For WSL flow, not used in androidx flow.
+     *
      * Accepts a list of custom complication data sources to attempt to set as the default
      * complication data source for the specified watch face [ComplicationSlot] id. The custom
      * complication data sources are tried in turn, if the first doesn't exist then the next one
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 28102a7..d94318a 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -1407,6 +1407,9 @@
             createComplicationSlotsManager(
                 CurrentUserStyleRepository(createUserStyleSchema())
             ).complicationSlots.map {
+                val systemDataSourceFallbackDefaultType =
+                    it.value.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType
+                        .toWireComplicationType()
                 ComplicationSlotMetadataWireFormat(
                     it.key,
                     it.value.complicationSlotBounds.perComplicationTypeBounds.keys.map {
@@ -1418,7 +1421,11 @@
                     it.value.supportedTypes.toWireTypes(),
                     it.value.defaultDataSourcePolicy.dataSourcesAsList(),
                     it.value.defaultDataSourcePolicy.systemDataSourceFallback,
-                    it.value.defaultDataSourceType.toWireComplicationType(),
+                    systemDataSourceFallbackDefaultType,
+                    it.value.defaultDataSourcePolicy.primaryDataSourceDefaultType
+                        ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
+                    it.value.defaultDataSourcePolicy.secondaryDataSourceDefaultType
+                        ?.toWireComplicationType() ?: systemDataSourceFallbackDefaultType,
                     it.value.initiallyEnabled,
                     it.value.fixedComplicationDataSource,
                     it.value.configExtras
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
index 3dc4dc6..f80df82 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/XmlSchemaAndComplicationSlotsDefinition.kt
@@ -91,7 +91,6 @@
         val bounds: ComplicationSlotBounds,
         val supportedTypes: List<ComplicationType>,
         val defaultDataSourcePolicy: DefaultComplicationDataSourcePolicy,
-        val defaultDataSourceType: ComplicationType,
         val initiallyEnabled: Boolean,
         val fixedComplicationDataSource: Boolean
     ) {
@@ -164,10 +163,40 @@
                     attributes.getString(R.styleable.ComplicationSlot_primaryDataSource)?.let {
                         ComponentName.unflattenFromString(it)
                     }
+                val primaryDataSourceDefaultType =
+                    if (attributes.hasValue(
+                            R.styleable.ComplicationSlot_primaryDataSourceDefaultType
+                        )
+                    ) {
+                        ComplicationType.fromWireType(
+                            attributes.getInt(
+                                R.styleable.ComplicationSlot_primaryDataSourceDefaultType,
+                                0
+                            )
+                        )
+                    } else {
+                        null
+                    }
                 val secondaryDataSource =
                     attributes.getString(R.styleable.ComplicationSlot_secondaryDataSource)?.let {
                         ComponentName.unflattenFromString(it)
                     }
+
+                val secondaryDataSourceDefaultType =
+                    if (attributes.hasValue(
+                            R.styleable.ComplicationSlot_secondaryDataSourceDefaultType
+                        )
+                    ) {
+                        ComplicationType.fromWireType(
+                            attributes.getInt(
+                                R.styleable.ComplicationSlot_secondaryDataSourceDefaultType,
+                                0
+                            )
+                        )
+                    } else {
+                        null
+                    }
+
                 require(
                     attributes.hasValue(R.styleable.ComplicationSlot_systemDataSourceFallback)
                 ) {
@@ -177,37 +206,64 @@
                     R.styleable.ComplicationSlot_systemDataSourceFallback,
                     0
                 )
+                require(
+                    attributes.hasValue(
+                        R.styleable.ComplicationSlot_systemDataSourceFallbackDefaultType
+                    )
+                ) {
+                    "A ComplicationSlot must have a systemDataSourceFallbackDefaultType" +
+                        " attribute"
+                }
+                val systemDataSourceFallbackDefaultType = ComplicationType.fromWireType(
+                    attributes.getInt(
+                        R.styleable.ComplicationSlot_systemDataSourceFallbackDefaultType,
+                        0
+                    )
+                )
                 val defaultComplicationDataSourcePolicy = when {
                     secondaryDataSource != null -> {
                         require(primaryDataSource != null) {
                             "If a secondaryDataSource is specified, a primaryDataSource must be too"
                         }
+                        require(primaryDataSourceDefaultType != null) {
+                            "If a primaryDataSource is specified, a " +
+                                "primaryDataSourceDefaultType must be too"
+                        }
+                        require(secondaryDataSourceDefaultType != null) {
+                            "If a secondaryDataSource is specified, a " +
+                                "secondaryDataSourceDefaultType must be too"
+                        }
                         DefaultComplicationDataSourcePolicy(
                             primaryDataSource,
+                            primaryDataSourceDefaultType,
                             secondaryDataSource,
-                            systemDataSourceFallback
+                            secondaryDataSourceDefaultType,
+                            systemDataSourceFallback,
+                            systemDataSourceFallbackDefaultType
                         )
                     }
 
-                    primaryDataSource != null -> DefaultComplicationDataSourcePolicy(
-                        primaryDataSource,
-                        systemDataSourceFallback
-                    )
+                    primaryDataSource != null -> {
+                        require(primaryDataSourceDefaultType != null) {
+                            "If a primaryDataSource is specified, a " +
+                                "primaryDataSourceDefaultType must be too"
+                        }
+                        DefaultComplicationDataSourcePolicy(
+                            primaryDataSource,
+                            primaryDataSourceDefaultType,
+                            systemDataSourceFallback,
+                            systemDataSourceFallbackDefaultType
+                        )
+                    }
 
-                    else -> DefaultComplicationDataSourcePolicy(systemDataSourceFallback)
+                    else -> {
+                        DefaultComplicationDataSourcePolicy(
+                            systemDataSourceFallback,
+                            systemDataSourceFallbackDefaultType
+                        )
+                    }
                 }
 
-                require(
-                    attributes.hasValue(R.styleable.ComplicationSlot_defaultDataSourceType)
-                ) {
-                    "A ComplicationSlot must have a defaultDataSourceType attribute"
-                }
-                val defaultDataSourceType = ComplicationType.fromWireType(
-                    attributes.getInt(
-                        R.styleable.ComplicationSlot_defaultDataSourceType,
-                        0
-                    )
-                )
                 val initiallyEnabled = attributes.getBoolean(
                     R.styleable.ComplicationSlot_initiallyEnabled,
                     true
@@ -231,7 +287,6 @@
                     bounds,
                     supportedTypesList,
                     defaultComplicationDataSourcePolicy,
-                    defaultDataSourceType,
                     initiallyEnabled,
                     fixedComplicationDataSource
                 )
@@ -262,7 +317,7 @@
                     complicationSlotInflationFactory.getCanvasComplicationFactory(it.slotId),
                     it.supportedTypes,
                     it.defaultDataSourcePolicy,
-                    it.defaultDataSourceType,
+                    it.defaultDataSourcePolicy.systemDataSourceFallbackDefaultType,
                     it.initiallyEnabled,
                     Bundle(),
                     it.fixedComplicationDataSource,
@@ -280,4 +335,4 @@
             currentUserStyleRepository
         )
     }
-}
\ No newline at end of file
+}
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
index 362edee..8a207d8 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/control/InteractiveWatchFaceImpl.kt
@@ -170,6 +170,8 @@
     }
 
     fun onDestroy() {
-        engine = null
+        uiThreadCoroutineScope.launch {
+            engine = null
+        }
     }
 }
diff --git a/wear/watchface/watchface/src/main/res/values/attrs.xml b/wear/watchface/watchface/src/main/res/values/attrs.xml
index 08ce152..9254aae 100644
--- a/wear/watchface/watchface/src/main/res/values/attrs.xml
+++ b/wear/watchface/watchface/src/main/res/values/attrs.xml
@@ -49,9 +49,33 @@
         <!-- Optional. First of two non-system data source ComponentNames to be tried in turn. -->
         <attr name="primaryDataSource" format="string" />
 
+        <!-- Optional unless primaryDataSource is specified. The default [ComplicationType] for the
+        primaryDataSource. This is a subset of
+        androidx.wear.watchface.complications.data.ComplicationType. -->
+        <attr name="primaryDataSourceDefaultType" format="enum">
+            <enum name="SHORT_TEXT" value="3" />
+            <enum name="LONG_TEXT" value="4" />
+            <enum name="RANGED_VALUE" value="5" />
+            <enum name="MONOCHROMATIC_IMAGE" value="6" />
+            <enum name="SMALL_IMAGE" value="7" />
+            <enum name="PHOTO_IMAGE" value="8" />
+        </attr>
+
         <!-- Optional. Second of two non-system data source ComponentNames to be tried in turn. -->
         <attr name="secondaryDataSource" format="string" />
 
+        <!-- Optional unless secondaryDataSource is specified. The default [ComplicationType] for
+        the secondaryDataSource.  This is a subset of
+        androidx.wear.watchface.complications.data.ComplicationType. -->
+        <attr name="secondaryDataSourceDefaultType" format="enum">
+            <enum name="SHORT_TEXT" value="3" />
+            <enum name="LONG_TEXT" value="4" />
+            <enum name="RANGED_VALUE" value="5" />
+            <enum name="MONOCHROMATIC_IMAGE" value="6" />
+            <enum name="SMALL_IMAGE" value="7" />
+            <enum name="PHOTO_IMAGE" value="8" />
+        </attr>
+
         <!-- Required. Fallback in case none of the non-system data sources could be used.
         These definitions match androidx.wear.watchface.complications.SystemDataSources. -->
         <attr name="systemDataSourceFallback" format="enum">
@@ -72,7 +96,7 @@
 
         <!-- Required. The default [ComplicationType] for the default complication data source.
         This is a subset of androidx.wear.watchface.complications.data.ComplicationType. -->
-        <attr name="defaultDataSourceType" format="enum">
+        <attr name="systemDataSourceFallbackDefaultType" format="enum">
             <enum name="SHORT_TEXT" value="3" />
             <enum name="LONG_TEXT" value="4" />
             <enum name="RANGED_VALUE" value="5" />
diff --git a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index edbe885..e7fa707 100644
--- a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -211,6 +211,7 @@
     private val badStyleOption =
         ListUserStyleSetting.ListOption(Option.Id("bad_option"), "Bad", icon = null)
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     private val leftComplication =
         ComplicationSlot.createRoundRectComplicationSlotBuilder(
             LEFT_COMPLICATION_ID,
@@ -233,6 +234,7 @@
         ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
             .build()
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     private val rightComplication =
         ComplicationSlot.createRoundRectComplicationSlotBuilder(
             RIGHT_COMPLICATION_ID,
@@ -256,6 +258,7 @@
             .build()
 
     private val edgeComplicationHitTester = mock<ComplicationTapFilter>()
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     private val edgeComplication =
         ComplicationSlot.createEdgeComplicationSlotBuilder(
             EDGE_COMPLICATION_ID,
@@ -279,6 +282,7 @@
         ).setDefaultDataSourceType(ComplicationType.SHORT_TEXT)
             .build()
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     private val backgroundComplication =
         ComplicationSlot.createBackgroundComplicationSlotBuilder(
             BACKGROUND_COMPLICATION_ID,
@@ -437,6 +441,7 @@
         engineWrapper.onVisibilityChanged(true)
     }
 
+    @Suppress("DEPRECATION") // defaultDataSourceType
     private fun initEngineBeforeGetWatchFaceImpl(
         watchFaceType: Int,
         complicationSlots: List<ComplicationSlot>,
@@ -1755,6 +1760,7 @@
         assertThat(argument.value.acceptsTapEvents).isEqualTo(true)
     }
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     @Test
     public fun defaultComplicationDataSourcesWithFallbacks_newApi() {
         val dataSource1 = ComponentName("com.app1", "com.app1.App1")
@@ -1785,6 +1791,7 @@
         )
     }
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     @Test
     public fun defaultComplicationDataSourcesWithFallbacks_oldApi() {
         val dataSource1 = ComponentName("com.app1", "com.app1.App1")
@@ -2142,6 +2149,7 @@
         assertFalse(rightComplication.enabled)
     }
 
+    @Suppress("DEPRECATION") // setDefaultDataSourceType
     public fun UserStyleManager_init_applies_ComplicationsUserStyleSetting() {
         val complicationSlotId1 = 101
         val complicationSlotId2 = 102
@@ -3021,6 +3029,7 @@
         )
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Test
     public fun canvasComplication_onRendererCreated() {
         val leftCanvasComplication = mock<CanvasComplication>()
@@ -3059,6 +3068,7 @@
         verify(rightCanvasComplication).onRendererCreated(renderer)
     }
 
+    @Suppress("DEPRECATION") // DefaultComplicationDataSourcePolicyAndType
     @Test
     public fun complicationSlotsWithTheSameRenderer() {
         val sameCanvasComplication = mock<CanvasComplication>()
diff --git a/wear/wear/build.gradle b/wear/wear/build.gradle
index 36abd85..c198025 100644
--- a/wear/wear/build.gradle
+++ b/wear/wear/build.gradle
@@ -52,6 +52,10 @@
         androidTest.assets.srcDirs += project.rootDir.absolutePath + "/../../golden/wear/wear"
     }
 
+    buildTypes.all {
+        consumerProguardFiles "proguard-rules.pro"
+    }
+
     // Use Robolectric 4.+
     testOptions.unitTests.includeAndroidResources = true
 }
diff --git a/wear/wear/proguard-rules.pro b/wear/wear/proguard-rules.pro
new file mode 100644
index 0000000..1fb72ae
--- /dev/null
+++ b/wear/wear/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Copyright (C) 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.
+
+# Keep the classes and their public methods used to implement ambient as these
+# are called by the framework.
+-keep,allowoptimization class androidx.wear.ambient.* { public *; }
diff --git a/window/window/src/androidTest/java/androidx/window/layout/SidecarWindowBackendIntegrationTest.kt b/window/window/src/androidTest/java/androidx/window/layout/SidecarWindowBackendIntegrationTest.kt
index 760916f..2834b25 100644
--- a/window/window/src/androidTest/java/androidx/window/layout/SidecarWindowBackendIntegrationTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/layout/SidecarWindowBackendIntegrationTest.kt
@@ -194,9 +194,10 @@
     @Test
     public fun testVersionSupport() {
         // Only versions 1.0 and 0.1 are supported for now
-        var version = SidecarCompat.sidecarVersion
+        val version = SidecarCompat.sidecarVersion
         if (version != null) {
-            assertEquals(Version.VERSION_0_1, version)
+            val validVersion = Version.VERSION_0_1 == version || Version.VERSION_1_0 == version
+            assertTrue("Version must be either 1.0 or 0.1", validVersion)
         }
     }