Merge "Remove apex/media - migrated to packages/modules/Media"
diff --git a/Android.bp b/Android.bp
index 05175d9..f805947 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,7 +110,7 @@
 
         // AIDL sources from external directories
         ":android.hardware.graphics.common-V3-java-source",
-        ":android.hardware.security.keymint-V1-java-source",
+        ":android.hardware.security.keymint-V2-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
         ":android.hardware.tv.tuner-V1-java-source",
         ":android.security.apc-java-source",
diff --git a/core/api/current.txt b/core/api/current.txt
index 282a4c3..594e469 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1453,6 +1453,7 @@
     field public static final int supportsAssist = 16844016; // 0x10104f0
     field public static final int supportsBatteryGameMode;
     field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
+    field public static final int supportsInlineSuggestionsWithTouchExploration;
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
     field public static final int supportsMultipleDisplays = 16844182; // 0x1010596
@@ -4549,6 +4550,7 @@
     method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
     method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int);
+    method @NonNull public static android.app.ActivityOptions makeLaunchIntoPip(@NonNull android.app.PictureInPictureParams);
     method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
     method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, String);
     method @java.lang.SafeVarargs public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View,java.lang.String>...);
@@ -6634,10 +6636,12 @@
 
   public static class PictureInPictureParams.Builder {
     ctor public PictureInPictureParams.Builder();
+    ctor public PictureInPictureParams.Builder(@NonNull android.app.PictureInPictureParams);
     method public android.app.PictureInPictureParams build();
     method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>);
     method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational);
     method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterEnabled(boolean);
+    method @NonNull public android.app.PictureInPictureParams.Builder setCloseAction(@Nullable android.app.RemoteAction);
     method @NonNull public android.app.PictureInPictureParams.Builder setExpandedAspectRatio(@Nullable android.util.Rational);
     method @NonNull public android.app.PictureInPictureParams.Builder setSeamlessResizeEnabled(boolean);
     method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 273f59c..5d76b08 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2507,9 +2507,10 @@
 package android.app.usage {
 
   public final class BroadcastResponseStats implements android.os.Parcelable {
-    ctor public BroadcastResponseStats(@NonNull String);
+    ctor public BroadcastResponseStats(@NonNull String, @IntRange(from=1) long);
     method public int describeContents();
     method @IntRange(from=0) public int getBroadcastsDispatchedCount();
+    method @IntRange(from=1) public long getId();
     method @IntRange(from=0) public int getNotificationsCancelledCount();
     method @IntRange(from=0) public int getNotificationsPostedCount();
     method @IntRange(from=0) public int getNotificationsUpdatedCount();
@@ -2566,13 +2567,13 @@
   }
 
   public final class UsageStatsManager {
-    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void clearBroadcastResponseStats(@NonNull String, @IntRange(from=1) long);
+    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void clearBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
     method @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long getLastTimeAnyComponentUsed(@NonNull String);
     method public int getUsageSource();
     method @RequiresPermission(android.Manifest.permission.BIND_CARRIER_SERVICES) public void onCarrierPrivilegedAppsChanged();
-    method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public android.app.usage.BroadcastResponseStats queryBroadcastResponseStats(@NonNull String, @IntRange(from=1) long);
+    method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.List<android.app.usage.BroadcastResponseStats> queryBroadcastResponseStats(@Nullable String, @IntRange(from=0) long);
     method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
@@ -6075,7 +6076,7 @@
     method public boolean isAudioServerRunning();
     method public boolean isHdmiSystemAudioSupported();
     method @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public boolean isPstnCallAudioInterceptable();
-    method public static boolean isUltrasoundSupported();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_ULTRASOUND) public boolean isUltrasoundSupported();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void muteAwaitConnection(@NonNull int[], @NonNull android.media.AudioDeviceAttributes, long, @NonNull java.util.concurrent.TimeUnit) throws java.lang.IllegalStateException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void registerMuteAwaitConnectionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.MuteAwaitConnectionCallback);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9455f8f8..e5165449 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -357,6 +357,7 @@
   public final class PictureInPictureParams implements android.os.Parcelable {
     method public java.util.List<android.app.RemoteAction> getActions();
     method public float getAspectRatio();
+    method @Nullable public android.app.RemoteAction getCloseAction();
     method public float getExpandedAspectRatio();
     method public android.graphics.Rect getSourceRectHint();
     method @Nullable public CharSequence getSubtitle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 5012121..5ddaa80 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -350,6 +350,10 @@
     /** See {@link #setTransientLaunch()}. */
     private static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch";
 
+    /** see {@link #makeLaunchIntoPip(PictureInPictureParams)}. */
+    private static final String KEY_LAUNCH_INTO_PIP_PARAMS =
+            "android.activity.launchIntoPipParams";
+
     /**
      * @see #setLaunchCookie
      * @hide
@@ -444,6 +448,7 @@
     private boolean mRemoveWithTaskOrganizer;
     private boolean mLaunchedFromBubble;
     private boolean mTransientLaunch;
+    private PictureInPictureParams mLaunchIntoPipParams;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -1106,6 +1111,24 @@
         return opts;
     }
 
+    /**
+     * Creates an {@link ActivityOptions} instance that launch into picture-in-picture.
+     * This is normally used by a Host activity to start another activity that will directly enter
+     * picture-in-picture upon its creation.
+     * @param pictureInPictureParams {@link PictureInPictureParams} for launching the Activity to
+     *                               picture-in-picture mode.
+     */
+    @NonNull
+    public static ActivityOptions makeLaunchIntoPip(
+            @NonNull PictureInPictureParams pictureInPictureParams) {
+        final ActivityOptions opts = new ActivityOptions();
+        opts.mLaunchIntoPipParams = new PictureInPictureParams.Builder(pictureInPictureParams)
+                .setIsLaunchIntoPip(true)
+                .build();
+        opts.mLaunchBounds = new Rect(pictureInPictureParams.getSourceRectHint());
+        return opts;
+    }
+
     /** @hide */
     public boolean getLaunchTaskBehind() {
         return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -1219,6 +1242,7 @@
         mLaunchedFromBubble = opts.getBoolean(KEY_LAUNCHED_FROM_BUBBLE);
         mTransientLaunch = opts.getBoolean(KEY_TRANSIENT_LAUNCH);
         mSplashScreenStyle = opts.getInt(KEY_SPLASH_SCREEN_STYLE);
+        mLaunchIntoPipParams = opts.getParcelable(KEY_LAUNCH_INTO_PIP_PARAMS);
     }
 
     /**
@@ -1556,6 +1580,23 @@
         mLaunchWindowingMode = windowingMode;
     }
 
+    /**
+     * @return {@link PictureInPictureParams} used to launch into PiP mode.
+     * @hide
+     */
+    public PictureInPictureParams getLaunchIntoPipParams() {
+        return mLaunchIntoPipParams;
+    }
+
+    /**
+     * @return {@code true} if this instance is used to launch into PiP mode.
+     * @hide
+     */
+    public boolean isLaunchIntoPip() {
+        return mLaunchIntoPipParams != null
+                && mLaunchIntoPipParams.isLaunchIntoPip();
+    }
+
     /** @hide */
     public int getLaunchActivityType() {
         return mLaunchActivityType;
@@ -1867,6 +1908,7 @@
         mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
         mSpecsFuture = otherOptions.mSpecsFuture;
         mRemoteAnimationAdapter = otherOptions.mRemoteAnimationAdapter;
+        mLaunchIntoPipParams = otherOptions.mLaunchIntoPipParams;
     }
 
     /**
@@ -2039,6 +2081,9 @@
         if (mSplashScreenStyle != 0) {
             b.putInt(KEY_SPLASH_SCREEN_STYLE, mSplashScreenStyle);
         }
+        if (mLaunchIntoPipParams != null) {
+            b.putParcelable(KEY_LAUNCH_INTO_PIP_PARAMS, mLaunchIntoPipParams);
+        }
         return b;
     }
 
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 0a74bba..2d2788c 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -51,6 +51,9 @@
         private List<RemoteAction> mUserActions;
 
         @Nullable
+        private RemoteAction mCloseAction;
+
+        @Nullable
         private Rect mSourceRectHint;
 
         private Boolean mAutoEnterEnabled;
@@ -61,6 +64,27 @@
 
         private CharSequence mSubtitle;
 
+        private Boolean mIsLaunchIntoPip;
+
+        /** Default constructor */
+        public Builder() {}
+
+        /**
+         * Copy constructor
+         * @param original {@link PictureInPictureParams} instance this builder is built upon.
+         */
+        public Builder(@NonNull PictureInPictureParams original) {
+            mAspectRatio = original.mAspectRatio;
+            mUserActions = original.mUserActions;
+            mCloseAction = original.mCloseAction;
+            mSourceRectHint = original.mSourceRectHint;
+            mAutoEnterEnabled = original.mAutoEnterEnabled;
+            mSeamlessResizeEnabled = original.mSeamlessResizeEnabled;
+            mTitle = original.mTitle;
+            mSubtitle = original.mSubtitle;
+            mIsLaunchIntoPip = original.mIsLaunchIntoPip;
+        }
+
         /**
          * Sets the aspect ratio.  This aspect ratio is defined as the desired width / height, and
          * does not change upon device rotation.
@@ -114,6 +138,25 @@
         }
 
         /**
+         * Sets a close action that should be invoked before the default close PiP action. The
+         * custom action must close the activity quickly using {@link Activity#finish()}.
+         * Otherwise, the system will forcibly close the PiP as if no custom close action was
+         * provided.
+         *
+         * If the action matches one set via {@link PictureInPictureParams.Builder#setActions(List)}
+         * it may be shown in place of that custom action in the menu.
+         *
+         * @param action to replace the system close action
+         * @return this builder instance.
+         * @see RemoteAction
+         */
+        @NonNull
+        public Builder setCloseAction(@Nullable RemoteAction action) {
+            mCloseAction = action;
+            return this;
+        }
+
+        /**
          * Sets the source bounds hint. These bounds are only used when an activity first enters
          * picture-in-picture, and describe the bounds in window coordinates of activity entering
          * picture-in-picture that will be visible following the transition. For the best effect,
@@ -199,6 +242,20 @@
             return this;
         }
 
+        /**
+         * Sets whether the built {@link PictureInPictureParams} represents a launch into
+         * picture-in-picture request.
+         *
+         * This property is {@code false} by default.
+         * @param isLaunchIntoPip {@code true} if the built instance represents a launch into
+         *                                 picture-in-picture request
+         * @return this builder instance.
+         */
+        @NonNull
+        Builder setIsLaunchIntoPip(boolean isLaunchIntoPip) {
+            mIsLaunchIntoPip = isLaunchIntoPip;
+            return this;
+        }
 
         /**
          * @return an immutable {@link PictureInPictureParams} to be used when entering or updating
@@ -209,8 +266,9 @@
          */
         public PictureInPictureParams build() {
             PictureInPictureParams params = new PictureInPictureParams(mAspectRatio,
-                    mExpandedAspectRatio, mUserActions,
-                    mSourceRectHint, mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle);
+                    mExpandedAspectRatio, mUserActions, mCloseAction, mSourceRectHint,
+                    mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle,
+                    mIsLaunchIntoPip);
             return params;
         }
     }
@@ -234,6 +292,12 @@
     private List<RemoteAction> mUserActions;
 
     /**
+     * Action to replace the system close action.
+     */
+    @Nullable
+    private RemoteAction mCloseAction;
+
+    /**
      * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
      * We can use this internally for the transition into picture-in-picture to ensure that a
      * particular source rect is visible throughout the whole transition.
@@ -266,6 +330,13 @@
     @Nullable
     private CharSequence mSubtitle;
 
+    /**
+     * Whether this {@link PictureInPictureParams} represents a launch into
+     * picture-in-picture request.
+     * {@link #isLaunchIntoPip()} defaults to {@code false} is this is not set.
+     */
+    private Boolean mIsLaunchIntoPip;
+
     /** {@hide} */
     PictureInPictureParams() {
     }
@@ -278,6 +349,7 @@
             mUserActions = new ArrayList<>();
             in.readTypedList(mUserActions, RemoteAction.CREATOR);
         }
+        mCloseAction = in.readTypedObject(RemoteAction.CREATOR);
         if (in.readInt() != 0) {
             mSourceRectHint = Rect.CREATOR.createFromParcel(in);
         }
@@ -293,20 +365,26 @@
         if (in.readInt() != 0) {
             mSubtitle = in.readCharSequence();
         }
+        if (in.readInt() != 0) {
+            mIsLaunchIntoPip = in.readBoolean();
+        }
     }
 
     /** {@hide} */
     PictureInPictureParams(Rational aspectRatio, Rational expandedAspectRatio,
-            List<RemoteAction> actions, Rect sourceRectHint, Boolean autoEnterEnabled,
-            Boolean seamlessResizeEnabled, CharSequence title, CharSequence subtitle) {
+            List<RemoteAction> actions, RemoteAction closeAction, Rect sourceRectHint,
+            Boolean autoEnterEnabled, Boolean seamlessResizeEnabled, CharSequence title,
+            CharSequence subtitle, Boolean isLaunchIntoPip) {
         mAspectRatio = aspectRatio;
         mExpandedAspectRatio = expandedAspectRatio;
         mUserActions = actions;
+        mCloseAction = closeAction;
         mSourceRectHint = sourceRectHint;
         mAutoEnterEnabled = autoEnterEnabled;
         mSeamlessResizeEnabled = seamlessResizeEnabled;
         mTitle = title;
         mSubtitle = subtitle;
+        mIsLaunchIntoPip = isLaunchIntoPip;
     }
 
     /**
@@ -314,10 +392,10 @@
      * @hide
      */
     public PictureInPictureParams(PictureInPictureParams other) {
-        this(other.mAspectRatio, other.mExpandedAspectRatio, other.mUserActions,
+        this(other.mAspectRatio, other.mExpandedAspectRatio, other.mUserActions, other.mCloseAction,
                 other.hasSourceBoundsHint() ? new Rect(other.getSourceRectHint()) : null,
-                other.mAutoEnterEnabled, other.mSeamlessResizeEnabled, other.mTitle,
-                other.mSubtitle);
+                other.mAutoEnterEnabled, other.mSeamlessResizeEnabled,
+                other.mTitle, other.mSubtitle, other.mIsLaunchIntoPip);
     }
 
     /**
@@ -335,6 +413,9 @@
         if (otherArgs.hasSetActions()) {
             mUserActions = otherArgs.mUserActions;
         }
+        if (otherArgs.hasSetCloseAction()) {
+            mCloseAction = otherArgs.mCloseAction;
+        }
         if (otherArgs.hasSourceBoundsHint()) {
             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
         }
@@ -350,6 +431,9 @@
         if (otherArgs.hasSetSubtitle()) {
             mSubtitle = otherArgs.mSubtitle;
         }
+        if (otherArgs.mIsLaunchIntoPip != null) {
+            mIsLaunchIntoPip = otherArgs.mIsLaunchIntoPip;
+        }
     }
 
     /**
@@ -415,7 +499,26 @@
     }
 
     /**
+     * @return the close action.
+     * @hide
+     */
+    @TestApi
+    @Nullable
+    public RemoteAction getCloseAction() {
+        return mCloseAction;
+    }
+
+    /**
+     * @return whether the close action was set.
+     * @hide
+     */
+    public boolean hasSetCloseAction() {
+        return mCloseAction != null;
+    }
+
+    /**
      * Truncates the set of actions to the given {@param size}.
+     *
      * @hide
      */
     public void truncateActions(int size) {
@@ -495,14 +598,22 @@
     }
 
     /**
+     * @return whether this {@link PictureInPictureParams} represents a launch into pip request.
+     * @hide
+     */
+    public boolean isLaunchIntoPip() {
+        return mIsLaunchIntoPip == null ? false : mIsLaunchIntoPip;
+    }
+
+    /**
      * @return True if no parameters are set
      * @hide
      */
     public boolean empty() {
-        return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio()
-                && !hasSetExpandedAspectRatio() && mAutoEnterEnabled != null
-                && mSeamlessResizeEnabled != null && !hasSetTitle()
-                && !hasSetSubtitle();
+        return !hasSourceBoundsHint() && !hasSetActions() && !hasSetCloseAction()
+                && !hasSetAspectRatio() && !hasSetExpandedAspectRatio() && mAutoEnterEnabled == null
+                && mSeamlessResizeEnabled == null && !hasSetTitle()
+                && !hasSetSubtitle() && mIsLaunchIntoPip == null;
     }
 
     @Override
@@ -515,15 +626,18 @@
                 && Objects.equals(mAspectRatio, that.mAspectRatio)
                 && Objects.equals(mExpandedAspectRatio, that.mExpandedAspectRatio)
                 && Objects.equals(mUserActions, that.mUserActions)
+                && Objects.equals(mCloseAction, that.mCloseAction)
                 && Objects.equals(mSourceRectHint, that.mSourceRectHint)
                 && Objects.equals(mTitle, that.mTitle)
-                && Objects.equals(mSubtitle, that.mSubtitle);
+                && Objects.equals(mSubtitle, that.mSubtitle)
+                && Objects.equals(mIsLaunchIntoPip, that.mIsLaunchIntoPip);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mAspectRatio, mExpandedAspectRatio, mUserActions, mSourceRectHint,
-                mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle);
+        return Objects.hash(mAspectRatio, mExpandedAspectRatio, mUserActions, mCloseAction,
+                mSourceRectHint, mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle,
+                mIsLaunchIntoPip);
     }
 
     @Override
@@ -541,6 +655,9 @@
         } else {
             out.writeInt(0);
         }
+
+        out.writeTypedObject(mCloseAction, 0);
+
         if (mSourceRectHint != null) {
             out.writeInt(1);
             mSourceRectHint.writeToParcel(out, 0);
@@ -571,6 +688,12 @@
         } else {
             out.writeInt(0);
         }
+        if (mIsLaunchIntoPip != null) {
+            out.writeInt(1);
+            out.writeBoolean(mIsLaunchIntoPip);
+        } else {
+            out.writeInt(0);
+        }
     }
 
     private void writeRationalToParcel(Rational rational, Parcel out) {
@@ -597,10 +720,12 @@
                 + " expandedAspectRatio=" + mExpandedAspectRatio
                 + " sourceRectHint=" + getSourceRectHint()
                 + " hasSetActions=" + hasSetActions()
+                + " hasSetCloseAction=" + hasSetCloseAction()
                 + " isAutoPipEnabled=" + isAutoEnterEnabled()
                 + " isSeamlessResizeEnabled=" + isSeamlessResizeEnabled()
                 + " title=" + getTitle()
                 + " subtitle=" + getSubtitle()
+                + " isLaunchIntoPip=" + isLaunchIntoPip()
                 + ")";
     }
 
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index eca4170..5c7c73c 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -191,6 +191,13 @@
     public boolean preferDockBigOverlays;
 
     /**
+     * The task id of the host Task of the launch-into-pip Activity, i.e., it points to the Task
+     * the launch-into-pip Activity is originated from.
+     * @hide
+     */
+    public int launchIntoPipHostTaskId;
+
+    /**
      * The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of
      * (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS),
      * {@code null} otherwise.
@@ -516,6 +523,7 @@
         topActivityType = source.readInt();
         pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR);
         preferDockBigOverlays = source.readBoolean();
+        launchIntoPipHostTaskId = source.readInt();
         displayCutoutInsets = source.readTypedObject(Rect.CREATOR);
         topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
         isResizeable = source.readBoolean();
@@ -562,6 +570,7 @@
         dest.writeInt(topActivityType);
         dest.writeTypedObject(pictureInPictureParams, flags);
         dest.writeBoolean(preferDockBigOverlays);
+        dest.writeInt(launchIntoPipHostTaskId);
         dest.writeTypedObject(displayCutoutInsets, flags);
         dest.writeTypedObject(topActivityInfo, flags);
         dest.writeBoolean(isResizeable);
@@ -602,6 +611,7 @@
                 + " topActivityType=" + topActivityType
                 + " pictureInPictureParams=" + pictureInPictureParams
                 + " preferDockBigOverlays=" + preferDockBigOverlays
+                + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId
                 + " displayCutoutSafeInsets=" + displayCutoutInsets
                 + " topActivityInfo=" + topActivityInfo
                 + " launchCookies=" + launchCookies
diff --git a/core/java/android/app/usage/BroadcastResponseStats.java b/core/java/android/app/usage/BroadcastResponseStats.java
index 5acc3dda..e1d37e1 100644
--- a/core/java/android/app/usage/BroadcastResponseStats.java
+++ b/core/java/android/app/usage/BroadcastResponseStats.java
@@ -23,6 +23,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * Class containing a collection of stats related to response events started from an app
  * after receiving a broadcast.
@@ -32,17 +34,30 @@
 @SystemApi
 public final class BroadcastResponseStats implements Parcelable {
     private final String mPackageName;
+    private final long mId;
     private int mBroadcastsDispatchedCount;
     private int mNotificationsPostedCount;
     private int mNotificationsUpdatedCount;
     private int mNotificationsCancelledCount;
 
-    public BroadcastResponseStats(@NonNull String packageName) {
+    /**
+     * Creates a new {@link BroadcastResponseStats} object that contain the stats for broadcasts
+     * with {@code id} (specified using
+     * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)} by the sender) that
+     * were sent to {@code packageName}.
+     *
+     * @param packageName the name of the package that broadcasts were sent to.
+     * @param id the ID specified by the sender using
+     *           {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
+     */
+    public BroadcastResponseStats(@NonNull String packageName, @IntRange(from = 1) long id) {
         mPackageName = packageName;
+        mId = id;
     }
 
     private BroadcastResponseStats(@NonNull Parcel in) {
         mPackageName = in.readString8();
+        mId = in.readLong();
         mBroadcastsDispatchedCount = in.readInt();
         mNotificationsPostedCount = in.readInt();
         mNotificationsUpdatedCount = in.readInt();
@@ -58,6 +73,14 @@
     }
 
     /**
+     * @return the ID of the broadcasts that the stats in this object correspond to.
+     */
+    @IntRange(from = 1)
+    public long getId() {
+        return mId;
+    }
+
+    /**
      * Returns the total number of broadcasts that were dispatched to the app by the caller.
      *
      * <b> Note that the returned count will only include the broadcasts that the caller explicitly
@@ -148,9 +171,35 @@
     }
 
     @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || !(obj instanceof BroadcastResponseStats)) {
+            return false;
+        }
+        final BroadcastResponseStats other = (BroadcastResponseStats) obj;
+        return this.mBroadcastsDispatchedCount == other.mBroadcastsDispatchedCount
+                && this.mNotificationsPostedCount == other.mNotificationsPostedCount
+                && this.mNotificationsUpdatedCount == other.mNotificationsUpdatedCount
+                && this.mNotificationsCancelledCount == other.mNotificationsCancelledCount
+                && this.mId == other.mId
+                && this.mPackageName.equals(other.mPackageName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPackageName, mId, mBroadcastsDispatchedCount,
+                mNotificationsPostedCount, mNotificationsUpdatedCount,
+                mNotificationsCancelledCount);
+    }
+
+    @Override
     public @NonNull String toString() {
         return "stats {"
-                + "broadcastsSent=" + mBroadcastsDispatchedCount
+                + "package=" + mPackageName
+                + ",id=" + mId
+                + ",broadcastsSent=" + mBroadcastsDispatchedCount
                 + ",notificationsPosted=" + mNotificationsPostedCount
                 + ",notificationsUpdated=" + mNotificationsUpdatedCount
                 + ",notificationsCancelled=" + mNotificationsCancelledCount
@@ -165,6 +214,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
         dest.writeString8(mPackageName);
+        dest.writeLong(mId);
         dest.writeInt(mBroadcastsDispatchedCount);
         dest.writeInt(mNotificationsPostedCount);
         dest.writeInt(mNotificationsUpdatedCount);
diff --git a/core/java/android/app/usage/BroadcastResponseStatsList.aidl b/core/java/android/app/usage/BroadcastResponseStatsList.aidl
new file mode 100644
index 0000000..7380359
--- /dev/null
+++ b/core/java/android/app/usage/BroadcastResponseStatsList.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 android.app.usage;
+
+/** {@hide} */
+parcelable BroadcastResponseStatsList;
\ No newline at end of file
diff --git a/core/java/android/app/usage/BroadcastResponseStatsList.java b/core/java/android/app/usage/BroadcastResponseStatsList.java
new file mode 100644
index 0000000..4d2ff286
--- /dev/null
+++ b/core/java/android/app/usage/BroadcastResponseStatsList.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 android.app.usage;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** @hide */
+public final class BroadcastResponseStatsList implements Parcelable {
+    private List<BroadcastResponseStats> mBroadcastResponseStats;
+
+    public BroadcastResponseStatsList(
+            @NonNull List<BroadcastResponseStats> broadcastResponseStats) {
+        mBroadcastResponseStats = broadcastResponseStats;
+    }
+
+    private BroadcastResponseStatsList(@NonNull Parcel in) {
+        mBroadcastResponseStats = new ArrayList<>();
+        final byte[] bytes = in.readBlob();
+        final Parcel data = Parcel.obtain();
+        try {
+            data.unmarshall(bytes, 0, bytes.length);
+            data.setDataPosition(0);
+            data.readTypedList(mBroadcastResponseStats, BroadcastResponseStats.CREATOR);
+        } finally {
+            data.recycle();
+        }
+    }
+
+    @NonNull
+    public List<BroadcastResponseStats> getList() {
+        return mBroadcastResponseStats == null ? Collections.emptyList() : mBroadcastResponseStats;
+    }
+
+    @Override
+    public @ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
+        final Parcel data = Parcel.obtain();
+        try {
+            data.writeTypedList(mBroadcastResponseStats);
+            dest.writeBlob(data.marshall());
+        } finally {
+            data.recycle();
+        }
+    }
+
+    public static final @NonNull Creator<BroadcastResponseStatsList> CREATOR =
+            new Creator<BroadcastResponseStatsList>() {
+                @Override
+                public @NonNull BroadcastResponseStatsList createFromParcel(
+                        @NonNull Parcel source) {
+                    return new BroadcastResponseStatsList(source);
+                }
+
+                @Override
+                public @NonNull BroadcastResponseStatsList[] newArray(int size) {
+                    return new BroadcastResponseStatsList[size];
+                }
+            };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 6f8fea1..a430714 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.app.usage.BroadcastResponseStats;
+import android.app.usage.BroadcastResponseStatsList;
 import android.app.usage.UsageEvents;
 import android.content.pm.ParceledListSlice;
 
@@ -73,9 +74,11 @@
     void forceUsageSourceSettingRead();
     long getLastTimeAnyComponentUsed(String packageName, String callingPackage);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
-    BroadcastResponseStats queryBroadcastResponseStats(
+    BroadcastResponseStatsList queryBroadcastResponseStats(
             String packageName, long id, String callingPackage, int userId);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
     void clearBroadcastResponseStats(String packageName, long id, String callingPackage,
             int userId);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+    void clearBroadcastEvents(String callingPackage, int userId);
 }
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index b81c62d..d7152b3 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -1397,29 +1397,46 @@
      * Returns the broadcast response stats since the last boot corresponding to
      * {@code packageName} and {@code id}.
      *
-     * <p>Broadcast response stats will include the aggregated data of what actions an app took upon
-     * receiving a broadcast. This data will consider the broadcasts that the caller sent to
+     * <p> Broadcast response stats will include the aggregated data of what actions an app took
+     * upon receiving a broadcast. This data will consider the broadcasts that the caller sent to
      * {@code packageName} and explicitly requested to record the response events using
      * {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
      *
-     * @param packageName The name of the package that the caller wants to query for.
-     * @param id The ID corresponding to the broadcasts that the caller wants to query for. This is
-     *           the ID the caller specifies when requesting a broadcast response event to be
-     *           recorded using {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
+     * <p> The returned list could one or more {@link BroadcastResponseStats} objects or be empty
+     * depending on the {@code packageName} and {@code id} and whether there is any data
+     * corresponding to these. If the {@code packageName} is not {@code null} and {@code id} is
+     * {@code > 0}, then the returned list would contain at most one {@link BroadcastResponseStats}
+     * object. Otherwise, the returned list could contain more than one
+     * {@link BroadcastResponseStats} object in no particular order.
      *
-     * @return the broadcast response stats corresponding to {@code packageName} and {@code id}.
+     * <p> Note: It is possible that same {@code id} was used for broadcasts sent to different
+     * packages. So, callers can query the data corresponding to
+     * all broadcasts with a particular {@code id} by passing {@code packageName} as {@code null}.
      *
+     * @param packageName The name of the package that the caller wants to query for
+     *                    or {@code null} to indicate that data corresponding to all packages
+     *                    should be returned.
+     * @param id The ID corresponding to the broadcasts that the caller wants to query for, or
+     *           {@code 0} to indicate that data corresponding to all IDs should be returned.
+     *           This is the ID the caller specifies when requesting a broadcast response event
+     *           to be recorded using
+     *           {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
+     *
+     * @return the list of broadcast response stats corresponding to {@code packageName}
+     *         and {@code id}.
+     *
+     * @see #clearBroadcastResponseStats(String, long)
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
     @UserHandleAware
     @NonNull
-    public BroadcastResponseStats queryBroadcastResponseStats(
-            @NonNull String packageName, @IntRange(from = 1) long id) {
+    public List<BroadcastResponseStats> queryBroadcastResponseStats(
+            @Nullable String packageName, @IntRange(from = 0) long id) {
         try {
             return mService.queryBroadcastResponseStats(packageName, id,
-                    mContext.getOpPackageName(), mContext.getUserId());
+                    mContext.getOpPackageName(), mContext.getUserId()).getList();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -1428,12 +1445,15 @@
     /**
      * Clears the broadcast response stats corresponding to {@code packageName} and {@code id}.
      *
-     * When a caller uses this API, stats related to the events occurring till that point will be
-     * cleared and subsequent calls to {@link #queryBroadcastResponseStats(String, long)} will
+     * <p> When a caller uses this API, stats related to the events occurring till that point will
+     * be cleared and subsequent calls to {@link #queryBroadcastResponseStats(String, long)} will
      * return stats related to events occurring after this.
      *
-     * @param packageName The name of the package that the caller wants to clear the data for.
-     * @param id The ID corresponding to the broadcasts that the caller wants to clear the data for.
+     * @param packageName The name of the package that the caller wants to clear the data for or
+     *                    {@code null} to indicate that data corresponding to all packages should
+     *                    be cleared.
+     * @param id The ID corresponding to the broadcasts that the caller wants to clear the data
+     *           for, or {code 0} to indicate that data corresponding to all IDs should be deleted.
      *           This is the ID the caller specifies when requesting a broadcast response event
      *           to be recorded using
      *           {@link BroadcastOptions#recordResponseEventWhileInBackground(long)}.
@@ -1444,8 +1464,8 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
     @UserHandleAware
-    public void clearBroadcastResponseStats(@NonNull String packageName,
-            @IntRange(from = 1) long id) {
+    public void clearBroadcastResponseStats(@Nullable String packageName,
+            @IntRange(from = 0) long id) {
         try {
             mService.clearBroadcastResponseStats(packageName, id,
                     mContext.getOpPackageName(), mContext.getUserId());
@@ -1453,4 +1473,19 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Clears the broadcast events that were sent by the caller uid.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+    @UserHandleAware
+    public void clearBroadcastEvents() {
+        try {
+            mService.clearBroadcastEvents(mContext.getOpPackageName(), mContext.getUserId());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 179f6ee..4dc1fca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11785,7 +11785,10 @@
      * user and that ideally it should not be covered. Setting this is only appropriate for UI
      * where the user would likely take action to uncover it.
      * <p>
-     * The system will try to respect this, but when not possible will ignore it.
+     * The system will try to respect this preference, but when not possible will ignore it.
+     * <p>
+     * Note: while this is set to {@code true}, the system will ignore the {@code Rect}s provided
+     * through {@link #setPreferKeepClearRects} (but not clear them).
      * <p>
      * @see #setPreferKeepClearRects
      * @see #isPreferKeepClear
@@ -11817,11 +11820,11 @@
      * user and that ideally they should not be covered. Setting this is only appropriate for UI
      * where the user would likely take action to uncover it.
      * <p>
-     * If the whole view is preferred to be clear ({@link #isPreferKeepClear}), the rects set here
-     * will be ignored.
-     * <p>
      * The system will try to respect this preference, but when not possible will ignore it.
      * <p>
+     * Note: While {@link #isPreferKeepClear} is {@code true}, the {@code Rect}s set here are
+     * ignored.
+     * <p>
      * @see #setPreferKeepClear
      * @see #getPreferKeepClearRects
      */
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 9a70667..d7c1846 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -64,6 +64,7 @@
  * @attr ref android.R.styleable#InputMethod_isDefault
  * @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
  * @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
+ * @attr ref android.R.styleable#InputMethod_supportsInlineSuggestionsWithTouchExploration
  * @attr ref android.R.styleable#InputMethod_suppressesSpellChecker
  * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker
  * @attr ref android.R.styleable#InputMethod_configChanges
@@ -125,6 +126,11 @@
     private final boolean mInlineSuggestionsEnabled;
 
     /**
+     * The flag whether this IME supports inline suggestions when touch exploration is enabled.
+     */
+    private final boolean mSupportsInlineSuggestionsWithTouchExploration;
+
+    /**
      * The flag whether this IME suppresses spell checker.
      */
     private final boolean mSuppressesSpellChecker;
@@ -189,6 +195,7 @@
         boolean isAuxIme = true;
         boolean supportsSwitchingToNextInputMethod = false; // false as default
         boolean inlineSuggestionsEnabled = false; // false as default
+        boolean supportsInlineSuggestionsWithTouchExploration = false; // false as default
         boolean suppressesSpellChecker = false; // false as default
         boolean showInInputMethodPicker = true; // true as default
         mForceDefault = false;
@@ -234,6 +241,9 @@
                     false);
             inlineSuggestionsEnabled = sa.getBoolean(
                     com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
+            supportsInlineSuggestionsWithTouchExploration = sa.getBoolean(
+                    com.android.internal.R.styleable
+                            .InputMethod_supportsInlineSuggestionsWithTouchExploration, false);
             suppressesSpellChecker = sa.getBoolean(
                     com.android.internal.R.styleable.InputMethod_suppressesSpellChecker, false);
             showInInputMethodPicker = sa.getBoolean(
@@ -314,6 +324,8 @@
         mIsAuxIme = isAuxIme;
         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
         mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
+        mSupportsInlineSuggestionsWithTouchExploration =
+                supportsInlineSuggestionsWithTouchExploration;
         mSuppressesSpellChecker = suppressesSpellChecker;
         mShowInInputMethodPicker = showInInputMethodPicker;
         mIsVrOnly = isVrOnly;
@@ -326,6 +338,7 @@
         mIsAuxIme = source.readInt() == 1;
         mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
         mInlineSuggestionsEnabled = source.readInt() == 1;
+        mSupportsInlineSuggestionsWithTouchExploration = source.readInt() == 1;
         mSuppressesSpellChecker = source.readBoolean();
         mShowInInputMethodPicker = source.readBoolean();
         mIsVrOnly = source.readBoolean();
@@ -345,7 +358,8 @@
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
-                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */);
+                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */,
+                false /* inlineSuggestionsEnabled */);
     }
 
     /**
@@ -360,7 +374,8 @@
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
                 false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
                 false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges,
-                false /* supportsStylusHandwriting */);
+                false /* supportsStylusHandwriting */,
+                false /* inlineSuggestionsEnabled */);
     }
 
     /**
@@ -373,7 +388,8 @@
         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
                 true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
                 false /* isVrOnly */, 0 /* handledconfigChanges */,
-                false /* supportsStylusHandwriting */);
+                false /* supportsStylusHandwriting */,
+                false /* inlineSuggestionsEnabled */);
     }
 
     /**
@@ -385,7 +401,8 @@
             boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
                 supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
-                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */);
+                0 /* handledConfigChanges */, false /* supportsStylusHandwriting */,
+                false /* inlineSuggestionsEnabled */);
     }
 
     /**
@@ -395,7 +412,8 @@
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
             List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
             boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
-            boolean isVrOnly, int handledConfigChanges, boolean supportsStylusHandwriting) {
+            boolean isVrOnly, int handledConfigChanges, boolean supportsStylusHandwriting,
+            boolean supportsInlineSuggestionsWithTouchExploration) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -406,6 +424,8 @@
         mForceDefault = forceDefault;
         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
         mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
+        mSupportsInlineSuggestionsWithTouchExploration =
+                supportsInlineSuggestionsWithTouchExploration;
         mSuppressesSpellChecker = false;
         mShowInInputMethodPicker = true;
         mIsVrOnly = isVrOnly;
@@ -583,6 +603,8 @@
                 + " mIsVrOnly=" + mIsVrOnly
                 + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
                 + " mInlineSuggestionsEnabled=" + mInlineSuggestionsEnabled
+                + " mSupportsInlineSuggestionsWithTouchExploration="
+                + mSupportsInlineSuggestionsWithTouchExploration
                 + " mSuppressesSpellChecker=" + mSuppressesSpellChecker
                 + " mShowInInputMethodPicker=" + mShowInInputMethodPicker
                 + " mSupportsStylusHandwriting=" + mSupportsStylusHandwriting);
@@ -654,6 +676,15 @@
     }
 
     /**
+     * Returns {@code true} if this input method supports inline suggestions when touch exploration
+     * is enabled.
+     * @hide
+     */
+    public boolean supportsInlineSuggestionsWithTouchExploration() {
+        return mSupportsInlineSuggestionsWithTouchExploration;
+    }
+
+    /**
      * Return {@code true} if this input method suppresses spell checker.
      */
     public boolean suppressesSpellChecker() {
@@ -683,6 +714,7 @@
         dest.writeInt(mIsAuxIme ? 1 : 0);
         dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
         dest.writeInt(mInlineSuggestionsEnabled ? 1 : 0);
+        dest.writeInt(mSupportsInlineSuggestionsWithTouchExploration ? 1 : 0);
         dest.writeBoolean(mSuppressesSpellChecker);
         dest.writeBoolean(mShowInInputMethodPicker);
         dest.writeBoolean(mIsVrOnly);
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index 0443ad0..0835824 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -455,7 +455,14 @@
             if (mSourceU != null) {
                 // T done
                 mResultT = (T) res;
-                mSourceU.whenComplete(this);
+
+                // Subscribe to the second job completion.
+                mSourceU.whenComplete((r, e) -> {
+                    // Mark the first job completion by setting mSourceU to null, so that next time
+                    // the execution flow goes to the else case below.
+                    mSourceU = null;
+                    accept(r, e);
+                });
             } else {
                 // U done
                 try {
diff --git a/core/java/com/android/internal/util/PerfettoTrigger.java b/core/java/com/android/internal/util/PerfettoTrigger.java
index c758504..f3af528 100644
--- a/core/java/com/android/internal/util/PerfettoTrigger.java
+++ b/core/java/com/android/internal/util/PerfettoTrigger.java
@@ -18,6 +18,7 @@
 
 import android.os.SystemClock;
 import android.util.Log;
+import android.util.SparseLongArray;
 
 import java.io.IOException;
 
@@ -28,8 +29,9 @@
 public class PerfettoTrigger {
     private static final String TAG = "PerfettoTrigger";
     private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto";
-    private static final long THROTTLE_MILLIS = 60000;
-    private static volatile long sLastTriggerTime = -THROTTLE_MILLIS;
+    private static final long THROTTLE_MILLIS = 300000;
+    private static final SparseLongArray sLastInvocationPerTrigger = new SparseLongArray(100);
+    private static final Object sLock = new Object();
 
     /**
      * @param triggerName The name of the trigger. Must match the value defined in the AOT
@@ -38,18 +40,23 @@
     public static void trigger(String triggerName) {
         // Trace triggering has a non-negligible cost (fork+exec).
         // To mitigate potential excessive triggering by the API client we ignore calls that happen
-        // too quickl after the most recent trigger.
-        long sinceLastTrigger = SystemClock.elapsedRealtime() - sLastTriggerTime;
-        if (sinceLastTrigger < THROTTLE_MILLIS) {
-            Log.v(TAG, "Not triggering " + triggerName + " - not enough time since last trigger");
-            return;
+        // too quickly after the most recent trigger.
+        synchronized (sLock) {
+            long lastTrigger = sLastInvocationPerTrigger.get(triggerName.hashCode());
+            long sinceLastTrigger = SystemClock.elapsedRealtime() - lastTrigger;
+            if (sinceLastTrigger < THROTTLE_MILLIS) {
+                Log.v(TAG, "Not triggering " + triggerName
+                        + " - not enough time since last trigger");
+                return;
+            }
+
+            sLastInvocationPerTrigger.put(triggerName.hashCode(), SystemClock.elapsedRealtime());
         }
 
         try {
             ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, triggerName);
             Log.v(TAG, "Triggering " + String.join(" ", pb.command()));
             pb.start();
-            sLastTriggerTime = SystemClock.elapsedRealtime();
         } catch (IOException e) {
             Log.w(TAG, "Failed to trigger " + triggerName, e);
         }
diff --git a/core/java/com/android/internal/util/UserIcons.java b/core/java/com/android/internal/util/UserIcons.java
index 17b84ff..d9c1e57 100644
--- a/core/java/com/android/internal/util/UserIcons.java
+++ b/core/java/com/android/internal/util/UserIcons.java
@@ -46,11 +46,21 @@
      * Converts a given drawable to a bitmap.
      */
     public static Bitmap convertToBitmap(Drawable icon) {
+        return convertToBitmapAtSize(icon, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+    }
+
+    /**
+     * Converts a given drawable to a bitmap, with width and height equal to the default icon size.
+     */
+    public static Bitmap convertToBitmapAtUserIconSize(Resources res, Drawable icon) {
+        int size = res.getDimensionPixelSize(R.dimen.user_icon_size);
+        return convertToBitmapAtSize(icon, size, size);
+    }
+
+    private static Bitmap convertToBitmapAtSize(Drawable icon, int width, int height) {
         if (icon == null) {
             return null;
         }
-        final int width = icon.getIntrinsicWidth();
-        final int height = icon.getIntrinsicHeight();
         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         Canvas canvas = new Canvas(bitmap);
         icon.setBounds(0, 0, width, height);
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 78bb53d..5fa4a65 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -150,6 +150,7 @@
     private Icon mShortcutIcon;
     private View mAppNameDivider;
     private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this);
+    private ArrayList<MessagingGroup> mToRecycle = new ArrayList<>();
 
     public ConversationLayout(@NonNull Context context) {
         super(context);
@@ -472,6 +473,12 @@
         updateTitleAndNamesDisplay();
 
         updateConversationLayout();
+
+        // Recycle everything at the end of the update, now that we know it's no longer needed.
+        for (MessagingGroup group : mToRecycle) {
+            group.recycle();
+        }
+        mToRecycle.clear();
     }
 
     /**
@@ -745,18 +752,18 @@
             MessagingGroup group = oldGroups.get(i);
             if (!mGroups.contains(group)) {
                 List<MessagingMessage> messages = group.getMessages();
-                Runnable endRunnable = () -> {
-                    mMessagingLinearLayout.removeTransientView(group);
-                    group.recycle();
-                };
-
                 boolean wasShown = group.isShown();
                 mMessagingLinearLayout.removeView(group);
                 if (wasShown && !MessagingLinearLayout.isGone(group)) {
                     mMessagingLinearLayout.addTransientView(group, 0);
-                    group.removeGroupAnimated(endRunnable);
+                    group.removeGroupAnimated(() -> {
+                        mMessagingLinearLayout.removeTransientView(group);
+                        group.recycle();
+                    });
                 } else {
-                    endRunnable.run();
+                    // Defer recycling until after the update is done, since we may still need the
+                    // old group around to perform other updates.
+                    mToRecycle.add(group);
                 }
                 mMessages.removeAll(messages);
                 mHistoricMessages.removeAll(messages);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 47cb754..4aa00f6 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -64,7 +64,6 @@
         "libbase",
         "libcutils",
         "libharfbuzz_ng",
-        "libhwui",
         "liblog",
         "libminikin",
         "libz",
@@ -266,6 +265,7 @@
                 "libui",
                 "libgraphicsenv",
                 "libgui",
+                "libhwui",
                 "libmediandk",
                 "libpermission",
                 "libsensor",
@@ -344,9 +344,21 @@
             ],
             static_libs: [
                 "libandroidfw",
-                "libcompiler_rt",
-                "libutils",
+                "libbinary_parse",
+                "libdng_sdk",
+                "libft2",
                 "libhostgraphics",
+                "libhwui",
+                "libimage_type_recognition",
+                "libjpeg",
+                "libpiex",
+                "libpng",
+                "libtiff_directory",
+                "libui-types",
+                "libutils",
+                "libwebp-decode",
+                "libwebp-encode",
+                "libwuffs_mirror_release_c",
             ],
         },
         linux_glibc: {
diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp
index 3e513df..93ba23b 100644
--- a/core/jni/LayoutlibLoader.cpp
+++ b/core/jni/LayoutlibLoader.cpp
@@ -14,15 +14,31 @@
  * limitations under the License.
  */
 
-#include "jni.h"
-#include "core_jni_helpers.h"
-
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/graphics/jni_runtime.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/jni_macros.h>
 #include <unicode/putil.h>
+#include <unicode/udata.h>
+
 #include <clocale>
 #include <sstream>
 #include <unordered_map>
 #include <vector>
 
+#include "core_jni_helpers.h"
+#include "jni.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#endif
+
+#include <iostream>
+
 using namespace std;
 
 /*
@@ -33,6 +49,33 @@
  */
 
 static JavaVM* javaVM;
+static jclass bridge;
+static jclass layoutLog;
+static jmethodID getLogId;
+static jmethodID logMethodId;
+
+extern int register_android_os_Binder(JNIEnv* env);
+extern int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env);
+
+typedef void (*FreeFunction)(void*);
+
+static void NativeAllocationRegistry_Delegate_nativeApplyFreeFunction(JNIEnv*, jclass,
+                                                                      jlong freeFunction,
+                                                                      jlong ptr) {
+    void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
+    FreeFunction nativeFreeFunction =
+            reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
+    nativeFreeFunction(nativePtr);
+}
+
+static JNINativeMethod gMethods[] = {
+        NATIVE_METHOD(NativeAllocationRegistry_Delegate, nativeApplyFreeFunction, "(JJ)V"),
+};
+
+int register_libcore_util_NativeAllocationRegistry_Delegate(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "libcore/util/NativeAllocationRegistry_Delegate", gMethods,
+                                    NELEM(gMethods));
+}
 
 namespace android {
 
@@ -47,6 +90,7 @@
 extern int register_android_database_SQLiteDebug(JNIEnv* env);
 extern int register_android_os_FileObserver(JNIEnv* env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
+extern int register_android_os_Parcel(JNIEnv* env);
 extern int register_android_os_SystemClock(JNIEnv* env);
 extern int register_android_os_SystemProperties(JNIEnv* env);
 extern int register_android_os_Trace(JNIEnv* env);
@@ -54,6 +98,11 @@
 extern int register_android_util_EventLog(JNIEnv* env);
 extern int register_android_util_Log(JNIEnv* env);
 extern int register_android_util_jar_StrictJarFile(JNIEnv* env);
+extern int register_android_view_KeyCharacterMap(JNIEnv* env);
+extern int register_android_view_KeyEvent(JNIEnv* env);
+extern int register_android_view_MotionEvent(JNIEnv* env);
+extern int register_android_view_ThreadedRenderer(JNIEnv* env);
+extern int register_android_view_VelocityTracker(JNIEnv* env);
 extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
 
 #define REG_JNI(name)      { name }
@@ -78,8 +127,10 @@
         {"android.content.res.StringBlock", REG_JNI(register_android_content_StringBlock)},
         {"android.content.res.XmlBlock", REG_JNI(register_android_content_XmlBlock)},
 #ifdef __linux__
+        {"android.os.Binder", REG_JNI(register_android_os_Binder)},
         {"android.os.FileObserver", REG_JNI(register_android_os_FileObserver)},
         {"android.os.MessageQueue", REG_JNI(register_android_os_MessageQueue)},
+        {"android.os.Parcel", REG_JNI(register_android_os_Parcel)},
 #endif
         {"android.os.SystemClock", REG_JNI(register_android_os_SystemClock)},
         {"android.os.SystemProperties", REG_JNI(register_android_os_SystemProperties)},
@@ -88,11 +139,15 @@
         {"android.util.EventLog", REG_JNI(register_android_util_EventLog)},
         {"android.util.Log", REG_JNI(register_android_util_Log)},
         {"android.util.jar.StrictJarFile", REG_JNI(register_android_util_jar_StrictJarFile)},
+        {"android.view.KeyCharacterMap", REG_JNI(register_android_view_KeyCharacterMap)},
+        {"android.view.KeyEvent", REG_JNI(register_android_view_KeyEvent)},
+        {"android.view.MotionEvent", REG_JNI(register_android_view_MotionEvent)},
+        {"android.view.VelocityTracker", REG_JNI(register_android_view_VelocityTracker)},
         {"com.android.internal.util.VirtualRefBasePtr",
          REG_JNI(register_com_android_internal_util_VirtualRefBasePtr)},
+        {"libcore.util.NativeAllocationRegistry_Delegate",
+         REG_JNI(register_libcore_util_NativeAllocationRegistry_Delegate)},
 };
-// Vector to store the names of classes that need delegates of their native methods
-static vector<string> classesToDelegate;
 
 static int register_jni_procs(const std::unordered_map<std::string, RegJNIRec>& jniRegMap,
         const vector<string>& classesToRegister, JNIEnv* env) {
@@ -102,36 +157,17 @@
             return -1;
         }
     }
+
+    if (register_android_graphics_classes(env) < 0) {
+        return -1;
+    }
+
     return 0;
 }
 
 int AndroidRuntime::registerNativeMethods(JNIEnv* env,
         const char* className, const JNINativeMethod* gMethods, int numMethods) {
-    string classNameString = string(className);
-    if (find(classesToDelegate.begin(), classesToDelegate.end(), classNameString)
-            != classesToDelegate.end()) {
-        // Register native methods to the delegate class <classNameString>_NativeDelegate
-        // by adding _Original to the name of each method.
-        replace(classNameString.begin(), classNameString.end(), '$', '_');
-        string delegateClassName = classNameString + "_NativeDelegate";
-        jclass clazz = env->FindClass(delegateClassName.c_str());
-        JNINativeMethod gTypefaceDelegateMethods[numMethods];
-        for (int i = 0; i < numMethods; i++) {
-            JNINativeMethod gTypefaceMethod = gMethods[i];
-            string newName = string(gTypefaceMethod.name) + "_Original";
-            gTypefaceDelegateMethods[i].name = strdup(newName.c_str());
-            gTypefaceDelegateMethods[i].signature = gTypefaceMethod.signature;
-            gTypefaceDelegateMethods[i].fnPtr = gTypefaceMethod.fnPtr;
-        }
-        int result = env->RegisterNatives(clazz, gTypefaceDelegateMethods, numMethods);
-        for (int i = 0; i < numMethods; i++) {
-            free((char*)gTypefaceDelegateMethods[i].name);
-        }
-        return result;
-    }
-
-    jclass clazz = env->FindClass(className);
-    return env->RegisterNatives(clazz, gMethods, numMethods);
+    return jniRegisterNativeMethods(env, className, gMethods, numMethods);
 }
 
 JNIEnv* AndroidRuntime::getJNIEnv() {
@@ -164,6 +200,125 @@
     return result;
 }
 
+void LayoutlibLogger(base::LogId, base::LogSeverity severity, const char* tag, const char* file,
+                     unsigned int line, const char* message) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jint logPrio = severity;
+    jstring tagString = env->NewStringUTF(tag);
+    jstring messageString = env->NewStringUTF(message);
+
+    jobject bridgeLog = env->CallStaticObjectMethod(bridge, getLogId);
+
+    env->CallVoidMethod(bridgeLog, logMethodId, logPrio, tagString, messageString);
+
+    env->DeleteLocalRef(tagString);
+    env->DeleteLocalRef(messageString);
+    env->DeleteLocalRef(bridgeLog);
+}
+
+void LayoutlibAborter(const char* abort_message) {
+    // Layoutlib should not call abort() as it would terminate Studio.
+    // Throw an exception back to Java instead.
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jniThrowRuntimeException(env, "The Android framework has encountered a fatal error");
+}
+
+// This method has been copied/adapted from system/core/init/property_service.cpp
+// If the ro.product.cpu.abilist* properties have not been explicitly
+// set, derive them from ro.system.product.cpu.abilist* properties.
+static void property_initialize_ro_cpu_abilist() {
+    const std::string EMPTY = "";
+    const char* kAbilistProp = "ro.product.cpu.abilist";
+    const char* kAbilist32Prop = "ro.product.cpu.abilist32";
+    const char* kAbilist64Prop = "ro.product.cpu.abilist64";
+
+    // If the properties are defined explicitly, just use them.
+    if (base::GetProperty(kAbilistProp, EMPTY) != EMPTY) {
+        return;
+    }
+
+    std::string abilist32_prop_val;
+    std::string abilist64_prop_val;
+    const auto abilist32_prop = "ro.system.product.cpu.abilist32";
+    const auto abilist64_prop = "ro.system.product.cpu.abilist64";
+    abilist32_prop_val = base::GetProperty(abilist32_prop, EMPTY);
+    abilist64_prop_val = base::GetProperty(abilist64_prop, EMPTY);
+
+    // Merge ABI lists for ro.product.cpu.abilist
+    auto abilist_prop_val = abilist64_prop_val;
+    if (abilist32_prop_val != EMPTY) {
+        if (abilist_prop_val != EMPTY) {
+            abilist_prop_val += ",";
+        }
+        abilist_prop_val += abilist32_prop_val;
+    }
+
+    // Set these properties
+    const std::pair<const char*, const std::string&> set_prop_list[] = {
+            {kAbilistProp, abilist_prop_val},
+            {kAbilist32Prop, abilist32_prop_val},
+            {kAbilist64Prop, abilist64_prop_val},
+    };
+    for (const auto& [prop, prop_val] : set_prop_list) {
+        base::SetProperty(prop, prop_val);
+    }
+}
+
+static void* mmapFile(const char* dataFilePath) {
+#ifdef _WIN32
+    // Windows needs file path in wide chars to handle unicode file paths
+    int size = MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, NULL, 0);
+    std::vector<wchar_t> wideDataFilePath(size);
+    MultiByteToWideChar(CP_UTF8, 0, dataFilePath, -1, wideDataFilePath.data(), size);
+    HANDLE file =
+            CreateFileW(wideDataFilePath.data(), GENERIC_READ, FILE_SHARE_READ, nullptr,
+                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
+    if ((HANDLE)INVALID_HANDLE_VALUE == file) {
+        return nullptr;
+    }
+
+    struct CloseHandleWrapper {
+        void operator()(HANDLE h) { CloseHandle(h); }
+    };
+    std::unique_ptr<void, CloseHandleWrapper> mmapHandle(
+            CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
+    if (!mmapHandle) {
+        return nullptr;
+    }
+    return MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0);
+#else
+    int fd = open(dataFilePath, O_RDONLY);
+    if (fd == -1) {
+        return nullptr;
+    }
+
+    struct stat sb;
+    if (fstat(fd, &sb) == -1) {
+        close(fd);
+        return nullptr;
+    }
+
+    void* addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+    if (addr == MAP_FAILED) {
+        close(fd);
+        return nullptr;
+    }
+
+    close(fd);
+    return addr;
+#endif
+}
+
+static bool init_icu(const char* dataPath) {
+    void* addr = mmapFile(dataPath);
+    UErrorCode err = U_ZERO_ERROR;
+    udata_setCommonData(addr, &err);
+    if (err != U_ZERO_ERROR) {
+        return false;
+    }
+    return true;
+}
+
 } // namespace android
 
 using namespace android;
@@ -175,37 +330,82 @@
         return JNI_ERR;
     }
 
+    init_android_graphics();
+
     // Configuration is stored as java System properties.
     // Get a reference to System.getProperty
     jclass system = FindClassOrDie(env, "java/lang/System");
     jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty",
                                                          "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
 
-    // Get the names of classes that have to delegate their native methods
-    auto delegateNativesToNativesString =
-            (jstring) env->CallStaticObjectMethod(system,
-                    getPropertyMethod, env->NewStringUTF("delegate_natives_to_natives"),
-                    env->NewStringUTF(""));
-    classesToDelegate = parseCsv(env, delegateNativesToNativesString);
-
     // Get the names of classes that need to register their native methods
     auto nativesClassesJString =
-            (jstring) env->CallStaticObjectMethod(system,
-                                                  getPropertyMethod, env->NewStringUTF("native_classes"),
-                                                  env->NewStringUTF(""));
+            (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                 env->NewStringUTF("core_native_classes"),
+                                                 env->NewStringUTF(""));
     vector<string> classesToRegister = parseCsv(env, nativesClassesJString);
 
+    jstring registerProperty =
+            (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                 env->NewStringUTF(
+                                                         "register_properties_during_load"),
+                                                 env->NewStringUTF(""));
+    const char* registerPropertyString = env->GetStringUTFChars(registerProperty, 0);
+    if (strcmp(registerPropertyString, "true") == 0) {
+        // Set the system properties first as they could be used in the static initialization of
+        // other classes
+        if (register_android_os_SystemProperties(env) < 0) {
+            return JNI_ERR;
+        }
+        classesToRegister.erase(find(classesToRegister.begin(), classesToRegister.end(),
+                                     "android.os.SystemProperties"));
+        bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+        bridge = MakeGlobalRefOrDie(env, bridge);
+        jmethodID setSystemPropertiesMethod =
+                GetStaticMethodIDOrDie(env, bridge, "setSystemProperties", "()V");
+        env->CallStaticVoidMethod(bridge, setSystemPropertiesMethod);
+        property_initialize_ro_cpu_abilist();
+    }
+    env->ReleaseStringUTFChars(registerProperty, registerPropertyString);
+
     if (register_jni_procs(gRegJNIMap, classesToRegister, env) < 0) {
         return JNI_ERR;
     }
 
     // Set the location of ICU data
-    auto stringPath = (jstring) env->CallStaticObjectMethod(system,
-        getPropertyMethod, env->NewStringUTF("icu.dir"),
-        env->NewStringUTF(""));
+    auto stringPath = (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                           env->NewStringUTF("icu.data.path"),
+                                                           env->NewStringUTF(""));
     const char* path = env->GetStringUTFChars(stringPath, 0);
-    u_setDataDirectory(path);
+    bool icuInitialized = init_icu(path);
     env->ReleaseStringUTFChars(stringPath, path);
+    if (!icuInitialized) {
+        return JNI_ERR;
+    }
+
+    jstring useJniProperty =
+            (jstring)env->CallStaticObjectMethod(system, getPropertyMethod,
+                                                 env->NewStringUTF("use_bridge_for_logging"),
+                                                 env->NewStringUTF(""));
+    const char* useJniString = env->GetStringUTFChars(useJniProperty, 0);
+    if (strcmp(useJniString, "true") == 0) {
+        layoutLog = FindClassOrDie(env, "com/android/ide/common/rendering/api/ILayoutLog");
+        layoutLog = MakeGlobalRefOrDie(env, layoutLog);
+        logMethodId = GetMethodIDOrDie(env, layoutLog, "logAndroidFramework",
+                                       "(ILjava/lang/String;Ljava/lang/String;)V");
+        if (bridge == nullptr) {
+            bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
+            bridge = MakeGlobalRefOrDie(env, bridge);
+        }
+        getLogId = GetStaticMethodIDOrDie(env, bridge, "getLog",
+                                          "()Lcom/android/ide/common/rendering/api/ILayoutLog;");
+        android::base::SetLogger(LayoutlibLogger);
+        android::base::SetAborter(LayoutlibAborter);
+    } else {
+        // initialize logging, so ANDROD_LOG_TAGS env variable is respected
+        android::base::InitLogging(nullptr, android::base::StderrLogger);
+    }
+    env->ReleaseStringUTFChars(useJniProperty, useJniString);
 
     // Use English locale for number format to ensure correct parsing of floats when using strtof
     setlocale(LC_NUMERIC, "en_US.UTF-8");
@@ -213,3 +413,9 @@
     return JNI_VERSION_1_6;
 }
 
+JNIEXPORT void JNI_OnUnload(JavaVM* vm, void*) {
+    JNIEnv* env = nullptr;
+    vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+    env->DeleteGlobalRef(bridge);
+    env->DeleteGlobalRef(layoutLog);
+}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fca2bd1..7150fca 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3364,7 +3364,7 @@
             area for the user and that ideally it should not be covered. Setting this is only
             appropriate for UI where the user would likely take action to uncover it.
             <p>The system will try to respect this, but when not possible will ignore it.
-            See {@link android.view.View#setPreferKeepClear}. -->
+            <p>This is equivalent to {@link android.view.View#setPreferKeepClear}.-->
         <attr name="preferKeepClear" format="boolean" />
 
         <!-- <p>Whether or not the auto handwriting initiation is enabled in this View.
@@ -3644,6 +3644,14 @@
         <attr name="__removed2" format="boolean" />
         <!-- Specifies whether the IME supports showing inline suggestions. -->
         <attr name="supportsInlineSuggestions" format="boolean" />
+        <!-- Specifies whether the IME supports showing inline suggestions when touch
+             exploration is enabled. This does nothing if supportsInlineSuggestions is false.
+             The default value is false and most IMEs should not set this
+             to true since the older menu-style Autofill works better with touch exploration.
+             This attribute should be set to true in special situations, such as if this is an
+             accessibility-focused IME which blocks user interaction with the app window while the
+             IME is displayed. -->
+        <attr name="supportsInlineSuggestionsWithTouchExploration" format="boolean" />
         <!-- Specifies whether the IME suppresses system spell checker.
              The default value is false. If an IME sets this attribute to true,
              the system spell checker will be disabled while the IME has an
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4874e65..39b41b5 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -991,4 +991,7 @@
     <dimen name="secondary_rounded_corner_radius_adjustment">0px</dimen>
     <dimen name="secondary_rounded_corner_radius_top_adjustment">0px</dimen>
     <dimen name="secondary_rounded_corner_radius_bottom_adjustment">0px</dimen>
+
+    <!-- Default size for user icons (a.k.a. avatar images) -->
+    <dimen name="user_icon_size">190dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9fa5f78..3beb4b2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3280,6 +3280,7 @@
     <public name="knownActivityEmbeddingCerts" />
     <public name="intro" />
     <public name="enableOnBackInvokedCallback" />
+    <public name="supportsInlineSuggestionsWithTouchExploration" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01de0000">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e27aa83..f531c3a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -545,6 +545,7 @@
   <java-symbol type="dimen" name="immersive_mode_cling_width" />
   <java-symbol type="dimen" name="accessibility_magnification_indicator_width" />
   <java-symbol type="dimen" name="circular_display_mask_thickness" />
+  <java-symbol type="dimen" name="user_icon_size" />
 
   <java-symbol type="string" name="add_account_button_label" />
   <java-symbol type="string" name="addToDictionary" />
diff --git a/core/tests/coretests/res/xml/ime_meta_inline_suggestions_with_touch_exploration.xml b/core/tests/coretests/res/xml/ime_meta_inline_suggestions_with_touch_exploration.xml
new file mode 100644
index 0000000..3440208
--- /dev/null
+++ b/core/tests/coretests/res/xml/ime_meta_inline_suggestions_with_touch_exploration.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<input-method
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity"
+    android:supportsInlineSuggestionsWithTouchExploration="true"
+>
+    <subtype
+        android:label="subtype1"
+        android:imeSubtypeLocale="en_US"
+        android:imeSubtypeMode="keyboard" />
+</input-method>
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index 8718b95..e7d7d640 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -55,11 +55,13 @@
 
         assertThat(imi.supportsSwitchingToNextInputMethod(), is(false));
         assertThat(imi.isInlineSuggestionsEnabled(), is(false));
+        assertThat(imi.supportsInlineSuggestionsWithTouchExploration(), is(false));
 
         final InputMethodInfo clone = cloneViaParcel(imi);
 
         assertThat(clone.supportsSwitchingToNextInputMethod(), is(false));
         assertThat(imi.isInlineSuggestionsEnabled(), is(false));
+        assertThat(imi.supportsInlineSuggestionsWithTouchExploration(), is(false));
     }
 
     @Test
@@ -85,6 +87,18 @@
     }
 
     @Test
+    public void testInlineSuggestionsEnabledWithTouchExploration() throws Exception {
+        final InputMethodInfo imi =
+                buildInputMethodForTest(R.xml.ime_meta_inline_suggestions_with_touch_exploration);
+
+        assertThat(imi.supportsInlineSuggestionsWithTouchExploration(), is(true));
+
+        final InputMethodInfo clone = cloneViaParcel(imi);
+
+        assertThat(clone.supportsInlineSuggestionsWithTouchExploration(), is(true));
+    }
+
+    @Test
     public void testIsVrOnly() throws Exception {
         final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_vr_only);
 
diff --git a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
index a2bc77a..3a27225 100644
--- a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
+++ b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java
@@ -29,6 +29,7 @@
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
+import java.util.function.BiFunction;
 
 /**
  * Unit test for {@link AndroidFuture}.
@@ -154,4 +155,35 @@
                 expectThrows(ExecutionException.class, future1::get);
         assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class);
     }
+
+    @Test
+    public void testThenCombine() throws Exception {
+        String nearFutureString = "near future comes";
+        AndroidFuture<String> nearFuture = AndroidFuture.supply(() -> nearFutureString);
+        String farFutureString = " before far future.";
+        AndroidFuture<String> farFuture = AndroidFuture.supply(() -> farFutureString);
+        AndroidFuture<String> combinedFuture =
+                nearFuture.thenCombine(farFuture, ((s1, s2) -> s1 + s2));
+
+        assertThat(combinedFuture.get()).isEqualTo(nearFutureString + farFutureString);
+    }
+
+    @Test
+    public void testThenCombine_functionThrowingException() throws Exception {
+        String nearFutureString = "near future comes";
+        AndroidFuture<String> nearFuture = AndroidFuture.supply(() -> nearFutureString);
+        String farFutureString = " before far future.";
+        AndroidFuture<String> farFuture = AndroidFuture.supply(() -> farFutureString);
+        UnsupportedOperationException exception = new UnsupportedOperationException(
+                "Unsupported operation exception thrown!");
+        BiFunction<String, String, String> throwingFunction = (s1, s2) -> {
+            throw exception;
+        };
+        AndroidFuture<String> combinedFuture = nearFuture.thenCombine(farFuture, throwingFunction);
+
+        ExecutionException thrown = expectThrows(ExecutionException.class,
+                () -> combinedFuture.get());
+
+        assertThat(thrown.getCause()).isSameInstanceAs(exception);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 6ffcf10..241f1a7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -423,7 +423,6 @@
                             WindowContainerTransaction t) {
                         // This is triggered right before the rotation is applied
                         if (fromRotation != toRotation) {
-                            mBubblePositioner.setRotation(toRotation);
                             if (mStackView != null) {
                                 // Layout listener set on stackView will update the positioner
                                 // once the rotation is applied
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 127d5a8..75b19fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -20,6 +20,7 @@
 
 import android.annotation.IntDef;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Insets;
 import android.graphics.PointF;
@@ -112,10 +113,6 @@
         update();
     }
 
-    public void setRotation(int rotation) {
-        mRotation = rotation;
-    }
-
     /**
      * Available space and inset information. Call this when config changes
      * occur or when added to a window.
@@ -273,7 +270,8 @@
 
     /** @return whether the device is in landscape orientation. */
     public boolean isLandscape() {
-        return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270;
+        return mContext.getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
     }
 
     /** @return whether the screen is considered large. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 67b3983..13d9081 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -310,6 +310,10 @@
         return mPipTransitionState.isInPip();
     }
 
+    private boolean isLaunchIntoPipTask() {
+        return mPictureInPictureParams != null && mPictureInPictureParams.isLaunchIntoPip();
+    }
+
     /**
      * Returns whether the entry animation is waiting to be started.
      */
@@ -397,6 +401,10 @@
         }
 
         final WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (isLaunchIntoPipTask()) {
+            exitLaunchIntoPipTask(wct);
+            return;
+        }
 
         if (ENABLE_SHELL_TRANSITIONS) {
             if (requestEnterSplit && mSplitScreenOptional.isPresent()) {
@@ -468,6 +476,14 @@
         });
     }
 
+    private void exitLaunchIntoPipTask(WindowContainerTransaction wct) {
+        wct.startTask(mTaskInfo.launchIntoPipHostTaskId, null /* ActivityOptions */);
+        mTaskOrganizer.applyTransaction(wct);
+
+        // Remove the PiP with fade-out animation right after the host Task is brought to front.
+        removePip();
+    }
+
     private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) {
         // Reset the final windowing mode.
         wct.setWindowingMode(mToken, getOutPipWindowingMode());
@@ -729,7 +745,7 @@
     }
 
     /**
-     * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
+     * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int, boolean)}.
      * Meanwhile this callback is invoked whenever the task is removed. For instance:
      *   - as a result of removeRootTasksInWindowingModes from WM
      *   - activity itself is died
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3887372..6e695e6 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -7294,8 +7294,13 @@
      * Ultrasound playback and capture, false otherwise.
      */
     @SystemApi
-    public static boolean isUltrasoundSupported() {
-        return AudioSystem.isUltrasoundSupported();
+    @RequiresPermission(android.Manifest.permission.ACCESS_ULTRASOUND)
+    public boolean isUltrasoundSupported() {
+        try {
+            return getService().isUltrasoundSupported();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 2c9f015..d702eb9 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -138,6 +138,8 @@
 
     boolean isMicrophoneMuted();
 
+    boolean isUltrasoundSupported();
+
     void setMicrophoneMute(boolean on, String callingPackage, int userId, in String attributionTag);
 
     oneway void setMicrophoneMuteFromSwitch(boolean on);
diff --git a/native/android/input.cpp b/native/android/input.cpp
index c06c81e..a231d8f 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -283,6 +283,21 @@
             axis, pointer_index, history_index);
 }
 
+int32_t AMotionEvent_getActionButton(const AInputEvent* motion_event) {
+    return static_cast<const MotionEvent*>(motion_event)->getActionButton();
+}
+
+int32_t AMotionEvent_getClassification(const AInputEvent* motion_event) {
+    switch (static_cast<const MotionEvent*>(motion_event)->getClassification()) {
+        case android::MotionClassification::NONE:
+            return AMOTION_EVENT_CLASSIFICATION_NONE;
+        case android::MotionClassification::AMBIGUOUS_GESTURE:
+            return AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE;
+        case android::MotionClassification::DEEP_PRESS:
+            return AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS;
+    }
+}
+
 const AInputEvent* AMotionEvent_fromJava(JNIEnv* env, jobject motionEvent) {
     MotionEvent* eventSrc = android::android_view_MotionEvent_getNativePtr(env, motionEvent);
     if (eventSrc == nullptr) {
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 3009a36..67a98a9 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -114,8 +114,10 @@
     ALooper_removeFd;
     ALooper_wake;
     AMotionEvent_getAction;
+    AMotionEvent_getActionButton; # introduced=Tiramisu
     AMotionEvent_getAxisValue; # introduced-arm=13 introduced-arm64=21 introduced-mips=13 introduced-mips64=21 introduced-x86=13 introduced-x86_64=21
     AMotionEvent_getButtonState; # introduced-arm=14 introduced-arm64=21 introduced-mips=14 introduced-mips64=21 introduced-x86=14 introduced-x86_64=21
+    AMotionEvent_getClassification; # introduced=Tiramisu
     AMotionEvent_getDownTime;
     AMotionEvent_getEdgeFlags;
     AMotionEvent_getEventTime;
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
index 0e60873..6ded1637 100644
--- a/packages/CompanionDeviceManager/Android.bp
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -39,6 +39,7 @@
     static_libs: [
         "androidx.lifecycle_lifecycle-livedata",
         "androidx.lifecycle_lifecycle-extensions",
+        "androidx.recyclerview_recyclerview",
         "androidx.appcompat_appcompat",
     ],
 
diff --git a/packages/CompanionDeviceManager/res/color/selector.xml b/packages/CompanionDeviceManager/res/color/selector.xml
new file mode 100644
index 0000000..fda827d
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/color/selector.xml
@@ -0,0 +1,20 @@
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT 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_pressed="true" android:color="@android:color/darker_gray"/> <!-- pressed -->
+    <item android:color="@android:color/white"/>
+</selector>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
index 313e164..70cbfdf 100644
--- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
@@ -49,8 +49,8 @@
             android:layout_height="0dp"
             android:layout_weight="1">
 
-        <ListView
-                android:id="@+id/device_list"
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/device_list"
                 style="@android:style/Widget.Material.ListView"
                 android:layout_width="match_parent"
                 android:layout_height="200dp" />
diff --git a/packages/CompanionDeviceManager/res/layout/list_item_device.xml b/packages/CompanionDeviceManager/res/layout/list_item_device.xml
index d79aea6..153fc1f 100644
--- a/packages/CompanionDeviceManager/res/layout/list_item_device.xml
+++ b/packages/CompanionDeviceManager/res/layout/list_item_device.xml
@@ -19,7 +19,8 @@
               android:layout_height="wrap_content"
               android:orientation="horizontal"
               android:gravity="center_vertical"
-              android:padding="12dp">
+              android:padding="12dp"
+              android:background="@color/selector">
 
     <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index 16e851b..b51d310 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -46,10 +46,11 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
-import android.widget.ListView;
 import android.widget.TextView;
 
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
 
 import java.util.List;
 
@@ -94,9 +95,9 @@
     // regular.
     private Button mButtonAllow;
 
-    // The list is only shown for multiple-device regular association request, after at least one
-    // matching device is found.
-    private @Nullable ListView mListView;
+    // The recycler view is only shown for multiple-device regular association request, after
+    // at least one matching device is found.
+    private @Nullable RecyclerView mRecyclerView;
     private @Nullable DeviceListAdapter mAdapter;
 
     // The flag used to prevent double taps, that may lead to sending several requests for creating
@@ -195,14 +196,15 @@
         mTitle = findViewById(R.id.title);
         mSummary = findViewById(R.id.summary);
 
-        mListView = findViewById(R.id.device_list);
-        mListView.setOnItemClickListener((av, iv, position, id) -> onListItemClick(position));
+        mRecyclerView = findViewById(R.id.device_list);
+        mAdapter = new DeviceListAdapter(this, this::onListItemClick);
 
         mButtonAllow = findViewById(R.id.btn_positive);
         mButtonAllow.setOnClickListener(this::onPositiveButtonClick);
         findViewById(R.id.btn_negative).setOnClickListener(this::onNegativeButtonClick);
 
         final CharSequence appLabel = getApplicationLabel(this, mRequest.getPackageName());
+
         if (mRequest.isSelfManaged()) {
             initUiForSelfManagedAssociation(appLabel);
         } else if (mRequest.isSingleDevice()) {
@@ -333,7 +335,7 @@
         mTitle.setText(title);
         mSummary.setText(summary);
 
-        mListView.setVisibility(View.GONE);
+        mRecyclerView.setVisibility(View.GONE);
     }
 
     private void initUiForSingleDevice(CharSequence appLabel) {
@@ -345,12 +347,12 @@
                 deviceFilterPairs -> updateSingleDeviceUi(
                         deviceFilterPairs, deviceProfile, appLabel));
 
-        mListView.setVisibility(View.GONE);
+        mRecyclerView.setVisibility(View.GONE);
     }
 
     private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs,
             String deviceProfile, CharSequence appLabel) {
-        // Ignore "empty" scan repots.
+        // Ignore "empty" scan reports.
         if (deviceFilterPairs.isEmpty()) return;
         mSelectedDevice = requireNonNull(deviceFilterPairs.get(0));
 
@@ -393,10 +395,12 @@
         mTitle.setText(title);
         mSummary.setText(summary);
 
-        mAdapter = new DeviceListAdapter(this);
+        mAdapter = new DeviceListAdapter(this, this::onListItemClick);
 
         // TODO: hide the list and show a spinner until a first device matching device is found.
-        mListView.setAdapter(mAdapter);
+        mRecyclerView.setAdapter(mAdapter);
+        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+
         CompanionDeviceDiscoveryService.getScanResult().observe(
                 /* lifecycleOwner */ this,
                 /* observer */ mAdapter);
@@ -414,6 +418,8 @@
             if (DEBUG) Log.w(TAG, "Already selected.");
             return;
         }
+        // Notify the adapter to highlight the selected item.
+        mAdapter.setSelectedPosition(position);
 
         mSelectedDevice = requireNonNull(selectedDevice);
 
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
index 198b778..e5513b0 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceListAdapter.java
@@ -15,73 +15,84 @@
  */
 
 package com.android.companiondevicemanager;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.BaseAdapter;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.lifecycle.Observer;
+import androidx.recyclerview.widget.RecyclerView;
 
 import java.util.List;
-
 /**
  * Adapter for the list of "found" devices.
  */
-class DeviceListAdapter extends BaseAdapter implements Observer<List<DeviceFilterPair<?>>> {
+class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolder> implements
+        Observer<List<DeviceFilterPair<?>>> {
+    public int mSelectedPosition = RecyclerView.NO_POSITION;
+
     private final Context mContext;
 
     // List if pairs (display name, address)
     private List<DeviceFilterPair<?>> mDevices;
 
-    DeviceListAdapter(Context context) {
+    private OnItemClickListener mListener;
+
+    private static final int TYPE_WIFI = 0;
+    private static final int TYPE_BT = 1;
+
+    DeviceListAdapter(Context context, OnItemClickListener listener) {
         mContext = context;
+        mListener = listener;
     }
 
-    @Override
-    public int getCount() {
-        return mDevices != null ? mDevices.size() : 0;
-    }
-
-    @Override
     public DeviceFilterPair<?> getItem(int position) {
         return mDevices.get(position);
     }
 
     @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        View view = LayoutInflater.from(parent.getContext()).inflate(
+                R.layout.list_item_device, parent, false);
+        ViewHolder viewHolder = new ViewHolder(view);
+        if (viewType == TYPE_WIFI) {
+            viewHolder.mImageView.setImageDrawable(getIcon(
+                    com.android.internal.R.drawable.ic_wifi_signal_3));
+        } else {
+            viewHolder.mImageView.setImageDrawable(getIcon(
+                    android.R.drawable.stat_sys_data_bluetooth));
+        }
+        return viewHolder;
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        holder.itemView.setSelected(mSelectedPosition == position);
+        holder.mTextView.setText(mDevices.get(position).getDisplayName());
+        holder.itemView.setOnClickListener(v -> mListener.onItemClick(position));
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return isWifiDevice(position) ? TYPE_WIFI : TYPE_BT;
+    }
+
+    @Override
     public long getItemId(int position) {
         return position;
     }
 
     @Override
-    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
-        final View view = convertView != null
-                ? convertView
-                : LayoutInflater.from(mContext).inflate(R.layout.list_item_device, parent, false);
-
-        final DeviceFilterPair<?> item = getItem(position);
-        bindView(view, item);
-
-        return view;
+    public int getItemCount() {
+        return mDevices != null ? mDevices.size() : 0;
     }
 
-    private void bindView(@NonNull View view, DeviceFilterPair<?> item) {
-        final TextView textView = view.findViewById(android.R.id.text1);
-        textView.setText(item.getDisplayName());
-
-        final ImageView iconView = view.findViewById(android.R.id.icon);
-
-        // TODO(b/211417476): Set either Bluetooth or WiFi icon.
-        iconView.setVisibility(View.GONE);
-        // final int iconRes = isBt ? android.R.drawable.stat_sys_data_bluetooth
-        //        : com.android.internal.R.drawable.ic_wifi_signal_3;
-        // final Drawable icon = getTintedIcon(mResources, iconRes);
-        // iconView.setImageDrawable(icon);
+    public void setSelectedPosition(int position) {
+        mSelectedPosition = position;
     }
 
     @Override
@@ -89,4 +100,28 @@
         mDevices = deviceFilterPairs;
         notifyDataSetChanged();
     }
+
+    static class ViewHolder extends RecyclerView.ViewHolder {
+        private TextView mTextView;
+        private ImageView mImageView;
+        ViewHolder(View itemView) {
+            super(itemView);
+            mTextView = itemView.findViewById(android.R.id.text1);
+            mImageView = itemView.findViewById(android.R.id.icon);
+        }
+    }
+
+    private boolean isWifiDevice(int position) {
+        return mDevices.get(position).getDevice() instanceof android.net.wifi.ScanResult;
+    }
+
+    private Drawable getIcon(int resId) {
+        Drawable icon = mContext.getResources().getDrawable(resId, null);
+        icon.setTint(Color.DKGRAY);
+        return icon;
+    }
+
+    public interface OnItemClickListener {
+        void onItemClick(int position);
+    }
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index 1a955c4..72243f9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -146,7 +146,7 @@
          * @param iface the name of the interface.
          * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
          *              interface was removed.
-         * @param role whether the interface is in the client mode or server mode.
+         * @param role whether the interface is in client mode or server mode.
          * @param configuration the current IP configuration of the interface.
          * @hide
          */
diff --git a/packages/SettingsLib/ActivityEmbedding/Android.bp b/packages/SettingsLib/ActivityEmbedding/Android.bp
index fc82b79..2569198 100644
--- a/packages/SettingsLib/ActivityEmbedding/Android.bp
+++ b/packages/SettingsLib/ActivityEmbedding/Android.bp
@@ -14,6 +14,8 @@
 
     static_libs: [
         "androidx.annotation_annotation",
+        "androidx.core_core",
+        "windowExtLib",
         "SettingsLibUtils",
     ],
     sdk_version: "system_current",
diff --git a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
index 7f17d26..44b3b4e 100644
--- a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
+++ b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
@@ -16,8 +16,14 @@
 
 package com.android.settingslib.activityembedding;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import androidx.core.os.BuildCompat;
+import androidx.window.embedding.SplitController;
 
 import com.android.settingslib.utils.BuildCompatUtils;
 
@@ -44,6 +50,33 @@
         return false;
     }
 
+    /**
+     * Whether current activity is embedded in the Settings app or not.
+     */
+    public static boolean isActivityEmbedded(Activity activity) {
+        return SplitController.getInstance().isActivityEmbedded(activity);
+    }
+
+    /**
+     * Whether current activity is suggested to show back button or not.
+     */
+    public static boolean shouldHideBackButton(Activity activity, boolean isSecondaryLayerPage) {
+        if (!BuildCompat.isAtLeastT()) {
+            return false;
+        }
+        if (!isSecondaryLayerPage) {
+            return false;
+        }
+        final String shouldHideBackButton = Settings.Global.getString(activity.getContentResolver(),
+                "settings_hide_secondary_page_back_button_in_two_pane");
+
+        if (TextUtils.isEmpty(shouldHideBackButton)
+                || TextUtils.equals("true", shouldHideBackButton)) {
+            return isActivityEmbedded(activity);
+        }
+        return false;
+    }
+
     private ActivityEmbeddingUtils() {
     }
 }
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 684f4de..7a5ea47 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -48,7 +48,6 @@
         "SettingsLibCollapsingToolbarBaseActivity",
         "SettingsLibTwoTargetPreference",
         "SettingsLibSettingsTransition",
-        "SettingsLibActivityEmbedding",
         "SettingsLibButtonPreference",
         "setupdesign",
     ],
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 25d6c55..d893d09 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -22,8 +22,6 @@
     <!-- The translation for disappearing security views after having solved them. -->
     <dimen name="disappear_y_translation">-32dp</dimen>
 
-    <dimen name="circle_avatar_size">190dp</dimen>
-
     <!-- Height of a user icon view -->
     <dimen name="user_icon_view_height">24dp</dimen>
     <!-- User spinner -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 883e080..f6e3557 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -144,7 +144,7 @@
      * Returns a circular icon for a user.
      */
     public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
-        final int iconSize = UserIconDrawable.getSizeForList(context);
+        final int iconSize = UserIconDrawable.getDefaultSize(context);
         if (user.isManagedProfile()) {
             Drawable drawable = UserIconDrawable.getManagedUserDrawable(context);
             drawable.setBounds(0, 0, iconSize, iconSize);
diff --git a/packages/SettingsLib/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManager.java b/packages/SettingsLib/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManager.java
index fc38ada..afd3626 100644
--- a/packages/SettingsLib/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManager.java
@@ -22,7 +22,6 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -34,10 +33,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -52,12 +48,11 @@
     private static DeviceStateRotationLockSettingsManager sSingleton;
 
     private final ContentResolver mContentResolver;
+    private final String[] mDeviceStateRotationLockDefaults;
     private final Handler mMainHandler = Handler.getMain();
     private final Set<DeviceStateRotationLockSettingsListener> mListeners = new HashSet<>();
-    private String[] mDeviceStateRotationLockDefaults;
     private SparseIntArray mDeviceStateRotationLockSettings;
     private SparseIntArray mDeviceStateRotationLockFallbackSettings;
-    private List<SettableDeviceState> mSettableDeviceStates;
 
     private DeviceStateRotationLockSettingsManager(Context context) {
         mContentResolver = context.getContentResolver();
@@ -78,12 +73,6 @@
         return sSingleton;
     }
 
-    /** Resets the singleton instance of this class. Only used for testing. */
-    @VisibleForTesting
-    public static synchronized void resetInstance() {
-        sSingleton = null;
-    }
-
     /** Returns true if device-state based rotation lock settings are enabled. */
     public static boolean isDeviceStateRotationLockEnabled(Context context) {
         return context.getResources()
@@ -191,12 +180,6 @@
         return true;
     }
 
-    /** Returns a list of device states and their respective auto-rotation setting availability. */
-    public List<SettableDeviceState> getSettableDeviceStates() {
-        // Returning a copy to make sure that nothing outside can mutate our internal list.
-        return new ArrayList<>(mSettableDeviceStates);
-    }
-
     private void initializeInMemoryMap() {
         String serializedSetting =
                 Settings.Secure.getStringForUser(
@@ -232,17 +215,6 @@
         }
     }
 
-    /**
-     * Resets the state of the class and saved settings back to the default values provided by the
-     * resources config.
-     */
-    @VisibleForTesting
-    public void resetStateForTesting(Resources resources) {
-        mDeviceStateRotationLockDefaults =
-                resources.getStringArray(R.array.config_perDeviceStateRotationLockDefaults);
-        fallbackOnDefaults();
-    }
-
     private void fallbackOnDefaults() {
         loadDefaults();
         persistSettings();
@@ -279,7 +251,6 @@
     }
 
     private void loadDefaults() {
-        mSettableDeviceStates = new ArrayList<>(mDeviceStateRotationLockDefaults.length);
         mDeviceStateRotationLockSettings = new SparseIntArray(
                 mDeviceStateRotationLockDefaults.length);
         mDeviceStateRotationLockFallbackSettings = new SparseIntArray(1);
@@ -300,8 +271,6 @@
                                         + values.length);
                     }
                 }
-                boolean isSettable = rotationLockSetting != DEVICE_STATE_ROTATION_LOCK_IGNORED;
-                mSettableDeviceStates.add(new SettableDeviceState(deviceState, isSettable));
                 mDeviceStateRotationLockSettings.put(deviceState, rotationLockSetting);
             } catch (NumberFormatException e) {
                 Log.wtf(TAG, "Error parsing settings entry. Entry was: " + entry, e);
@@ -331,38 +300,4 @@
         /** Called whenever the settings have changed. */
         void onSettingsChanged();
     }
-
-    /** Represents a device state and whether it has an auto-rotation setting. */
-    public static class SettableDeviceState {
-        private final int mDeviceState;
-        private final boolean mIsSettable;
-
-        SettableDeviceState(int deviceState, boolean isSettable) {
-            mDeviceState = deviceState;
-            mIsSettable = isSettable;
-        }
-
-        /** Returns the device state associated with this object. */
-        public int getDeviceState() {
-            return mDeviceState;
-        }
-
-        /** Returns whether there is an auto-rotation setting for this device state. */
-        public boolean isSettable() {
-            return mIsSettable;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof SettableDeviceState)) return false;
-            SettableDeviceState that = (SettableDeviceState) o;
-            return mDeviceState == that.mDeviceState && mIsSettable == that.mIsSettable;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mDeviceState, mIsSettable);
-        }
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
index e5ea446..7db00f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
@@ -31,8 +31,6 @@
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 
-import com.android.settingslib.R;
-
 /**
  * Converts the user avatar icon to a circularly clipped one.
  * TODO: Move this to an internal framework class and share with the one in Keyguard.
@@ -49,9 +47,9 @@
 
     public static CircleFramedDrawable getInstance(Context context, Bitmap icon) {
         Resources res = context.getResources();
-        float iconSize = res.getDimension(R.dimen.circle_avatar_size);
+        int iconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.user_icon_size);
 
-        CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+        CircleFramedDrawable instance = new CircleFramedDrawable(icon, iconSize);
         return instance;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 035fafd..d01f2b4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -49,8 +49,6 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.core.os.BuildCompat;
 
-import com.android.settingslib.R;
-
 /**
  * Converts the user avatar icon to a circularly clipped one with an optional badge and frame
  */
@@ -120,8 +118,9 @@
      * @param context
      * @return size in pixels
      */
-    public static int getSizeForList(Context context) {
-        return (int) context.getResources().getDimension(R.dimen.circle_avatar_size);
+    public static int getDefaultSize(Context context) {
+        return context.getResources()
+                .getDimensionPixelSize(com.android.internal.R.dimen.user_icon_size);
     }
 
     public UserIconDrawable() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index f8bb38b..5862f60 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -16,19 +16,17 @@
 
 package com.android.settingslib.users;
 
-import android.annotation.NonNull;
 import android.app.Activity;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.util.Log;
 import android.widget.ImageView;
 
 import com.android.internal.util.UserIcons;
-import com.android.settingslib.R;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 import com.android.settingslib.utils.ThreadUtils;
 
@@ -114,10 +112,10 @@
     private void onDefaultIconSelected(int tintColor) {
         try {
             ThreadUtils.postOnBackgroundThread(() -> {
+                Resources res = mActivity.getResources();
                 Drawable drawable =
-                        UserIcons.getDefaultUserIconInColor(mActivity.getResources(), tintColor);
-                Bitmap bitmap = convertToBitmap(drawable,
-                        (int) mActivity.getResources().getDimension(R.dimen.circle_avatar_size));
+                        UserIcons.getDefaultUserIconInColor(res, tintColor);
+                Bitmap bitmap = UserIcons.convertToBitmapAtUserIconSize(res, drawable);
 
                 ThreadUtils.postOnMainThread(() -> onPhotoProcessed(bitmap));
             }).get();
@@ -126,14 +124,6 @@
         }
     }
 
-    private static Bitmap convertToBitmap(@NonNull Drawable icon, int size) {
-        Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
-        icon.setBounds(0, 0, size, size);
-        icon.draw(canvas);
-        return bitmap;
-    }
-
     private void onPhotoCropped(final Uri data) {
         ThreadUtils.postOnBackgroundThread(() -> {
             InputStream imageStream = null;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
deleted file mode 100644
index 8d687b6..0000000
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 com.android.settingslib.devicestate;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.R;
-import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager.SettableDeviceState;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class DeviceStateRotationLockSettingsManagerTest {
-
-    @Mock private Context mMockContext;
-    @Mock private Resources mMockResources;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        Context context = InstrumentationRegistry.getTargetContext();
-        when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
-        when(mMockContext.getResources()).thenReturn(mMockResources);
-        when(mMockContext.getContentResolver()).thenReturn(context.getContentResolver());
-    }
-
-    @Test
-    public void getSettableDeviceStates_returnsExpectedValuesInOriginalOrder() {
-        when(mMockResources.getStringArray(
-                R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
-                new String[]{"2:2", "4:0", "1:1", "0:0"});
-
-        List<SettableDeviceState> settableDeviceStates =
-                DeviceStateRotationLockSettingsManager.getInstance(
-                        mMockContext).getSettableDeviceStates();
-
-        assertThat(settableDeviceStates).containsExactly(
-                new SettableDeviceState(/* deviceState= */ 2, /* isSettable= */ true),
-                new SettableDeviceState(/* deviceState= */ 4, /* isSettable= */ false),
-                new SettableDeviceState(/* deviceState= */ 1, /* isSettable= */ true),
-                new SettableDeviceState(/* deviceState= */ 0, /* isSettable= */ false)
-        ).inOrder();
-    }
-}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 208825c..d8b050a 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -76,14 +76,14 @@
 
 enum class Style(internal val coreSpec: CoreSpec) {
     SPRITZ(CoreSpec(
-            a1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0)),
-            a2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0)),
-            a3 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0)),
+            a1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 12.0)),
+            a2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 8.0)),
+            a3 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 16.0)),
             n1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0)),
-            n2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0))
+            n2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 8.0))
     )),
     TONAL_SPOT(CoreSpec(
-            a1 = TonalSpec(chroma = Chroma(ChromaStrategy.GTE, 48.0)),
+            a1 = TonalSpec(chroma = Chroma(ChromaStrategy.GTE, 32.0)),
             a2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 16.0)),
             a3 = TonalSpec(Hue(HueStrategy.ADD, 60.0), Chroma(ChromaStrategy.EQ, 24.0)),
             n1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 4.0)),
@@ -91,17 +91,17 @@
     )),
     VIBRANT(CoreSpec(
             a1 = TonalSpec(chroma = Chroma(ChromaStrategy.GTE, 48.0)),
-            a2 = TonalSpec(Hue(HueStrategy.ADD, 10.0), Chroma(ChromaStrategy.EQ, 24.0)),
-            a3 = TonalSpec(Hue(HueStrategy.ADD, 20.0), Chroma(ChromaStrategy.GTE, 32.0)),
+            a2 = TonalSpec(Hue(HueStrategy.ADD, 15.0), Chroma(ChromaStrategy.EQ, 24.0)),
+            a3 = TonalSpec(Hue(HueStrategy.ADD, 30.0), Chroma(ChromaStrategy.GTE, 32.0)),
             n1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 8.0)),
             n2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 16.0))
     )),
     EXPRESSIVE(CoreSpec(
-            a1 = TonalSpec(Hue(HueStrategy.SUBTRACT, 40.0), Chroma(ChromaStrategy.GTE, 64.0)),
-            a2 = TonalSpec(Hue(HueStrategy.ADD, 20.0), Chroma(ChromaStrategy.EQ, 24.0)),
-            a3 = TonalSpec(Hue(HueStrategy.SUBTRACT, 80.0), Chroma(ChromaStrategy.GTE, 64.0)),
-            n1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 16.0)),
-            n2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 32.0))
+            a1 = TonalSpec(Hue(HueStrategy.SUBTRACT, 60.0), Chroma(ChromaStrategy.GTE, 64.0)),
+            a2 = TonalSpec(Hue(HueStrategy.SUBTRACT, 30.0), Chroma(ChromaStrategy.EQ, 24.0)),
+            a3 = TonalSpec(chroma = Chroma(ChromaStrategy.GTE, 48.0)),
+            n1 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 12.0)),
+            n2 = TonalSpec(chroma = Chroma(ChromaStrategy.EQ, 16.0))
     )),
     RAINBOW(CoreSpec(
             a1 = TonalSpec(chroma = Chroma(ChromaStrategy.GTE, 48.0)),
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index f982790..4a9a1f1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -263,22 +263,29 @@
         inoutInfo.touchableRegion.set(getTouchRegion(true));
     }
 
-    private Region getTouchRegion(boolean includeScrim) {
-        Region touchRegion = new Region();
+    private Region getSwipeRegion() {
+        Region swipeRegion = new Region();
 
         final Rect tmpRect = new Rect();
         mScreenshotPreview.getBoundsOnScreen(tmpRect);
         tmpRect.inset((int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
                 (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP));
-        touchRegion.op(tmpRect, Region.Op.UNION);
+        swipeRegion.op(tmpRect, Region.Op.UNION);
         mActionsContainerBackground.getBoundsOnScreen(tmpRect);
         tmpRect.inset((int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
                 (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP));
-        touchRegion.op(tmpRect, Region.Op.UNION);
+        swipeRegion.op(tmpRect, Region.Op.UNION);
         mDismissButton.getBoundsOnScreen(tmpRect);
-        touchRegion.op(tmpRect, Region.Op.UNION);
+        swipeRegion.op(tmpRect, Region.Op.UNION);
+
+        return swipeRegion;
+    }
+
+    private Region getTouchRegion(boolean includeScrim) {
+        Region touchRegion = getSwipeRegion();
 
         if (includeScrim && mScrollingScrim.getVisibility() == View.VISIBLE) {
+            final Rect tmpRect = new Rect();
             mScrollingScrim.getBoundsOnScreen(tmpRect);
             touchRegion.op(tmpRect, Region.Op.UNION);
         }
@@ -328,7 +335,7 @@
     @Override // ViewGroup
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         // scrolling scrim should not be swipeable; return early if we're on the scrim
-        if (!getTouchRegion(false).contains((int) ev.getRawX(), (int) ev.getRawY())) {
+        if (!getSwipeRegion().contains((int) ev.getRawX(), (int) ev.getRawY())) {
             return false;
         }
         // always pass through the down event so the swipe handler knows the initial state
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index b312ce2..8366bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -67,7 +67,7 @@
     wakefulnessLifecycle: WakefulnessLifecycle,
     configurationController: ConfigurationController,
     falsingManager: FalsingManager,
-    dumpManager: DumpManager,
+    dumpManager: DumpManager
 ) : Dumpable {
     private var pulseHeight: Float = 0f
     private var useSplitShade: Boolean = false
@@ -363,6 +363,7 @@
         notificationPanelController.setKeyguardOnlyContentAlpha(1.0f - scrimProgress)
         depthController.transitionToFullShadeProgress = scrimProgress
         udfpsKeyguardViewController?.setTransitionToFullShadeProgress(scrimProgress)
+        statusbar.setTransitionToFullShadeProgress(scrimProgress)
     }
 
     private fun setDragDownAmountAnimated(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8e4feb8..7736357 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -344,6 +344,7 @@
     private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
     private final DreamOverlayStateController mDreamOverlayStateController;
     private StatusBarCommandQueueCallbacks mCommandQueueCallbacks;
+    private float mTransitionToFullShadeProgress = 0f;
 
     void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
         updateBubblesVisibility();
@@ -3777,6 +3778,15 @@
         updateScrimController();
     }
 
+    /**
+     * Set the amount of progress we are currently in if we're transitioning to the full shade.
+     * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+     * shade.
+     */
+    public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) {
+        mTransitionToFullShadeProgress = transitionToFullShadeProgress;
+    }
+
     @VisibleForTesting
     public void updateScrimController() {
         Trace.beginSection("StatusBar#updateScrimController");
@@ -3795,7 +3805,8 @@
         mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
 
         if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
-            if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED) {
+            if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
+                    || mTransitionToFullShadeProgress > 0f) {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
             } else {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserCreator.java b/packages/SystemUI/src/com/android/systemui/user/UserCreator.java
index 3a270bb..0686071 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserCreator.java
+++ b/packages/SystemUI/src/com/android/systemui/user/UserCreator.java
@@ -19,6 +19,7 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.UserManager;
 
@@ -70,10 +71,12 @@
             }
 
             Drawable newUserIcon = userIcon;
+            Resources res = mContext.getResources();
             if (newUserIcon == null) {
-                newUserIcon = UserIcons.getDefaultUserIcon(mContext.getResources(), user.id, false);
+                newUserIcon = UserIcons.getDefaultUserIcon(res, user.id, false);
             }
-            mUserManager.setUserIcon(user.id, UserIcons.convertToBitmap(newUserIcon));
+            mUserManager.setUserIcon(
+                    user.id, UserIcons.convertToBitmapAtUserIconSize(res, newUserIcon));
 
             userCreationProgressDialog.dismiss();
             successCallback.accept(user);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
index 5a06048..6df56e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
@@ -19,6 +19,7 @@
 import android.app.WallpaperColors;
 import android.graphics.Color;
 import android.testing.AndroidTestingRunner;
+import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 
@@ -29,7 +30,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -108,7 +113,7 @@
                 Style.SPRITZ /* style */);
         int primaryMid = colorScheme.getAccent1().get(colorScheme.getAccent1().size() / 2);
         Cam cam = Cam.fromInt(primaryMid);
-        Assert.assertEquals(cam.getChroma(), 4.0, 1.0);
+        Assert.assertEquals(cam.getChroma(), 12.0, 1.0);
     }
 
     @Test
@@ -128,6 +133,41 @@
                 Style.EXPRESSIVE /* style */);
         int neutralMid = colorScheme.getNeutral1().get(colorScheme.getNeutral1().size() / 2);
         Cam cam = Cam.fromInt(neutralMid);
-        Assert.assertEquals(cam.getChroma(), 16.0, 1.0);
+        Assert.assertEquals(cam.getChroma(), 12.0, 1.0);
+    }
+
+    /**
+     * Generate xml for SystemPaletteTest#testThemeStyles().
+     */
+    @Test
+    public void generateThemeStyles() {
+        StringBuilder xml = new StringBuilder();
+        for (int hue = 0; hue < 360; hue += 60) {
+            final int sourceColor = Cam.getInt(hue, 50f, 50f);
+            final String sourceColorHex = Integer.toHexString(sourceColor);
+
+            xml.append("    <theme color=\"").append(sourceColorHex).append("\">\n");
+
+            for (Style style : Style.values()) {
+                String styleName = style.name().toLowerCase();
+                ColorScheme colorScheme = new ColorScheme(sourceColor, false, style);
+                xml.append("        <").append(styleName).append(">");
+
+                List<String> colors = new ArrayList<>();
+                for (Stream<Integer> stream: Arrays.asList(colorScheme.getAccent1().stream(),
+                        colorScheme.getAccent2().stream(),
+                        colorScheme.getAccent3().stream(),
+                        colorScheme.getNeutral1().stream(),
+                        colorScheme.getNeutral2().stream())) {
+                    colors.add("ffffff");
+                    colors.addAll(stream.map(Integer::toHexString).map(s -> s.substring(2)).collect(
+                            Collectors.toList()));
+                }
+                xml.append(String.join(",", colors));
+                xml.append("</").append(styleName).append(">\n");
+            }
+            xml.append("    </theme>\n");
+        }
+        Log.d("ColorSchemeXml", xml.toString());
     }
 }
diff --git a/services/Android.bp b/services/Android.bp
index e0ca8a6..2e4405f 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -54,7 +54,9 @@
         SYSTEM_OPTIMIZE_JAVA: {
             optimize: {
                 enabled: true,
-                optimize: true,
+                // TODO(b/210510433): Enable optimizations after improving
+                // retracing infra.
+                optimize: false,
                 shrink: true,
                 proguard_flags_files: ["proguard.flags"],
             },
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 76ee728..e0fa67f 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -103,7 +103,6 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.view.KeyEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillManager.SmartSuggestionMode;
@@ -367,8 +366,6 @@
     @Nullable
     private ClientSuggestionsSession mClientSuggestionsSession;
 
-    private final AccessibilityManager mAccessibilityManager;
-
     // TODO(b/216576510): Share one BroadcastReceiver between all Sessions instead of creating a
     // new one per Session.
     private final BroadcastReceiver mDelayedFillBroadcastReceiver =
@@ -518,10 +515,7 @@
                     return;
                 }
 
-                // If a11y touch exploration is enabled, then we do not send an inline fill request
-                // to the regular af service, because dropdown UI is easier to use.
-                if (mPendingInlineSuggestionsRequest.isServiceSupported()
-                        && !mAccessibilityManager.isTouchExplorationEnabled()) {
+                if (mPendingInlineSuggestionsRequest.isServiceSupported()) {
                     mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
                             mPendingFillRequest.getFillContexts(),
                             mPendingFillRequest.getClientState(),
@@ -1064,7 +1058,6 @@
         mRemoteFillService = serviceComponentName == null ? null
                 : new RemoteFillService(context, serviceComponentName, userId, this,
                         bindInstantServiceAllowed);
-        mAccessibilityManager = AccessibilityManager.getInstance(context);
         mActivityToken = activityToken;
         mHasCallback = hasCallback;
         mUiLatencyHistory = uiLatencyHistory;
diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
index be1bc79..c39b59a 100644
--- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java
+++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -120,6 +121,12 @@
             mBoundCompanionApplications.setValueForPackage(userId, packageName, serviceConnectors);
         }
 
+        if (serviceConnectors.isEmpty()) {
+            Slog.e(TAG, "Can't find CompanionDeviceService implementer in package: "
+                    + packageName + ". Please check if they are correctly declared.");
+            return;
+        }
+
         // The first connector in the list is always the primary connector: set a listener to it.
         serviceConnectors.get(0).setListener(this::onPrimaryServiceBindingDied);
 
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 9c8ed5a..efbc4de 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -3019,14 +3019,32 @@
         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
         intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
+
         // Send the broadcast twice -- once for all apps with READ_PHONE_STATE, then again
-        // for all apps with READ_PRIV but not READ_PHONE_STATE. This ensures that any app holding
-        // either READ_PRIV or READ_PHONE get this broadcast exactly once.
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.READ_PHONE_STATE);
-        mContext.createContextAsUser(UserHandle.ALL, 0)
-                .sendBroadcastMultiplePermissions(intent,
-                        new String[] { Manifest.permission.READ_PRIVILEGED_PHONE_STATE },
-                        new String[] { Manifest.permission.READ_PHONE_STATE });
+        // for all apps with READ_PRIVILEGED_PHONE_STATE but not READ_PHONE_STATE.
+        // Do this again twice, the first time for apps with ACCESS_FINE_LOCATION, then again with
+        // the location-sanitized service state for all apps without ACCESS_FINE_LOCATION.
+        // This ensures that any app holding either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE
+        // get this broadcast exactly once, and we are not exposing location without permission.
+        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
+                new String[] {Manifest.permission.READ_PHONE_STATE,
+                        Manifest.permission.ACCESS_FINE_LOCATION});
+        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
+                new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+                        Manifest.permission.ACCESS_FINE_LOCATION},
+                new String[] {Manifest.permission.READ_PHONE_STATE});
+
+        // Replace bundle with location-sanitized ServiceState
+        data = new Bundle();
+        state.createLocationInfoSanitizedCopy(true).fillInNotifierBundle(data);
+        intent.putExtras(data);
+        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
+                new String[] {Manifest.permission.READ_PHONE_STATE},
+                new String[] {Manifest.permission.ACCESS_FINE_LOCATION});
+        mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(intent,
+                new String[] {Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
+                new String[] {Manifest.permission.READ_PHONE_STATE,
+                        Manifest.permission.ACCESS_FINE_LOCATION});
     }
 
     private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId,
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 6c1a00d..97dd323 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -1018,6 +1018,7 @@
                         Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
                         0,
                         mService.mUserController.getCurrentUserId()) != 0;
+                final String packageName = proc.info.packageName;
                 final boolean crashSilenced = mAppsNotReportingCrashes != null
                         && mAppsNotReportingCrashes.contains(proc.info.packageName);
                 final long now = SystemClock.uptimeMillis();
@@ -1026,6 +1027,7 @@
                 if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
                         && !crashSilenced && !shouldThottle
                         && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
+                    Slog.i(TAG, "Showing crash dialog for package " + packageName + " u" + userId);
                     errState.getDialogController().showCrashDialogs(data);
                     if (!proc.isolated) {
                         mProcessCrashShowDialogTimes.put(proc.processName, proc.uid, now);
diff --git a/services/core/java/com/android/server/am/AppPermissionTracker.java b/services/core/java/com/android/server/am/AppPermissionTracker.java
index 7f48d52..69f70ca 100644
--- a/services/core/java/com/android/server/am/AppPermissionTracker.java
+++ b/services/core/java/com/android/server/am/AppPermissionTracker.java
@@ -64,6 +64,8 @@
     @GuardedBy("mLock")
     private SparseArray<ArraySet<String>> mUidGrantedPermissionsInMonitor = new SparseArray<>();
 
+    private volatile boolean mLockedBootCompleted = false;
+
     AppPermissionTracker(Context context, AppRestrictionController controller) {
         this(context, controller, null, null);
     }
@@ -85,20 +87,20 @@
         final PackageManagerInternal pmi = mInjector.getPackageManagerInternal();
         final PermissionManagerServiceInternal pm = mInjector.getPermissionManagerServiceInternal();
         final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
+        final SparseArray<ArraySet<String>> uidPerms = mUidGrantedPermissionsInMonitor;
         for (int userId : allUsers) {
             final List<ApplicationInfo> apps = pmi.getInstalledApplications(0, userId, SYSTEM_UID);
             if (apps == null) {
                 continue;
             }
-            synchronized (mLock) {
-                final SparseArray<ArraySet<String>> uidPerms = mUidGrantedPermissionsInMonitor;
-                final long now = SystemClock.elapsedRealtime();
-                for (int i = 0, size = apps.size(); i < size; i++) {
-                    final ApplicationInfo ai = apps.get(i);
-                    for (String permission : permissions) {
-                        if (pm.checkUidPermission(ai.uid, permission) != PERMISSION_GRANTED) {
-                            continue;
-                        }
+            final long now = SystemClock.elapsedRealtime();
+            for (int i = 0, size = apps.size(); i < size; i++) {
+                final ApplicationInfo ai = apps.get(i);
+                for (String permission : permissions) {
+                    if (pm.checkUidPermission(ai.uid, permission) != PERMISSION_GRANTED) {
+                        continue;
+                    }
+                    synchronized (mLock) {
                         ArraySet<String> grantedPermissions = uidPerms.get(ai.uid);
                         if (grantedPermissions == null) {
                             grantedPermissions = new ArraySet<String>();
@@ -132,25 +134,30 @@
     private void handlePermissionsChanged(int uid) {
         final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
         if (permissions != null && permissions.length > 0) {
+            final PermissionManagerServiceInternal pm =
+                    mInjector.getPermissionManagerServiceInternal();
+            final boolean[] states = new boolean[permissions.length];
+            for (int i = 0; i < permissions.length; i++) {
+                states[i] = pm.checkUidPermission(uid, permissions[i]) == PERMISSION_GRANTED;
+                if (DEBUG_PERMISSION_TRACKER) {
+                    Slog.i(TAG, UserHandle.formatUid(uid) + " " + permissions[i] + "=" + states[i]);
+                }
+            }
             synchronized (mLock) {
-                handlePermissionsChangedLocked(uid);
+                handlePermissionsChangedLocked(uid, permissions, states);
             }
         }
     }
 
     @GuardedBy("mLock")
-    private void handlePermissionsChangedLocked(int uid) {
-        final PermissionManagerServiceInternal pm = mInjector.getPermissionManagerServiceInternal();
+    private void handlePermissionsChangedLocked(int uid, String[] permissions, boolean[] states) {
         final int index = mUidGrantedPermissionsInMonitor.indexOfKey(uid);
         ArraySet<String> grantedPermissions = index >= 0
                 ? mUidGrantedPermissionsInMonitor.valueAt(index) : null;
-        final String[] permissions = mInjector.getPolicy().getBgPermissionsInMonitor();
         final long now = SystemClock.elapsedRealtime();
-        for (String permission: permissions) {
-            boolean granted = pm.checkUidPermission(uid, permission) == PERMISSION_GRANTED;
-            if (DEBUG_PERMISSION_TRACKER) {
-                Slog.i(TAG, UserHandle.formatUid(uid) + " " + permission + "=" + granted);
-            }
+        for (int i = 0; i < permissions.length; i++) {
+            final String permission = permissions[i];
+            final boolean granted = states[i];
             boolean changed = false;
             if (granted) {
                 if (grantedPermissions == null) {
@@ -200,6 +207,10 @@
     }
 
     private void onPermissionTrackerEnabled(boolean enabled) {
+        if (!mLockedBootCompleted) {
+            // Not ready, bail out.
+            return;
+        }
         final PermissionManager pm = mInjector.getPermissionManager();
         if (enabled) {
             pm.addOnPermissionsChangeListener(this);
@@ -211,6 +222,12 @@
     }
 
     @Override
+    void onLockedBootCompleted() {
+        mLockedBootCompleted = true;
+        onPermissionTrackerEnabled(mInjector.getPolicy().isEnabled());
+    }
+
+    @Override
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix);
         pw.println("APP PERMISSIONS TRACKER:");
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 1129c19..2ffd487 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -71,6 +71,7 @@
 import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
 import static android.os.PowerExemptionManager.reasonCodeToString;
 import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 
 import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
@@ -792,7 +793,7 @@
         mInjector = injector;
         mContext = injector.getContext();
         mActivityManagerService = service;
-        mBgHandlerThread = new HandlerThread("bgres-controller");
+        mBgHandlerThread = new HandlerThread("bgres-controller", THREAD_PRIORITY_BACKGROUND);
         mBgHandlerThread.start();
         mBgHandler = new BgHandler(mBgHandlerThread.getLooper(), injector);
         mBgExecutor = new HandlerExecutor(mBgHandler);
@@ -816,9 +817,11 @@
         mInjector.getAppStandbyInternal().addListener(mAppIdleStateChangeListener);
         mInjector.getRoleManager().addOnRoleHoldersChangedListenerAsUser(mBgExecutor,
                 mRoleHolderChangedListener, UserHandle.ALL);
-        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
-            mAppStateTrackers.get(i).onSystemReady();
-        }
+        mInjector.scheduleInitTrackers(mBgHandler, () -> {
+            for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
+                mAppStateTrackers.get(i).onSystemReady();
+            }
+        });
     }
 
     @VisibleForTesting
@@ -2137,6 +2140,10 @@
             }
             return null;
         }
+
+        void scheduleInitTrackers(Handler handler, Runnable initializers) {
+            handler.post(initializers);
+        }
     }
 
     private void registerForSystemBroadcasts() {
@@ -2221,6 +2228,21 @@
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
         userFilter.addAction(Intent.ACTION_UID_REMOVED);
         mContext.registerReceiverForAllUsers(broadcastReceiver, userFilter, null, mBgHandler);
+        final BroadcastReceiver bootReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final String action = intent.getAction();
+                switch (intent.getAction()) {
+                    case Intent.ACTION_LOCKED_BOOT_COMPLETED: {
+                        onLockedBootCompleted();
+                    } break;
+                }
+            }
+        };
+        final IntentFilter bootFilter = new IntentFilter();
+        bootFilter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+        mContext.registerReceiverAsUser(bootReceiver, UserHandle.SYSTEM,
+                bootFilter, null, mBgHandler);
     }
 
     void forEachTracker(Consumer<BaseAppStateTracker> sink) {
@@ -2275,6 +2297,12 @@
         mRestrictionSettings.removeUid(uid);
     }
 
+    private void onLockedBootCompleted() {
+        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
+            mAppStateTrackers.get(i).onLockedBootCompleted();
+        }
+    }
+
     boolean isBgAutoRestrictedBucketFeatureFlagEnabled() {
         return mConstantsObserver.mBgAutoRestrictedBucket;
     }
diff --git a/services/core/java/com/android/server/am/BaseAppStateTracker.java b/services/core/java/com/android/server/am/BaseAppStateTracker.java
index 482d697..0fada53 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTracker.java
@@ -204,6 +204,12 @@
     }
 
     /**
+     * Called when the system sends LOCKED_BOOT_COMPLETED.
+     */
+    void onLockedBootCompleted() {
+    }
+
+    /**
      * Called when a device config property in the activity manager namespace
      * has changed.
      */
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 9929ed7..86ca699 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1115,6 +1115,9 @@
                     int lastOomAdj = msg.arg1;
                     int procState = msg.arg2;
                     synchronized (mProcLock) {
+                        if(mPendingCompactionProcesses.isEmpty()) {
+                            return;
+                        }
                         proc = mPendingCompactionProcesses.remove(0);
                         opt = proc.mOptRecord;
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 807293f..0b9fb1a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3330,6 +3330,13 @@
         }
     }
 
+    private void enforceAccessUltrasoundPermission() {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_ULTRASOUND)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Missing ACCESS_ULTRASOUND permission");
+        }
+    }
+
     private void enforceQueryStatePermission() {
         if (mContext.checkCallingOrSelfPermission(Manifest.permission.QUERY_AUDIO_STATE)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -3462,6 +3469,12 @@
                 attributionTag, Binder.getCallingUid(), callingOrSelfHasAudioSettingsPermission());
     }
 
+    /** @see AudioManager#isUltrasoundSupported() */
+    public boolean isUltrasoundSupported() {
+        enforceAccessUltrasoundPermission();
+        return AudioSystem.isUltrasoundSupported();
+    }
+
     private boolean canChangeAccessibilityVolume() {
         synchronized (mAccessibilityServiceUidsLock) {
             if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2c2a2bf..17215e5 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -131,6 +131,7 @@
     private static final int MSG_STOP_SENSOR_LISTENER = 2;
     private static final int MSG_START_SENSOR_LISTENER = 3;
     private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+    private static final int MSG_SENSOR_CHANGED = 5;
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
@@ -158,6 +159,7 @@
     // These members should only be accessed on the mBgHandler thread.
     private BroadcastReceiver mBroadcastReceiver;
     private SensorListener mSensorListener;
+    private Sensor mLightSensor;
     private SettingsObserver mSettingsObserver;
     private DisplayListener mDisplayListener;
     private boolean mSensorRegistered;
@@ -327,6 +329,14 @@
         m.sendToTarget();
     }
 
+    /**
+     * Updates the light sensor to use.
+     */
+    public void setLightSensor(Sensor lightSensor) {
+        mBgHandler.obtainMessage(MSG_SENSOR_CHANGED, 0 /*unused*/, 0/*unused*/, lightSensor)
+                .sendToTarget();
+    }
+
     private void handleBrightnessChanged(float brightness, boolean userInitiated,
             float powerBrightnessFactor, boolean isUserSetBrightness,
             boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) {
@@ -428,13 +438,28 @@
         }
     }
 
+    private void handleSensorChanged(Sensor lightSensor) {
+        if (mLightSensor != lightSensor) {
+            mLightSensor = lightSensor;
+            stopSensorListener();
+            synchronized (mDataCollectionLock) {
+                mLastSensorReadings.clear();
+            }
+            // Attempt to restart the sensor listener. It will check to see if it should be running
+            // so there is no need to also check here.
+            startSensorListener();
+        }
+    }
+
     private void startSensorListener() {
         if (!mSensorRegistered
+                && mLightSensor != null
+                && mAmbientBrightnessStatsTracker != null
                 && mInjector.isInteractive(mContext)
                 && mInjector.isBrightnessModeAutomatic(mContentResolver)) {
             mAmbientBrightnessStatsTracker.start();
             mSensorRegistered = true;
-            mInjector.registerSensorListener(mContext, mSensorListener,
+            mInjector.registerSensorListener(mContext, mSensorListener, mLightSensor,
                     mInjector.getBackgroundHandler());
         }
     }
@@ -736,6 +761,7 @@
         pw.println("BrightnessTracker state:");
         synchronized (mDataCollectionLock) {
             pw.println("  mStarted=" + mStarted);
+            pw.println("  mLightSensor=" + mLightSensor);
             pw.println("  mLastBatteryLevel=" + mLastBatteryLevel);
             pw.println("  mLastBrightness=" + mLastBrightness);
             pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
@@ -1017,6 +1043,9 @@
                         disableColorSampling();
                     }
                     break;
+                case MSG_SENSOR_CHANGED:
+                    handleSensorChanged((Sensor) msg.obj);
+                    break;
 
             }
         }
@@ -1045,9 +1074,8 @@
     @VisibleForTesting
     static class Injector {
         public void registerSensorListener(Context context,
-                SensorEventListener sensorListener, Handler handler) {
+                SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
             SensorManager sensorManager = context.getSystemService(SensorManager.class);
-            Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
             sensorManager.registerListener(sensorListener,
                     lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler);
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 418e91d..9067f2e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -826,7 +826,6 @@
     private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
         // All properties that depend on the associated DisplayDevice and the DDC must be
         // updated here.
-        loadAmbientLightSensor();
         loadBrightnessRampRates();
         loadProximitySensor();
         loadNitsRange(mContext.getResources());
@@ -972,6 +971,9 @@
             }
 
             loadAmbientLightSensor();
+            if (mBrightnessTracker != null) {
+                mBrightnessTracker.setLightSensor(mLightSensor);
+            }
 
             if (mAutomaticBrightnessController != null) {
                 mAutomaticBrightnessController.stop();
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7068ed1..0b7e391 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -130,6 +130,7 @@
 import android.view.WindowManager.DisplayImePolicy;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.accessibility.AccessibilityManager;
 import android.view.autofill.AutofillId;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InlineSuggestionsRequest;
@@ -287,6 +288,9 @@
     private final InputMethodMenuController mMenuController;
     private final InputMethodBindingController mBindingController;
 
+    // TODO(b/219056452): Use AccessibilityManagerInternal instead.
+    private final AccessibilityManager mAccessibilityManager;
+
     /**
      * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
      *
@@ -1627,6 +1631,7 @@
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mUserManager = mContext.getSystemService(UserManager.class);
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+        mAccessibilityManager = AccessibilityManager.getInstance(context);
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_INPUT_METHODS);
         mPlatformCompat = IPlatformCompat.Stub.asInterface(
@@ -1995,12 +2000,13 @@
 
     @GuardedBy("ImfLock.class")
     private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId,
-            InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) {
+            InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback,
+            boolean touchExplorationEnabled) {
         final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked());
         try {
             IInputMethodInvoker curMethod = getCurMethodLocked();
-            if (userId == mSettings.getCurrentUserId() && imi != null
-                    && imi.isInlineSuggestionsEnabled() && curMethod != null) {
+            if (userId == mSettings.getCurrentUserId() && curMethod != null
+                    && imi != null && isInlineSuggestionsEnabled(imi, touchExplorationEnabled)) {
                 final IInlineSuggestionsRequestCallback callbackImpl =
                         new InlineSuggestionsRequestCallbackDecorator(callback,
                                 imi.getPackageName(), mCurTokenDisplayId, getCurTokenLocked(),
@@ -2014,6 +2020,13 @@
         }
     }
 
+    private static boolean isInlineSuggestionsEnabled(InputMethodInfo imi,
+            boolean touchExplorationEnabled) {
+        return imi.isInlineSuggestionsEnabled()
+                && (!touchExplorationEnabled
+                    || imi.supportsInlineSuggestionsWithTouchExploration());
+    }
+
     /**
      * The decorator which validates the host package name in the
      * {@link InlineSuggestionsRequest} argument to make sure it matches the IME package name.
@@ -5197,8 +5210,12 @@
         @Override
         public void onCreateInlineSuggestionsRequest(@UserIdInt int userId,
                 InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb) {
+            // Get the device global touch exploration state before lock to avoid deadlock.
+            boolean touchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
+
             synchronized (ImfLock.class) {
-                onCreateInlineSuggestionsRequestLocked(userId, requestInfo, cb);
+                onCreateInlineSuggestionsRequestLocked(userId, requestInfo, cb,
+                        touchExplorationEnabled);
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 39ee0f4..9b10058 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -40,6 +40,7 @@
 import android.os.ServiceManager;
 import android.os.Trace;
 import android.sysprop.ApexProperties;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.PrintWriterPrinter;
@@ -608,18 +609,21 @@
                             continue;
                         }
 
-                        String name = service.getName();
-                        for (ApexSystemServiceInfo info : mApexSystemServices) {
-                            if (info.getName().equals(name)) {
-                                throw new IllegalStateException(String.format(
-                                        "Duplicate apex-system-service %s from %s, %s",
-                                        name, info.mJarPath, service.getJarPath()));
+                        if (ai.isActive) {
+                            String name = service.getName();
+                            for (int j = 0; j < mApexSystemServices.size(); j++) {
+                                ApexSystemServiceInfo info = mApexSystemServices.get(j);
+                                if (info.getName().equals(name)) {
+                                    throw new IllegalStateException(TextUtils.formatSimple(
+                                            "Duplicate apex-system-service %s from %s, %s", name,
+                                            info.mJarPath, service.getJarPath()));
+                                }
                             }
+                            ApexSystemServiceInfo info = new ApexSystemServiceInfo(
+                                    service.getName(), service.getJarPath(),
+                                    service.getInitOrder());
+                            mApexSystemServices.add(info);
                         }
-
-                        ApexSystemServiceInfo info = new ApexSystemServiceInfo(
-                                service.getName(), service.getJarPath(), service.getInitOrder());
-                        mApexSystemServices.add(info);
                     }
                     Collections.sort(mApexSystemServices);
                     mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8a105dd..70a030d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2684,8 +2684,8 @@
     @GuardedBy("mLock")
     private void updateUserActivitySummaryLocked(long now, int dirty) {
         // Update the status of the user activity timeout timer.
-        if ((dirty & (DIRTY_DISPLAY_GROUP_WAKEFULNESS | DIRTY_WAKE_LOCKS
-                | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) == 0) {
+        if ((dirty & (DIRTY_DISPLAY_GROUP_WAKEFULNESS | DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
+                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS | DIRTY_ATTENTIVE)) == 0) {
             return;
         }
         mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
@@ -2772,6 +2772,11 @@
                             screenDimDuration);
                 }
 
+                if (isAttentiveTimeoutExpired(powerGroup, now)) {
+                    groupUserActivitySummary = 0;
+                    groupNextTimeout = -1;
+                }
+
                 hasUserActivitySummary |= groupUserActivitySummary != 0;
 
                 if (nextTimeout == -1) {
@@ -3127,7 +3132,7 @@
                     Message msg = mHandler.obtainMessage(MSG_SANDMAN);
                     msg.arg1 = powerGroup.getGroupId();
                     msg.setAsynchronous(true);
-                    mHandler.sendMessage(msg);
+                    mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 87ba859..d84d724 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -628,6 +628,10 @@
     // it references to gets removed. This should also be cleared when we move out of pip.
     private Task mLastParentBeforePip;
 
+    // Only set if this instance is a launch-into-pip Activity, points to the
+    // host Activity the launch-into-pip Activity is originated from.
+    private ActivityRecord mLaunchIntoPipHostActivity;
+
     boolean firstWindowDrawn;
     /** Whether the visible window(s) of this activity is drawn. */
     private boolean mReportedDrawn;
@@ -1225,6 +1229,9 @@
         if (mLastParentBeforePip != null) {
             pw.println(prefix + "lastParentTaskIdBeforePip=" + mLastParentBeforePip.mTaskId);
         }
+        if (mLaunchIntoPipHostActivity != null) {
+            pw.println(prefix + "launchIntoPipHostActivity=" + mLaunchIntoPipHostActivity);
+        }
 
         mLetterboxUiController.dump(pw, prefix);
 
@@ -1559,10 +1566,16 @@
     /**
      * Sets {@link #mLastParentBeforePip} to the current parent Task, it's caller's job to ensure
      * {@link #getTask()} is set before this is called.
+     *
+     * @param launchIntoPipHostActivity {@link ActivityRecord} as the host Activity for the
+     *        launch-int-pip Activity see also {@link #mLaunchIntoPipHostActivity}.
      */
-    void setLastParentBeforePip() {
-        mLastParentBeforePip = getTask();
+    void setLastParentBeforePip(@Nullable ActivityRecord launchIntoPipHostActivity) {
+        mLastParentBeforePip = (launchIntoPipHostActivity == null)
+                ? getTask()
+                : launchIntoPipHostActivity.getTask();
         mLastParentBeforePip.mChildPipActivity = this;
+        mLaunchIntoPipHostActivity = launchIntoPipHostActivity;
     }
 
     private void clearLastParentBeforePip() {
@@ -1570,12 +1583,17 @@
             mLastParentBeforePip.mChildPipActivity = null;
             mLastParentBeforePip = null;
         }
+        mLaunchIntoPipHostActivity = null;
     }
 
     @Nullable Task getLastParentBeforePip() {
         return mLastParentBeforePip;
     }
 
+    @Nullable ActivityRecord getLaunchIntoPipHostActivity() {
+        return mLaunchIntoPipHostActivity;
+    }
+
     private void updateColorTransform() {
         if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
             getPendingTransaction().setColorTransform(mSurfaceControl,
@@ -1856,6 +1874,10 @@
                 mRotationAnimationHint = rotationAnimation;
             }
 
+            if (options.getLaunchIntoPipParams() != null) {
+                pictureInPictureArgs = options.getLaunchIntoPipParams();
+            }
+
             mOverrideTaskTransition = options.getOverrideTaskTransition();
         }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 5ffe214..ef0ee12 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1896,6 +1896,14 @@
         mSupervisor.handleNonResizableTaskIfNeeded(startedTask,
                 mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);
 
+        // If Activity's launching into PiP, move the mStartActivity immediately to pinned mode.
+        // Note that mStartActivity and source should be in the same Task at this point.
+        if (mOptions != null && mOptions.isLaunchIntoPip()
+                && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask()) {
+            mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity,
+                    sourceRecord, "launch-into-pip");
+        }
+
         return START_SUCCESS;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 1741d0f..0497477 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3538,8 +3538,8 @@
                 final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
                 final float expandedAspectRatio = r.pictureInPictureArgs.getExpandedAspectRatio();
                 final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
-                mRootWindowContainer.moveActivityToPinnedRootTask(
-                        r, "enterPictureInPictureMode");
+                mRootWindowContainer.moveActivityToPinnedRootTask(r,
+                        null /* launchIntoPipHostActivity */, "enterPictureInPictureMode");
                 final Task task = r.getTask();
                 task.setPictureInPictureAspectRatio(aspectRatio, expandedAspectRatio);
                 task.setPictureInPictureActions(actions);
@@ -3922,11 +3922,11 @@
     @Override
     public void onPictureInPictureStateChanged(PictureInPictureUiState pipState) {
         enforceTaskPermission("onPictureInPictureStateChanged");
-        final Task rootPinnedStask = mRootWindowContainer.getDefaultTaskDisplayArea()
+        final Task rootPinnedTask = mRootWindowContainer.getDefaultTaskDisplayArea()
                 .getRootPinnedTask();
-        if (rootPinnedStask != null && rootPinnedStask.getTopMostActivity() != null) {
+        if (rootPinnedTask != null && rootPinnedTask.getTopMostActivity() != null) {
             mWindowManager.mAtmService.mActivityClientController.onPictureInPictureStateChanged(
-                    rootPinnedStask.getTopMostActivity(), pipState);
+                    rootPinnedTask.getTopMostActivity(), pipState);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 33b807b..9893f68 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -106,12 +106,6 @@
         synchronized (task.mWmService.mGlobalLock) {
             activityRecord = task.topRunningActivity();
 
-            if(!activityRecord.info.applicationInfo.isOnBackInvokedCallbackEnabled()) {
-                ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Activity %s: enableOnBackInvokedCallback=false."
-                        + " Returning null BackNavigationInfo.", activityRecord.getName());
-                return null;
-            }
-
             removedWindowContainer = activityRecord;
             taskWindowConfiguration = task.getTaskInfo().configuration.windowConfiguration;
             WindowState window = task.getWindow(WindowState::isFocused);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e845034..2a06d8b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6441,6 +6441,8 @@
 
         @Override
         public void onAppTransitionCancelledLocked(boolean keyguardGoingAway) {
+            // It is only needed when freezing display in legacy transition.
+            if (mTransitionController.isShellTransitionsEnabled()) return;
             continueUpdateOrientationForDiffOrienLaunchingApp();
         }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d535018..8ab2ee0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1979,7 +1979,8 @@
                 onTop);
     }
 
-    void moveActivityToPinnedRootTask(ActivityRecord r, String reason) {
+    void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
+            @Nullable ActivityRecord launchIntoPipHostActivity, String reason) {
         mService.deferWindowLayout();
 
         final TaskDisplayArea taskDisplayArea = r.getDisplayArea();
@@ -2030,7 +2031,7 @@
                         .setHasBeenVisible(true)
                         .build();
                 // Establish bi-directional link between the original and pinned task.
-                r.setLastParentBeforePip();
+                r.setLastParentBeforePip(launchIntoPipHostActivity);
                 // It's possible the task entering PIP is in freeform, so save the last
                 // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
                 // to its previous freeform bounds.
@@ -2091,6 +2092,10 @@
             r.setWindowingMode(intermediateWindowingMode);
             r.mWaitForEnteringPinnedMode = true;
             rootTask.setWindowingMode(WINDOWING_MODE_PINNED);
+            // Set the launch bounds for launch-into-pip Activity on the root task.
+            if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) {
+                rootTask.setBounds(r.getOptions().getLaunchBounds());
+            }
             rootTask.setDeferTaskAppear(false);
 
             // Reset the state that indicates it can enter PiP while pausing after we've moved it
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 58cf4bb..e985e7a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3398,6 +3398,12 @@
 
         info.pictureInPictureParams = getPictureInPictureParams(top);
         info.preferDockBigOverlays = getPreferDockBigOverlays();
+        if (info.pictureInPictureParams != null
+                && info.pictureInPictureParams.isLaunchIntoPip()
+                && top.getTopMostActivity().getLastParentBeforePip() != null) {
+            info.launchIntoPipHostTaskId =
+                    top.getTopMostActivity().getLastParentBeforePip().mTaskId;
+        }
         info.displayCutoutInsets = top != null ? top.getDisplayCutoutInsets() : null;
         info.topActivityInfo = mReuseActivitiesReport.top != null
                 ? mReuseActivitiesReport.top.info
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index dd1f29e..7fab94c 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -31,6 +31,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.os.Process.INVALID_UID;
+import static android.os.Process.SYSTEM_UID;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -82,6 +83,7 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
@@ -530,6 +532,11 @@
      * certificate.</li>
      */
     private boolean isAllowedToEmbedActivityInTrustedMode(@NonNull ActivityRecord a) {
+        if (UserHandle.getAppId(mTaskFragmentOrganizerUid) == SYSTEM_UID) {
+            // The system is trusted to embed other apps securely and for all users.
+            return true;
+        }
+
         if (mTaskFragmentOrganizerUid == a.getUid()) {
             // Activities from the same UID can be embedded freely by the host.
             return true;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 9f2188b..cbef60c 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -550,10 +550,10 @@
             throw new IllegalStateException("Too late to abort.");
         }
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Aborting Transition: %d", mSyncId);
-        mController.dispatchLegacyAppTransitionCancelled();
         mState = STATE_ABORT;
         // Syncengine abort will call through to onTransactionReady()
         mSyncEngine.abort(mSyncId);
+        mController.dispatchLegacyAppTransitionCancelled();
     }
 
     void setRemoteTransition(RemoteTransition remoteTransition) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index 936940f..e6bb0ce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -2648,6 +2648,11 @@
         AppPermissionTracker getAppPermissionTracker() {
             return mAppPermissionTracker;
         }
+
+        @Override
+        void scheduleInitTrackers(Handler handler, Runnable initializers) {
+            initializers.run();
+        }
     }
 
     private class TestBaseTrackerInjector<T extends BaseAppStatePolicy>
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index bdf94f3..356600d 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -33,6 +33,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
 import android.database.ContentObserver;
+import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.display.AmbientBrightnessDayStats;
@@ -42,6 +43,7 @@
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.input.InputSensorInfo;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -63,6 +65,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -84,8 +88,11 @@
     private static final String DEFAULT_DISPLAY_ID = "123";
     private static final float FLOAT_DELTA = 0.01f;
 
+    @Mock private InputSensorInfo mInputSensorInfoMock;
+
     private BrightnessTracker mTracker;
     private TestInjector mInjector;
+    private Sensor mLightSensorFake;
 
     private static Object sHandlerLock = new Object();
     private static Handler sHandler;
@@ -108,9 +115,12 @@
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
         mInjector = new TestInjector(ensureHandler());
+        mLightSensorFake = new Sensor(mInputSensorInfoMock);
 
         mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector);
+        mTracker.setLightSensor(mLightSensorFake);
         mDefaultNightModeColorTemperature =
                 InstrumentationRegistry.getContext().getResources().getInteger(
                 R.integer.config_nightDisplayColorTemperatureDefault);
@@ -834,6 +844,47 @@
         mTracker.stop();
     }
 
+    @Test
+    public void testLightSensorChange() {
+        // verify the tracker started correctly and a listener registered
+        startTracker(mTracker);
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+        // Setting the sensor to null should stop the registered listener.
+        mTracker.setLightSensor(null);
+        mInjector.waitForHandler();
+        assertNull(mInjector.mSensorListener);
+        assertNull(mInjector.mLightSensor);
+
+        // Resetting sensor should start listener again
+        mTracker.setLightSensor(mLightSensorFake);
+        mInjector.waitForHandler();
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+        Sensor secondSensor = new Sensor(mInputSensorInfoMock);
+        // Setting a different listener should keep things working
+        mTracker.setLightSensor(secondSensor);
+        mInjector.waitForHandler();
+        assertNotNull(mInjector.mSensorListener);
+        assertEquals(mInjector.mLightSensor, secondSensor);
+    }
+
+    @Test
+    public void testSetLightSensorDoesntStartListener() {
+        mTracker.setLightSensor(mLightSensorFake);
+        assertNull(mInjector.mSensorListener);
+    }
+
+    @Test
+    public void testNullLightSensorWontRegister() {
+        mTracker.setLightSensor(null);
+        startTracker(mTracker);
+        assertNull(mInjector.mSensorListener);
+        assertNull(mInjector.mLightSensor);
+    }
+
     private InputStream getInputStream(String data) {
         return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
     }
@@ -924,6 +975,7 @@
 
     private class TestInjector extends BrightnessTracker.Injector {
         SensorEventListener mSensorListener;
+        Sensor mLightSensor;
         BroadcastReceiver mBroadcastReceiver;
         DisplayManager.DisplayListener mDisplayListener;
         Map<String, Integer> mSecureIntSettings = new HashMap<>();
@@ -974,14 +1026,16 @@
 
         @Override
         public void registerSensorListener(Context context,
-                SensorEventListener sensorListener, Handler handler) {
+                SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
             mSensorListener = sensorListener;
+            mLightSensor = lightSensor;
         }
 
         @Override
         public void unregisterSensorListener(Context context,
                 SensorEventListener sensorListener) {
             mSensorListener = null;
+            mLightSensor = null;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 2f5993d1..5d3da43 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -132,7 +132,12 @@
 
     @Test
     public void testGetApexSystemServices() throws RemoteException {
-        when(mApexService.getAllPackages()).thenReturn(createApexInfoForTestPkg(true, false));
+        when(mApexService.getAllPackages()).thenReturn(new ApexInfo[] {
+                createApexInfoForTestPkg(false, true, 1),
+                // only active apex reports apex-system-service
+                createApexInfoForTestPkg(true, false, 2),
+        });
+
         mApexManager.scanApexPackagesTraced(mPackageParser2,
                 ParallelPackageParser.makeExecutorService());
 
@@ -484,17 +489,20 @@
         assertThat(e).hasMessageThat().contains("Failed to collect certificates from ");
     }
 
-    private ApexInfo[] createApexInfoForTestPkg(boolean isActive, boolean isFactory) {
+    private ApexInfo createApexInfoForTestPkg(boolean isActive, boolean isFactory, int version) {
         File apexFile = extractResource(TEST_APEX_PKG,  TEST_APEX_FILE_NAME);
         ApexInfo apexInfo = new ApexInfo();
         apexInfo.isActive = isActive;
         apexInfo.isFactory = isFactory;
         apexInfo.moduleName = TEST_APEX_PKG;
         apexInfo.modulePath = apexFile.getPath();
-        apexInfo.versionCode = 191000070;
+        apexInfo.versionCode = version;
         apexInfo.preinstalledModulePath = apexFile.getPath();
+        return apexInfo;
+    }
 
-        return new ApexInfo[]{apexInfo};
+    private ApexInfo[] createApexInfoForTestPkg(boolean isActive, boolean isFactory) {
+        return new ApexInfo[]{createApexInfoForTestPkg(isActive, isFactory, 191000070)};
     }
 
     private ApexInfo createApexInfo(String moduleName, int versionCode, boolean isActive,
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index c94168c..ed7aac7 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -1058,6 +1058,23 @@
         assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_ASLEEP);
     }
 
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testInattentiveSleep_goesToSleepFromDream() throws Exception {
+        setAttentiveTimeout(20000);
+        createService();
+        startSystem();
+        setPluggedIn(true);
+        forceAwake();
+        forceDream();
+        when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+
+        advanceTime(20500);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+    }
+
     @Test
     public void testWakeLock_affectsProperDisplayGroup() {
         final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
index 184ea52..fe1ea0d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
@@ -33,6 +33,7 @@
 import android.app.ActivityOptions;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
+import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
+import android.util.Rational;
 import android.view.SurfaceControl;
 import android.window.TaskOrganizer;
 
@@ -91,6 +93,20 @@
     }
 
     @Test
+    public void testMakeLaunchIntoPip() {
+        // Construct some params with set values
+        PictureInPictureParams params = new PictureInPictureParams.Builder()
+                .setAspectRatio(new Rational(1, 1))
+                .build();
+        // Construct ActivityOptions via makeLaunchIntoPip
+        ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params);
+
+        // Verify the params in ActivityOptions has the right flag being turned on
+        assertNotNull(opts.getLaunchIntoPipParams());
+        assertTrue(opts.isLaunchIntoPip());
+    }
+
+    @Test
     public void testTransferLaunchCookie() {
         final Binder cookie = new Binder();
         final ActivityOptions options = ActivityOptions.makeBasic();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 043bc07..b0c3a01 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -109,6 +109,7 @@
 
 import android.app.ActivityOptions;
 import android.app.ICompatCameraControlCallback;
+import android.app.PictureInPictureParams;
 import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.DestroyActivityItem;
@@ -2200,6 +2201,20 @@
         assertFalse(activity.supportsPictureInPicture());
     }
 
+    @Test
+    public void testLaunchIntoPip() {
+        final PictureInPictureParams params = new PictureInPictureParams.Builder()
+                .build();
+        final ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params);
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setLaunchIntoPipActivityOptions(opts)
+                .build();
+
+        // Verify the pictureInPictureArgs is set on the new Activity
+        assertNotNull(activity.pictureInPictureArgs);
+        assertTrue(activity.pictureInPictureArgs.isLaunchIntoPip());
+    }
+
     private void verifyProcessInfoUpdate(ActivityRecord activity, State state,
             boolean shouldUpdate, boolean activityChange) {
         reset(activity.app);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index c8e48a4..87abc53 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -39,6 +39,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.os.Process.SYSTEM_UID;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -68,6 +69,7 @@
 
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
+import android.app.PictureInPictureParams;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -1141,6 +1143,34 @@
     }
 
     @Test
+    public void testStartActivityInner_inTaskFragment_allowedForSystemUid() {
+        final ActivityStarter starter = prepareStarter(0, false);
+        final ActivityRecord targetRecord = new ActivityBuilder(mAtm).build();
+        final ActivityRecord sourceRecord = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final TaskFragment taskFragment = new TaskFragment(mAtm, sourceRecord.token,
+                true /* createdByOrganizer */);
+        sourceRecord.getTask().addChild(taskFragment, POSITION_TOP);
+
+        taskFragment.setTaskFragmentOrganizer(mock(TaskFragmentOrganizerToken.class), SYSTEM_UID,
+                "system_uid");
+
+        starter.startActivityInner(
+                /* r */targetRecord,
+                /* sourceRecord */ sourceRecord,
+                /* voiceSession */null,
+                /* voiceInteractor */ null,
+                /* startFlags */ 0,
+                /* doResume */true,
+                /* options */null,
+                /* inTask */null,
+                /* inTaskFragment */ taskFragment,
+                /* restrictedBgActivity */false,
+                /* intentGrants */null);
+
+        assertTrue(taskFragment.hasChild());
+    }
+
+    @Test
     public void testStartActivityInner_inTaskFragment_allowedForSameUid() {
         final ActivityStarter starter = prepareStarter(0, false);
         final ActivityRecord targetRecord = new ActivityBuilder(mAtm).build();
@@ -1264,4 +1294,36 @@
         // Verify the cookie is updated
         assertTrue(mRootWindowContainer.topRunningActivity().mLaunchCookie == newCookie);
     }
+
+    @Test
+    public void testStartLaunchIntoPipActivity() {
+        final ActivityStarter starter = prepareStarter(0, false);
+
+        // Create an activity from ActivityOptions#makeLaunchIntoPip
+        final PictureInPictureParams params = new PictureInPictureParams.Builder()
+                .build();
+        final ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params);
+        ActivityRecord targetRecord = new ActivityBuilder(mAtm)
+                .setLaunchIntoPipActivityOptions(opts)
+                .build();
+
+        // Start the target launch-into-pip activity from a source
+        final ActivityRecord sourceRecord = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        starter.startActivityInner(
+                /* r */ targetRecord,
+                /* sourceRecord */ sourceRecord,
+                /* voiceSession */ null,
+                /* voiceInteractor */ null,
+                /* startFlags */ 0,
+                /* doResume */ true,
+                /* options */ opts,
+                /* inTask */ null,
+                /* inTaskFragment */ null,
+                /* restrictedBgActivity */ false,
+                /* intentGrants */ null);
+
+        // Verify the ActivityRecord#getLaunchIntoPipHostActivity points to sourceRecord.
+        assertThat(targetRecord.getLaunchIntoPipHostActivity()).isNotNull();
+        assertEquals(targetRecord.getLaunchIntoPipHostActivity(), sourceRecord);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index ee17f52..ba65104 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -251,7 +251,8 @@
         ensureTaskPlacement(fullscreenTask, firstActivity, secondActivity);
 
         // Move first activity to pinned root task.
-        mRootWindowContainer.moveActivityToPinnedRootTask(firstActivity, "initialMove");
+        mRootWindowContainer.moveActivityToPinnedRootTask(firstActivity,
+                null /* launchIntoPipHostActivity */, "initialMove");
 
         final TaskDisplayArea taskDisplayArea = fullscreenTask.getDisplayArea();
         Task pinnedRootTask = taskDisplayArea.getRootPinnedTask();
@@ -260,7 +261,8 @@
         ensureTaskPlacement(fullscreenTask, secondActivity);
 
         // Move second activity to pinned root task.
-        mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity, "secondMove");
+        mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity,
+                null /* launchIntoPipHostActivity */, "secondMove");
 
         // Need to get root tasks again as a new instance might have been created.
         pinnedRootTask = taskDisplayArea.getRootPinnedTask();
@@ -291,7 +293,8 @@
 
 
         // Move first activity to pinned root task.
-        mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity, "initialMove");
+        mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity,
+                null /* launchIntoPipHostActivity */, "initialMove");
 
         assertTrue(firstActivity.mRequestForceTransition);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 5dbb4c5..bd1f9d5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -941,6 +941,7 @@
         private boolean mOnTop = false;
         private ActivityInfo.WindowLayout mWindowLayout;
         private boolean mVisible = true;
+        private ActivityOptions mLaunchIntoPipOpts;
 
         ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
@@ -1076,6 +1077,11 @@
             return this;
         }
 
+        ActivityBuilder setLaunchIntoPipActivityOptions(ActivityOptions opts) {
+            mLaunchIntoPipOpts = opts;
+            return this;
+        }
+
         ActivityRecord build() {
             SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
             try {
@@ -1132,7 +1138,9 @@
             }
 
             ActivityOptions options = null;
-            if (mLaunchTaskBehind) {
+            if (mLaunchIntoPipOpts != null) {
+                options = mLaunchIntoPipOpts;
+            } else if (mLaunchTaskBehind) {
                 options = ActivityOptions.makeTaskLaunchBehind();
             }
             final ActivityRecord activity = new ActivityRecord.Builder(mService)
diff --git a/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java b/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
index 27e8d69..ab8f69b 100644
--- a/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
+++ b/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
@@ -22,6 +22,7 @@
 
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -39,6 +40,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
 
 class BroadcastResponseStatsTracker {
     private static final String TAG = "ResponseStatsTracker";
@@ -172,28 +175,27 @@
         }
     }
 
-    @NonNull BroadcastResponseStats queryBroadcastResponseStats(int callingUid,
-            @NonNull String packageName, long id, @UserIdInt int userId) {
-        final BroadcastResponseStats aggregatedResponseStats =
-                new BroadcastResponseStats(packageName);
+    @NonNull List<BroadcastResponseStats> queryBroadcastResponseStats(int callingUid,
+            @Nullable String packageName, @IntRange(from = 0) long id, @UserIdInt int userId) {
+        final List<BroadcastResponseStats> broadcastResponseStatsList = new ArrayList<>();
         synchronized (mLock) {
             final SparseArray<UserBroadcastResponseStats> responseStatsForCaller =
                     mUserResponseStats.get(callingUid);
             if (responseStatsForCaller == null) {
-                return aggregatedResponseStats;
+                return broadcastResponseStatsList;
             }
             final UserBroadcastResponseStats responseStatsForUser =
                     responseStatsForCaller.get(userId);
             if (responseStatsForUser == null) {
-                return aggregatedResponseStats;
+                return broadcastResponseStatsList;
             }
-            responseStatsForUser.aggregateBroadcastResponseStats(aggregatedResponseStats,
-                    packageName, id);
+            responseStatsForUser.populateAllBroadcastResponseStats(
+                    broadcastResponseStatsList, packageName, id);
         }
-        return aggregatedResponseStats;
+        return broadcastResponseStatsList;
     }
 
-    void clearBroadcastResponseStats(int callingUid, @NonNull String packageName, long id,
+    void clearBroadcastResponseStats(int callingUid, @Nullable String packageName, long id,
             @UserIdInt int userId) {
         synchronized (mLock) {
             final SparseArray<UserBroadcastResponseStats> responseStatsForCaller =
@@ -210,6 +212,16 @@
         }
     }
 
+    void clearBroadcastEvents(int callingUid, @UserIdInt int userId) {
+        synchronized (mLock) {
+            final UserBroadcastEvents userBroadcastEvents = mUserBroadcastEvents.get(userId);
+            if (userBroadcastEvents == null) {
+                return;
+            }
+            userBroadcastEvents.clear(callingUid);
+        }
+    }
+
     void onUserRemoved(@UserIdInt int userId) {
         synchronized (mLock) {
             mUserBroadcastEvents.remove(userId);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 4a761a7..06aa8f0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -49,7 +49,7 @@
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.usage.AppLaunchEstimateInfo;
 import android.app.usage.AppStandbyInfo;
-import android.app.usage.BroadcastResponseStats;
+import android.app.usage.BroadcastResponseStatsList;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.EventStats;
 import android.app.usage.IUsageStatsManager;
@@ -2686,16 +2686,15 @@
 
         @Override
         @NonNull
-        public BroadcastResponseStats queryBroadcastResponseStats(
-                @NonNull String packageName,
-                @IntRange(from = 1) long id,
+        public BroadcastResponseStatsList queryBroadcastResponseStats(
+                @Nullable String packageName,
+                @IntRange(from = 0) long id,
                 @NonNull String callingPackage,
                 @UserIdInt int userId) {
-            Objects.requireNonNull(packageName);
             Objects.requireNonNull(callingPackage);
             // TODO: Move to Preconditions utility class
-            if (id <= 0) {
-                throw new IllegalArgumentException("id needs to be >0");
+            if (id < 0) {
+                throw new IllegalArgumentException("id needs to be >=0");
             }
 
             final int callingUid = Binder.getCallingUid();
@@ -2708,8 +2707,9 @@
             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
                     userId, false /* allowAll */, false /* requireFull */,
                     "queryBroadcastResponseStats" /* name */, callingPackage);
-            return mResponseStatsTracker.queryBroadcastResponseStats(
-                    callingUid, packageName, id, userId);
+            return new BroadcastResponseStatsList(
+                    mResponseStatsTracker.queryBroadcastResponseStats(
+                            callingUid, packageName, id, userId));
         }
 
         @Override
@@ -2718,10 +2718,9 @@
                 @IntRange(from = 1) long id,
                 @NonNull String callingPackage,
                 @UserIdInt int userId) {
-            Objects.requireNonNull(packageName);
             Objects.requireNonNull(callingPackage);
-            if (id <= 0) {
-                throw new IllegalArgumentException("id needs to be >0");
+            if (id < 0) {
+                throw new IllegalArgumentException("id needs to be >=0");
             }
 
             final int callingUid = Binder.getCallingUid();
@@ -2737,6 +2736,23 @@
             mResponseStatsTracker.clearBroadcastResponseStats(callingUid,
                     packageName, id, userId);
         }
+
+        @Override
+        public void clearBroadcastEvents(@NonNull String callingPackage, @UserIdInt int userId) {
+            Objects.requireNonNull(callingPackage);
+
+            final int callingUid = Binder.getCallingUid();
+            if (!hasPermission(callingPackage)) {
+                throw new SecurityException(
+                        "Caller does not have the permission needed to call this API; "
+                                + "callingPackage=" + callingPackage
+                                + ", callingUid=" + callingUid);
+            }
+            userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
+                    userId, false /* allowAll */, false /* requireFull */,
+                    "clearBroadcastResponseStats" /* name */, callingPackage);
+            mResponseStatsTracker.clearBroadcastEvents(callingUid, userId);
+        }
     }
 
     void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
diff --git a/services/usage/java/com/android/server/usage/UserBroadcastEvents.java b/services/usage/java/com/android/server/usage/UserBroadcastEvents.java
index 819644846..0ec59c3 100644
--- a/services/usage/java/com/android/server/usage/UserBroadcastEvents.java
+++ b/services/usage/java/com/android/server/usage/UserBroadcastEvents.java
@@ -51,6 +51,10 @@
     }
 
     void onUidRemoved(int uid) {
+        clear(uid);
+    }
+
+    void clear(int uid) {
         for (int i = mBroadcastEvents.size() - 1; i >= 0; --i) {
             final LongSparseArray<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
             for (int j = broadcastEvents.size() - 1; j >= 0; --j) {
diff --git a/services/usage/java/com/android/server/usage/UserBroadcastResponseStats.java b/services/usage/java/com/android/server/usage/UserBroadcastResponseStats.java
index ac2a320..1828a71 100644
--- a/services/usage/java/com/android/server/usage/UserBroadcastResponseStats.java
+++ b/services/usage/java/com/android/server/usage/UserBroadcastResponseStats.java
@@ -16,6 +16,7 @@
 
 package com.android.server.usage;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.usage.BroadcastResponseStats;
@@ -23,6 +24,8 @@
 
 import com.android.internal.util.IndentingPrintWriter;
 
+import java.util.List;
+
 class UserBroadcastResponseStats {
     /**
      * Contains the mapping of a BroadcastEvent type to it's aggregated stats.
@@ -39,31 +42,38 @@
             BroadcastEvent broadcastEvent) {
         BroadcastResponseStats responseStats = mResponseStats.get(broadcastEvent);
         if (responseStats == null) {
-            responseStats = new BroadcastResponseStats(broadcastEvent.getTargetPackage());
+            responseStats = new BroadcastResponseStats(broadcastEvent.getTargetPackage(),
+                    broadcastEvent.getIdForResponseEvent());
             mResponseStats.put(broadcastEvent, responseStats);
         }
         return responseStats;
     }
 
-    void aggregateBroadcastResponseStats(
-            @NonNull BroadcastResponseStats responseStats,
-            @NonNull String packageName, long id) {
+    void populateAllBroadcastResponseStats(
+            @NonNull List<BroadcastResponseStats> broadcastResponseStatsList,
+            @Nullable String packageName, @IntRange(from = 0) long id) {
         for (int i = mResponseStats.size() - 1; i >= 0; --i) {
             final BroadcastEvent broadcastEvent = mResponseStats.keyAt(i);
-            if (broadcastEvent.getIdForResponseEvent() == id
-                    && broadcastEvent.getTargetPackage().equals(packageName)) {
-                responseStats.addCounts(mResponseStats.valueAt(i));
+            if (id != 0 && id != broadcastEvent.getIdForResponseEvent()) {
+                continue;
             }
+            if (packageName != null && !packageName.equals(broadcastEvent.getTargetPackage())) {
+                continue;
+            }
+            broadcastResponseStatsList.add(mResponseStats.valueAt(i));
         }
     }
 
-    void clearBroadcastResponseStats(@NonNull String packageName, long id) {
+    void clearBroadcastResponseStats(@Nullable String packageName, @IntRange(from = 0) long id) {
         for (int i = mResponseStats.size() - 1; i >= 0; --i) {
             final BroadcastEvent broadcastEvent = mResponseStats.keyAt(i);
-            if (broadcastEvent.getIdForResponseEvent() == id
-                    && broadcastEvent.getTargetPackage().equals(packageName)) {
-                mResponseStats.removeAt(i);
+            if (id != 0 && id != broadcastEvent.getIdForResponseEvent()) {
+                continue;
             }
+            if (packageName != null && !packageName.equals(broadcastEvent.getTargetPackage())) {
+                continue;
+            }
+            mResponseStats.removeAt(i);
         }
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3d00474..eb3df1c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -8226,7 +8226,9 @@
             "store_sim_pin_for_unattended_reboot_bool";
 
     /**
-     * Determine whether "Enable 2G" toggle can be shown.
+     * Allow whether the user can use the "Allow 2G" toggle in Settings.
+     *
+     * If {@code true} then the toggle is disabled (i.e. grayed out).
      *
      * Used to trade privacy/security against potentially reduced carrier coverage for some
      * carriers.
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index a49a61b5..b6ae530 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -25,15 +25,20 @@
 import android.annotation.SystemApi;
 import android.app.Activity;
 import android.app.PendingIntent;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.telephony.SubscriptionInfo;
 import android.telephony.TelephonyFrameworkInitializer;
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccCardManager.ResetOption;
+import android.util.Log;
 
 import com.android.internal.telephony.euicc.IEuiccController;
 
@@ -57,6 +62,7 @@
  */
 @RequiresFeature(PackageManager.FEATURE_TELEPHONY_EUICC)
 public class EuiccManager {
+    private static final String TAG = "EuiccManager";
 
     /**
      * Intent action to launch the embedded SIM (eUICC) management settings screen.
@@ -811,6 +817,14 @@
      */
     public static final int ERROR_INVALID_PORT = 10017;
 
+    /**
+     * Apps targeting on Android T and beyond will get exception whenever switchToSubscription
+     * without portIndex is called for disable subscription.
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    public static final long SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE = 218393363L;
 
     private final Context mContext;
     private int mCardId;
@@ -1127,7 +1141,7 @@
      * intent to prompt the user to accept the download. The caller should also be authorized to
      * manage the subscription to be enabled.
      *
-     * <p> From Android T, devices might support MEP(Multiple Enabled Profile), the subscription
+     * <p> From Android T, devices might support MEP(Multiple Enabled Profiles), the subscription
      * can be installed on different port from the eUICC. Calling apps with carrier privilege
      * (see {@link TelephonyManager#hasCarrierPrivileges}) over the currently active subscriptions
      * can use {@link #switchToSubscription(int, int, PendingIntent)} to specify which port to
@@ -1138,10 +1152,12 @@
      *
      * @param subscriptionId the ID of the subscription to enable. May be
      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
-     *     current profile without activating another profile to replace it. If it's a disable
-     *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
-     *     permission, or the calling app must be authorized to manage the active subscription on
-     *     the target eUICC.
+     *     current profile without activating another profile to replace it. Calling apps targeting
+     *     on android T must use {@link #switchToSubscription(int, int, PendingIntent)} API for
+     *     disable profile, port index can be found from {@link SubscriptionInfo#getPortIndex()}.
+     *     If it's a disable operation, requires the
+     *     {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or the
+     *     calling app must be authorized to manage the active subscription on the target eUICC.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
@@ -1151,6 +1167,18 @@
             return;
         }
         try {
+            // TODO: Uncomment below compat change code once callers are ported to use
+            //  switchToSubscription with portIndex for disable operation.
+            // if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+            //        && getIEuiccController().isCompatChangeEnabled(mContext.getOpPackageName(),
+            //        SWITCH_WITHOUT_PORT_INDEX_EXCEPTION_ON_DISABLE)) {
+            //    // Apps targeting on Android T and beyond will get exception whenever
+            //    // switchToSubscription without portIndex is called with INVALID_SUBSCRIPTION_ID.
+            //    Log.e(TAG, "switchToSubscription without portIndex is not allowed for"
+            //            + " disable operation");
+            //    throw new IllegalArgumentException("Must use switchToSubscription with portIndex"
+            //            + " API for disable operation");
+            // }
             getIEuiccController().switchToSubscription(mCardId,
                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
@@ -1180,7 +1208,10 @@
      *     current profile without activating another profile to replace it. If it's a disable
      *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
      *     permission, or the calling app must be authorized to manage the active subscription on
-     *     the target eUICC.
+     *     the target eUICC. From Android T, multiple enabled profiles is supported. Calling apps
+     *     targeting on android T must use {@link #switchToSubscription(int, int, PendingIntent)}
+     *     API for disable profile, port index can be found from
+     *     {@link SubscriptionInfo#getPortIndex()}.
      * @param portIndex the index of the port to target for the enabled subscription
      * @param callbackIntent a PendingIntent to launch when the operation completes.
      */
@@ -1192,6 +1223,17 @@
             return;
         }
         try {
+            boolean canWriteEmbeddedSubscriptions = mContext.checkCallingOrSelfPermission(
+                    Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+                    == PackageManager.PERMISSION_GRANTED;
+            // If the caller is not privileged caller and does not have the carrier privilege over
+            // any active subscription, do not continue.
+            if (!canWriteEmbeddedSubscriptions && !getIEuiccController()
+                    .hasCarrierPrivilegesForPackageOnAnyPhone(mContext.getOpPackageName())) {
+                Log.e(TAG, "Not permitted to use switchToSubscription with portIndex");
+                throw new SecurityException(
+                        "Must have carrier privileges to use switchToSubscription with portIndex");
+            }
             getIEuiccController().switchToSubscriptionWithPort(mCardId,
                     subscriptionId, portIndex, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index dda95b1..19f1a5b 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -55,4 +55,6 @@
     List<String> getSupportedCountries(boolean isSupported);
     boolean isSupportedCountry(String countryIso);
     boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage);
+    boolean hasCarrierPrivilegesForPackageOnAnyPhone(String callingPackage);
+    boolean isCompatChangeEnabled(String callingPackage, long changeId);
 }
diff --git a/tests/Internal/src/com/android/internal/util/UserIconsTest.java b/tests/Internal/src/com/android/internal/util/UserIconsTest.java
new file mode 100644
index 0000000..cc7b20b
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/util/UserIconsTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 com.android.internal.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.R;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class UserIconsTest {
+
+    @Test
+    public void convertToBitmapAtUserIconSize_sizeIsCorrect() {
+        Resources res = InstrumentationRegistry.getTargetContext().getResources();
+        Drawable icon = UserIcons.getDefaultUserIcon(res, 0, true);
+        Bitmap bitmap = UserIcons.convertToBitmapAtUserIconSize(res, icon);
+        int expectedSize = res.getDimensionPixelSize(R.dimen.user_icon_size);
+
+        assertThat(bitmap.getWidth()).isEqualTo(expectedSize);
+        assertThat(bitmap.getHeight()).isEqualTo(expectedSize);
+    }
+
+}