Merge "[Ravenwood] Support NativeAllocationRegistry" into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index f10c0fc..eabe1f1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -872,6 +872,7 @@
   public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public String getAttributionTag();
+    method @FlaggedApi("android.permission.flags.device_id_in_op_proxy_info_enabled") @Nullable public String getDeviceId();
     method @Nullable public String getPackageName();
     method @IntRange(from=0) public int getUid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 68cc17b..caaaf51 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -7438,6 +7438,7 @@
         }
         mDdmSyncStageUpdater.next(Stage.Running);
 
+        long timestampApplicationOnCreateNs = 0;
         try {
             // If the app is being launched for full backup or restore, bring it up in
             // a restricted environment with the base application class.
@@ -7480,8 +7481,10 @@
                     + data.instrumentationName + ": " + e.toString(), e);
             }
             try {
+                timestampApplicationOnCreateNs = SystemClock.elapsedRealtimeNanos();
                 mInstrumentation.callApplicationOnCreate(app);
             } catch (Exception e) {
+                timestampApplicationOnCreateNs = 0;
                 if (!mInstrumentation.onException(app, e)) {
                     throw new RuntimeException(
                       "Unable to create application " + app.getClass().getName()
@@ -7519,7 +7522,7 @@
         }
 
         try {
-            mgr.finishAttachApplication(mStartSeq);
+            mgr.finishAttachApplication(mStartSeq, timestampApplicationOnCreateNs);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 20b2357..2d0f6fc 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3457,6 +3457,8 @@
         private @Nullable String mPackageName;
         /** Attribution tag of the proxy that noted the op */
         private @Nullable String mAttributionTag;
+        /** Persistent device Id of the proxy that noted the op */
+        private @Nullable String mDeviceId;
 
         /**
          * Reinit existing object with new state.
@@ -3464,14 +3466,16 @@
          * @param uid UID of the proxy app that noted the op
          * @param packageName Package of the proxy that noted the op
          * @param attributionTag attribution tag of the proxy that noted the op
+         * @param deviceId Persistent device Id of the proxy that noted the op
          *
          * @hide
          */
         public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName,
-                @Nullable String attributionTag) {
+                @Nullable String attributionTag, @Nullable String deviceId) {
             mUid = Preconditions.checkArgumentNonnegative(uid);
             mPackageName = packageName;
             mAttributionTag = attributionTag;
+            mDeviceId = deviceId;
         }
 
 
@@ -3505,16 +3509,33 @@
                 @IntRange(from = 0) int uid,
                 @Nullable String packageName,
                 @Nullable String attributionTag) {
+            this(uid, packageName, attributionTag,
+                    VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
+        }
+
+        /**
+         * Creates a new OpEventProxyInfo.
+         *
+         * @param uid UID of the proxy app that noted the op
+         * @param packageName Package of the proxy that noted the op
+         * @param attributionTag Attribution tag of the proxy that noted the op
+         * @param deviceId Persistent device Id of the proxy that noted the op
+         *
+         * @hide
+         */
+        public OpEventProxyInfo(
+                @IntRange(from = 0) int uid,
+                @Nullable String packageName,
+                @Nullable String attributionTag,
+                @Nullable String deviceId) {
             this.mUid = uid;
             com.android.internal.util.AnnotationValidations.validate(
                     IntRange.class, null, mUid,
                     "from", 0);
             this.mPackageName = packageName;
             this.mAttributionTag = attributionTag;
-
-            // onConstructed(); // You can define this method to get a callback
+            this.mDeviceId = deviceId;
         }
-
         /**
          * Copy constructor
          *
@@ -3525,6 +3546,7 @@
             mUid = orig.mUid;
             mPackageName = orig.mPackageName;
             mAttributionTag = orig.mAttributionTag;
+            mDeviceId = orig.mDeviceId;
         }
 
         /**
@@ -3551,6 +3573,9 @@
             return mAttributionTag;
         }
 
+        @FlaggedApi(Flags.FLAG_DEVICE_ID_IN_OP_PROXY_INFO_ENABLED)
+        public @Nullable String getDeviceId() { return mDeviceId; }
+
         @Override
         @DataClass.Generated.Member
         public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -3560,10 +3585,12 @@
             byte flg = 0;
             if (mPackageName != null) flg |= 0x2;
             if (mAttributionTag != null) flg |= 0x4;
+            if (mDeviceId != null) flg |= 0x8;
             dest.writeByte(flg);
             dest.writeInt(mUid);
             if (mPackageName != null) dest.writeString(mPackageName);
             if (mAttributionTag != null) dest.writeString(mAttributionTag);
+            if (mDeviceId != null) dest.writeString(mDeviceId);
         }
 
         @Override
@@ -3581,14 +3608,14 @@
             int uid = in.readInt();
             String packageName = (flg & 0x2) == 0 ? null : in.readString();
             String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
-
+            String deviceId = (flg & 0x8) == 0 ? null : in.readString();
             this.mUid = uid;
             com.android.internal.util.AnnotationValidations.validate(
                     IntRange.class, null, mUid,
                     "from", 0);
             this.mPackageName = packageName;
             this.mAttributionTag = attributionTag;
-
+            this.mDeviceId = deviceId;
             // onConstructed(); // You can define this method to get a callback
         }
 
diff --git a/core/java/android/app/GrammaticalInflectionManager.java b/core/java/android/app/GrammaticalInflectionManager.java
index f0bc3e2..37e51f8 100644
--- a/core/java/android/app/GrammaticalInflectionManager.java
+++ b/core/java/android/app/GrammaticalInflectionManager.java
@@ -104,7 +104,7 @@
      * Sets the current grammatical gender for all privileged applications. The value will be
      * stored in an encrypted file at {@link android.os.Environment#getDataSystemCeDirectory(int)}
      *
-     * @param grammaticalGender the terms of address the user preferred in system.
+     * @param grammaticalGender the grammatical gender set by the user for the system.
      *
      * @see Configuration#getGrammaticalGender
      * @hide
@@ -123,12 +123,12 @@
     }
 
     /**
-     * Get the current grammatical gender of privileged application from the encrypted file.
+     * Allows privileged preloaded applications to get the system grammatical gender when set.
      *
-     * @return the value of system grammatical gender only if the calling app has the permission,
-     * otherwise throwing an exception.
+     * @return The value of system grammatical gender only if the calling app has the
+     * permission, otherwise throwing an exception.
      *
-     * @throws SecurityException if the caller does not have the required permission.
+     * @throws SecurityException If the caller does not have the required permission.
      *
      * @see Configuration#getGrammaticalGender
      */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3765c81..e8b57f2 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -196,7 +196,7 @@
     oneway void finishReceiver(in IBinder who, int resultCode, in String resultData, in Bundle map,
             boolean abortBroadcast, int flags);
     void attachApplication(in IApplicationThread app, long startSeq);
-    void finishAttachApplication(long startSeq);
+    void finishAttachApplication(long startSeq, long timestampApplicationOnCreateNs);
     List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
     @UnsupportedAppUsage
     void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4060467..c3bac71 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -18,7 +18,6 @@
 
 import static android.annotation.Dimension.DP;
 import static android.app.Flags.evenlyDividedCallStyleActionLayout;
-import static android.app.Flags.updateRankingTime;
 import static android.app.admin.DevicePolicyResources.Drawables.Source.NOTIFICATION;
 import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
 import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
@@ -2600,7 +2599,7 @@
     public Notification()
     {
         this.when = System.currentTimeMillis();
-        if (updateRankingTime()) {
+        if (Flags.sortSectionByTime()) {
             creationTime = when;
             extras.putBoolean(EXTRA_SHOW_WHEN, true);
         } else {
@@ -2616,7 +2615,7 @@
     public Notification(Context context, int icon, CharSequence tickerText, long when,
             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
     {
-        if (updateRankingTime()) {
+        if (Flags.sortSectionByTime()) {
             creationTime = when;
             extras.putBoolean(EXTRA_SHOW_WHEN, true);
         }
@@ -2649,7 +2648,7 @@
         this.icon = icon;
         this.tickerText = tickerText;
         this.when = when;
-        if (updateRankingTime()) {
+        if (Flags.sortSectionByTime()) {
             creationTime = when;
             extras.putBoolean(EXTRA_SHOW_WHEN, true);
         } else {
@@ -3260,8 +3259,9 @@
                 boolean mustClearCookie = false;
                 if (!parcel.hasClassCookie(Notification.class)) {
                     // This is the "root" notification, and not an "inner" notification (including
-                    // publicVersion or anything else that might be embedded in extras).
-                    parcel.setClassCookie(Notification.class, this);
+                    // publicVersion or anything else that might be embedded in extras). So we want
+                    // to use its token for every inner notification (might be null).
+                    parcel.setClassCookie(Notification.class, mAllowlistToken);
                     mustClearCookie = true;
                 }
                 try {
@@ -3270,7 +3270,7 @@
                     writeToParcelImpl(parcel, flags);
                 } finally {
                     if (mustClearCookie) {
-                        parcel.removeClassCookie(Notification.class, this);
+                        parcel.removeClassCookie(Notification.class, mAllowlistToken);
                     }
                 }
             } else {
@@ -3294,14 +3294,9 @@
         parcel.writeInt(1);
 
         if (Flags.secureAllowlistToken()) {
-            Notification rootNotification = (Notification) parcel.getClassCookie(
-                    Notification.class);
-            if (rootNotification != null && rootNotification != this) {
-                // Always use the same token as the root notification
-                parcel.writeStrongBinder(rootNotification.mAllowlistToken);
-            } else {
-                parcel.writeStrongBinder(mAllowlistToken);
-            }
+            // Always use the same token as the root notification (might be null).
+            IBinder rootNotificationToken = (IBinder) parcel.getClassCookie(Notification.class);
+            parcel.writeStrongBinder(rootNotificationToken);
         } else {
             parcel.writeStrongBinder(mAllowlistToken);
         }
@@ -5985,21 +5980,22 @@
                 }
                 if (mN.extras.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                     contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
-                    contentView.setLong(R.id.chronometer, "setBase",
-                            mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
+                    contentView.setLong(R.id.chronometer, "setBase", mN.getWhen()
+                            + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
                     contentView.setBoolean(R.id.chronometer, "setStarted", true);
                     boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN);
                     contentView.setChronometerCountDown(R.id.chronometer, countsDown);
                     setTextViewColorSecondary(contentView, R.id.chronometer, p);
                 } else {
                     contentView.setViewVisibility(R.id.time, View.VISIBLE);
-                    contentView.setLong(R.id.time, "setTime", mN.when);
+                    contentView.setLong(R.id.time, "setTime", mN.getWhen());
                     setTextViewColorSecondary(contentView, R.id.time, p);
                 }
             } else {
                 // We still want a time to be set but gone, such that we can show and hide it
                 // on demand in case it's a child notification without anything in the header
-                contentView.setLong(R.id.time, "setTime", mN.when != 0 ? mN.when : mN.creationTime);
+                contentView.setLong(R.id.time, "setTime", mN.getWhen() != 0 ? mN.getWhen() :
+                        mN.creationTime);
                 setTextViewColorSecondary(contentView, R.id.time, p);
             }
         }
@@ -7166,7 +7162,7 @@
                 }
             }
 
-            if (!updateRankingTime()) {
+            if (!Flags.sortSectionByTime()) {
                 mN.creationTime = System.currentTimeMillis();
             }
 
@@ -7619,10 +7615,29 @@
     }
 
     /**
+     * Returns #when, unless it's set to 0, which should be shown as/treated as a 'current'
+     * notification. 0 is treated as a special value because it was special in an old version of
+     * android, and some apps are still (incorrectly) using it.
+     *
+     * @hide
+     */
+    public long getWhen() {
+        if (Flags.sortSectionByTime()) {
+            if (when == 0) {
+                return creationTime;
+            }
+        }
+        return when;
+    }
+
+    /**
      * @return true if the notification will show the time; false otherwise
      * @hide
      */
     public boolean showsTime() {
+        if (Flags.sortSectionByTime()) {
+            return extras.getBoolean(EXTRA_SHOW_WHEN);
+        }
         return when != 0 && extras.getBoolean(EXTRA_SHOW_WHEN);
     }
 
@@ -7631,6 +7646,9 @@
      * @hide
      */
     public boolean showsChronometer() {
+        if (Flags.sortSectionByTime()) {
+            return extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
+        }
         return when != 0 && extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
     }
 
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 9b3fb5c..726064e 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -1198,17 +1198,18 @@
      * Callback called when a particular foreground service type has timed out.
      *
      * <p>This callback is meant to give the app a small grace period of a few seconds to finish
-     * the foreground service of the offending type - if it fails to do so, the app will be
+     * the foreground service of the associated type - if it fails to do so, the app will be
      * declared an ANR.
      *
-     * <p>The foreground service of the offending type can be stopped within the time limit by
+     * <p>The foreground service of the associated type can be stopped within the time limit by
      * {@link android.app.Service#stopSelf()},
      * {@link android.content.Context#stopService(android.content.Intent)} or their overloads.
      * {@link android.app.Service#stopForeground(int)} can be used as well, which demotes the
      * service to a "background" service, which will soon be stopped by the system.
      *
      * <p>The specific time limit for each type (if one exists) is mentioned in the documentation
-     * for that foreground service type.
+     * for that foreground service type. See
+     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC dataSync} for example.
      *
      * <p>Note: time limits are restricted to a rolling 24-hour window - for example, if a
      * foreground service type has a time limit of 6 hours, that time counter begins as soon as the
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index e4425ca..8c4667f 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -40,3 +40,13 @@
      description: "Add a new callback in Service to indicate a FGS has reached its timeout."
      bug: "317799821"
 }
+
+flag {
+     namespace: "system_performance"
+     name: "app_start_info_timestamps"
+     description: "Additional timestamps."
+     bug: "287153617"
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
+}
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index c62680f..027d101 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -92,6 +92,7 @@
         mTestedUsers = new ArraySet<>();
         mUsersCleaningUp = new ArraySet<>();
         setTestHalEnabled(true);
+        Log.d(getTag(), "Opening BiometricTestSession");
     }
 
     /**
diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig
index 6b5e17d..b588308 100644
--- a/core/java/android/permission/flags.aconfig
+++ b/core/java/android/permission/flags.aconfig
@@ -180,3 +180,11 @@
     description: "Use runtime permission state to determine appop state"
     bug: "266164193"
 }
+
+flag {
+    name: "device_id_in_op_proxy_info_enabled"
+    is_fixed_read_only: true
+    namespace: "permissions"
+    description: "Enable getDeviceId API in OpEventProxyInfo"
+    bug: "337340961"
+}
\ No newline at end of file
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index b9de93c..7653bdb 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -56,11 +56,18 @@
     public static class BytesResult {
         public final String value;
         public final String units;
+        /**
+         * Content description of the {@link #units}.
+         * See {@link View#setContentDescription(CharSequence)}
+         */
+        public final String unitsContentDescription;
         public final long roundedBytes;
 
-        public BytesResult(String value, String units, long roundedBytes) {
+        public BytesResult(String value, String units, String unitsContentDescription,
+                long roundedBytes) {
             this.value = value;
             this.units = units;
+            this.unitsContentDescription = unitsContentDescription;
             this.roundedBytes = roundedBytes;
         }
     }
@@ -271,20 +278,20 @@
         final Locale locale = res.getConfiguration().getLocales().get(0);
         final NumberFormat numberFormatter = getNumberFormatter(locale, rounded.fractionDigits);
         final String formattedNumber = numberFormatter.format(rounded.value);
-        final String units;
+        // Since ICU does not give us access to the pattern, we need to extract the unit string
+        // from ICU, which we do by taking out the formatted number out of the formatted string
+        // and trimming the result of spaces and controls.
+        final String formattedMeasure = formatMeasureShort(
+                locale, numberFormatter, rounded.value, rounded.units);
+        final String numberRemoved = deleteFirstFromString(formattedMeasure, formattedNumber);
+        String units = SPACES_AND_CONTROLS.trim(numberRemoved).toString();
+        String unitsContentDescription = units;
         if (rounded.units == MeasureUnit.BYTE) {
             // ICU spells out "byte" instead of "B".
             units = getByteSuffixOverride(res);
-        } else {
-            // Since ICU does not give us access to the pattern, we need to extract the unit string
-            // from ICU, which we do by taking out the formatted number out of the formatted string
-            // and trimming the result of spaces and controls.
-            final String formattedMeasure = formatMeasureShort(
-                    locale, numberFormatter, rounded.value, rounded.units);
-            final String numberRemoved = deleteFirstFromString(formattedMeasure, formattedNumber);
-            units = SPACES_AND_CONTROLS.trim(numberRemoved).toString();
         }
-        return new BytesResult(formattedNumber, units, rounded.roundedBytes);
+        return new BytesResult(formattedNumber, units, unitsContentDescription,
+                rounded.roundedBytes);
     }
 
     /**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 65d9b3a..cb5a885 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -62,7 +62,6 @@
 import android.view.InputDevice;
 import android.view.IInputFilter;
 import android.view.AppTransitionAnimationSpec;
-import android.view.TaskTransitionSpec;
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.SurfaceControl;
@@ -962,19 +961,6 @@
     void setTaskSnapshotEnabled(boolean enabled);
 
     /**
-     * Customized the task transition animation with a task transition spec.
-     *
-     * @param spec the spec that will be used to customize the task animations
-     */
-    void setTaskTransitionSpec(in TaskTransitionSpec spec);
-
-    /**
-     * Clears any task transition spec that has been previously set and
-     * reverts to using the default task transition with no spec changes.
-     */
-    void clearTaskTransitionSpec();
-
-    /**
      * Registers the frame rate per second count callback for one given task ID.
      * Each callback can only register for receiving FPS callback for one task id until unregister
      * is called. If there's no task associated with the given task id,
diff --git a/core/java/android/view/TaskTransitionSpec.aidl b/core/java/android/view/TaskTransitionSpec.aidl
deleted file mode 100644
index 08af15c..0000000
--- a/core/java/android/view/TaskTransitionSpec.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-** Copyright 2021, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.view;
-
-/** @hide */
-parcelable TaskTransitionSpec;
diff --git a/core/java/android/view/TaskTransitionSpec.java b/core/java/android/view/TaskTransitionSpec.java
deleted file mode 100644
index 9a2d3ba..0000000
--- a/core/java/android/view/TaskTransitionSpec.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Holds information about how to execute task transition animations.
- *
- * This class is intended to be used with IWindowManager.setTaskTransitionSpec methods when
- * we want more customization over the way default task transitions are executed.
- *
- * @hide
- */
-public class TaskTransitionSpec implements Parcelable {
-    /**
-     * The background color to use during task animations (override the default background color)
-     */
-    public final int backgroundColor;
-
-    public TaskTransitionSpec(int backgroundColor) {
-        this.backgroundColor = backgroundColor;
-    }
-
-    public TaskTransitionSpec(Parcel in) {
-        this.backgroundColor = in.readInt();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(backgroundColor);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<TaskTransitionSpec>
-            CREATOR = new Parcelable.Creator<TaskTransitionSpec>() {
-                public TaskTransitionSpec createFromParcel(Parcel in) {
-                    return new TaskTransitionSpec(in);
-                }
-
-                public TaskTransitionSpec[] newArray(int size) {
-                    return new TaskTransitionSpec[size];
-                }
-            };
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ddead88..a844370 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -912,12 +912,6 @@
     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
 
     /**
-     * The logging tag used by this class when logging verbose and chatty (high volume)
-     * autofill-related messages.
-     */
-    private static final String AUTOFILL_CHATTY_LOG_TAG = "View.Autofill.Chatty";
-
-    /**
      * The logging tag used by this class when logging content capture-related messages.
      */
     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
@@ -8708,8 +8702,8 @@
     @CallSuper
     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
             @Nullable Rect previouslyFocusedRect) {
-        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-            Log.v(AUTOFILL_CHATTY_LOG_TAG, "onFocusChanged() entered. gainFocus: "
+        if (DBG) {
+            Log.d(VIEW_LOG_TAG, "onFocusChanged() entered. gainFocus: "
                     + gainFocus);
         }
         if (gainFocus) {
@@ -8777,8 +8771,8 @@
         if (canNotifyAutofillEnterExitEvent()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
-                if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                    Log.v(AUTOFILL_CHATTY_LOG_TAG, this + " afm is not null");
+                if (DBG) {
+                    Log.d(VIEW_LOG_TAG, this + " afm is not null");
                 }
                 if (enter) {
                     // We have not been laid out yet, hence cannot evaluate
@@ -8791,8 +8785,8 @@
                     // animation beginning. On the time, the view is not visible
                     // to the user. And then as the animation progresses, the view
                     // becomes visible to the user.
-                    if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                        Log.v(AUTOFILL_CHATTY_LOG_TAG,
+                    if (DBG) {
+                        Log.d(VIEW_LOG_TAG,
                                 "notifyEnterOrExitForAutoFillIfNeeded:"
                                 + " isLaidOut(): " + isLaidOut()
                                 + " isVisibleToUser(): " + isVisibleToUser()
@@ -11024,28 +11018,28 @@
     }
 
     private boolean isAutofillable() {
-        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-            Log.v(AUTOFILL_CHATTY_LOG_TAG, "isAutofillable() entered.");
+        if (DBG) {
+            Log.d(VIEW_LOG_TAG, "isAutofillable() entered.");
         }
         if (getAutofillType() == AUTOFILL_TYPE_NONE) {
-            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
+            if (DBG) {
+                Log.d(VIEW_LOG_TAG, "getAutofillType() returns AUTOFILL_TYPE_NONE");
             }
             return false;
         }
 
         final AutofillManager afm = getAutofillManager();
         if (afm == null) {
-            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_CHATTY_LOG_TAG, "AutofillManager is null");
+            if (DBG) {
+                Log.d(VIEW_LOG_TAG, "AutofillManager is null");
             }
             return false;
         }
 
         // Check whether view is not part of an activity. If it's not, return false.
         if (getAutofillViewId() <= LAST_APP_AUTOFILL_ID) {
-            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_CHATTY_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
+            if (DBG) {
+                Log.d(VIEW_LOG_TAG, "getAutofillViewId()<=LAST_APP_AUTOFILL_ID");
             }
             return false;
         }
@@ -11056,9 +11050,8 @@
         if ((isImportantForAutofill() && afm.isTriggerFillRequestOnFilteredImportantViewsEnabled())
                 || (!isImportantForAutofill()
                     && afm.isTriggerFillRequestOnUnimportantViewEnabled())) {
-            if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_CHATTY_LOG_TAG,
-                        "isImportantForAutofill(): " + isImportantForAutofill()
+            if (DBG) {
+                Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill()
                         + "afm.isAutofillable(): " + afm.isAutofillable(this));
             }
             return afm.isAutofillable(this) ? true : notifyAugmentedAutofillIfNeeded(afm);
@@ -11066,8 +11059,8 @@
 
         // If the previous condition is not met, fall back to the previous way to trigger fill
         // request based on autofill importance instead.
-        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-            Log.v(AUTOFILL_CHATTY_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
+        if (DBG) {
+            Log.d(VIEW_LOG_TAG, "isImportantForAutofill(): " + isImportantForAutofill());
         }
         return isImportantForAutofill() ? true : notifyAugmentedAutofillIfNeeded(afm);
     }
@@ -11083,8 +11076,8 @@
 
     /** @hide */
     public boolean canNotifyAutofillEnterExitEvent() {
-        if (Log.isLoggable(AUTOFILL_CHATTY_LOG_TAG, Log.VERBOSE)) {
-            Log.v(AUTOFILL_CHATTY_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
+        if (DBG) {
+            Log.d(VIEW_LOG_TAG, "canNotifyAutofillEnterExitEvent() entered. "
                     + " isAutofillable(): " + isAutofillable()
                     + " isAttachedToWindow(): " + isAttachedToWindow());
         }
@@ -17160,10 +17153,12 @@
 
     /**
      * Handle a key event before it is processed by any input method
-     * associated with the view hierarchy.  This can be used to intercept
+     * associated with the view hierarchy. This can be used to intercept
      * key events in special situations before the IME consumes them; a
      * typical example would be handling the BACK key to update the application's
-     * UI instead of allowing the IME to see it and close itself.
+     * UI instead of allowing the IME to see it and close itself. Due to a bug,
+     * this function is not called for BACK key events on Android T and U, when
+     * the IME is shown.
      *
      * @param keyCode The value in event.getKeyCode().
      * @param event Description of the key event.
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index ee6ba24..3b9b162 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -16,6 +16,8 @@
 
 package android.window;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
@@ -27,6 +29,8 @@
 import android.util.Log;
 import android.view.ViewRootImpl;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 
 /**
@@ -280,7 +284,8 @@
         sendStopDispatching();
     }
 
-    static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
+    @VisibleForTesting(visibility = PACKAGE)
+    public static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
         @NonNull
         private final IOnBackInvokedCallback mIOnBackInvokedCallback;
         /**
@@ -327,7 +332,8 @@
      * Subclass of ImeOnBackInvokedCallback indicating that a predictive IME back animation may be
      * played instead of invoking the callback.
      */
-    static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
+    @VisibleForTesting(visibility = PACKAGE)
+    public static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback {
         DefaultImeOnBackAnimationCallback(@NonNull IOnBackInvokedCallback iCallback, int id,
                 int priority) {
             super(iCallback, id, priority);
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 7f6678e..cf0c015 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -176,6 +176,12 @@
                 mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
                 return;
             }
+            if ((callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback
+                    || callback instanceof ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
+                    && !isOnBackInvokedCallbackEnabled()) {
+                // Fall back to compat back key injection if legacy back behaviour should be used.
+                return;
+            }
             if (!mOnBackInvokedCallbacks.containsKey(priority)) {
                 mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
             }
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index a022842..7267eb8 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -190,17 +190,21 @@
         return -1;
     }
 
-    jbyte* bufferBytes = NULL;
-    if (buffer) {
-        bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL);
+    bool is_dir_in = (endpoint & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+    jbyte *bufferBytes = (jbyte *)malloc(length);
+
+    if (!is_dir_in && buffer) {
+        env->GetByteArrayRegion(buffer, start, length, bufferBytes);
     }
 
-    jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout);
+    jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
 
-    if (bufferBytes) {
-        env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0);
+    if (is_dir_in && buffer) {
+        env->SetByteArrayRegion(buffer, start, length, bufferBytes);
     }
 
+    free(bufferBytes);
+
     return result;
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e2106c5..77a9912 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8233,7 +8233,7 @@
         </activity>
         <activity android:name="com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity"
                   android:exported="false"
-                  android:theme="@style/Theme.DeviceDefault.Resolver"
+                  android:theme="@style/AccessibilityButtonChooserDialog"
                   android:finishOnCloseSystemDialogs="true"
                   android:excludeFromRecents="true"
                   android:documentLaunchMode="never"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 50ed422..877d11e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7038,4 +7038,7 @@
          If the gesture is completed faster than this, we assume it's not performed by human and the
          event gets ignored. -->
     <integer name="config_defaultMinEmergencyGestureTapDurationMillis">200</integer>
+
+    <!-- Whether the system uses auto-suspend mode. -->
+    <bool name="config_useAutoSuspend">true</bool>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5945f81..a46dc04 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1685,4 +1685,9 @@
         <item name="android:paddingStart">8dp</item>
         <item name="android:background">?android:attr/selectableItemBackground</item>
     </style>
+
+    <style name="AccessibilityButtonChooserDialog"
+           parent="@style/Theme.DeviceDefault.Resolver">
+        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d432c05..972d8df 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5424,4 +5424,7 @@
   <!-- Back swipe thresholds -->
   <java-symbol type="dimen" name="navigation_edge_action_progress_threshold" />
   <java-symbol type="dimen" name="back_progress_non_linear_factor" />
+
+  <!-- For PowerManagerService to determine whether to use auto-suspend mode -->
+  <java-symbol type="bool" name="config_useAutoSuspend" />
 </resources>
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 5cc1ee4..7fb894a 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -86,6 +86,7 @@
 import android.os.Parcelable;
 import android.os.SystemProperties;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
@@ -126,6 +127,7 @@
 
     @Rule
     public TestRule compatChangeRule = new PlatformCompatChangeRule();
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Before
     public void setUp() {
@@ -1835,6 +1837,36 @@
         Assert.assertEquals(bitmap, resultBitmap);
     }
 
+    @Test
+    public void testGetWhen_zero() {
+        Notification n = new Notification.Builder(mContext, "test")
+                .setWhen(0)
+                .build();
+
+        mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+        assertThat(n.getWhen()).isEqualTo(0);
+
+        mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+        assertThat(n.getWhen()).isEqualTo(n.creationTime);
+    }
+
+    @Test
+    public void testGetWhen_devProvidedNonZero() {
+        Notification n = new Notification.Builder(mContext, "test")
+                .setWhen(9)
+                .build();
+
+        mSetFlagsRule.disableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+        assertThat(n.getWhen()).isEqualTo(9);
+
+        mSetFlagsRule.enableFlags(Flags.FLAG_SORT_SECTION_BY_TIME);
+
+        assertThat(n.getWhen()).isEqualTo(9);
+    }
+
     private void assertValid(Notification.Colors c) {
         // Assert that all colors are populated
         assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID);
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index 852d696..1a8e75a 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -40,6 +40,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.IWindow;
 import android.view.IWindowSession;
+import android.view.ImeBackAnimationController;
 import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
@@ -77,6 +78,12 @@
     @Mock
     private OnBackAnimationCallback mCallback2;
     @Mock
+    private ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback mImeCallback;
+    @Mock
+    private ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback mDefaultImeCallback;
+    @Mock
+    private ImeBackAnimationController mImeBackAnimationController;
+    @Mock
     private Context mContext;
     @Mock
     private ApplicationInfo mApplicationInfo;
@@ -103,7 +110,7 @@
         doReturn(mApplicationInfo).when(mContext).getApplicationInfo();
 
         mDispatcher = new WindowOnBackInvokedDispatcher(mContext, Looper.getMainLooper());
-        mDispatcher.attachToWindow(mWindowSession, mWindow, null);
+        mDispatcher.attachToWindow(mWindowSession, mWindow, mImeBackAnimationController);
     }
 
     private void waitForIdle() {
@@ -419,4 +426,28 @@
         // onBackPressed is called from animator, so it can happen more than once.
         verify(mCallback1, atLeast(1)).onBackProgressed(any());
     }
+
+    @Test
+    public void registerImeCallbacks_onBackInvokedCallbackEnabled() throws RemoteException {
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
+        assertCallbacksSize(/* default */ 1, /* overlay */ 0);
+        assertSetCallbackInfo();
+        assertTopCallback(mImeBackAnimationController);
+
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
+        assertCallbacksSize(/* default */ 2, /* overlay */ 0);
+        assertSetCallbackInfo();
+        assertTopCallback(mImeCallback);
+    }
+
+    @Test
+    public void registerImeCallbacks_legacyBack() throws RemoteException {
+        doReturn(false).when(mApplicationInfo).isOnBackInvokedCallbackEnabled();
+
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mDefaultImeCallback);
+        assertNoSetCallbackInfo();
+
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mImeCallback);
+        assertNoSetCallbackInfo();
+    }
 }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 89d3058..e38038e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -1520,12 +1520,16 @@
     @GuardedBy("mLock")
     TaskFragmentContainer resolveStartActivityIntent(@NonNull WindowContainerTransaction wct,
             int taskId, @NonNull Intent intent, @Nullable Activity launchingActivity) {
-        // Skip resolving if started from an isolated navigated TaskFragmentContainer.
         if (launchingActivity != null) {
             final TaskFragmentContainer taskFragmentContainer = getContainerWithActivity(
                     launchingActivity);
             if (taskFragmentContainer != null
                     && taskFragmentContainer.isIsolatedNavigationEnabled()) {
+                // Skip resolving if started from an isolated navigated TaskFragmentContainer.
+                return null;
+            }
+            if (isAssociatedWithOverlay(launchingActivity)) {
+                // Skip resolving if the launching activity associated with an overlay.
                 return null;
             }
         }
@@ -1659,9 +1663,8 @@
         // is the first embedded TF in the task.
         final TaskContainer taskContainer = container.getTaskContainer();
         // TODO(b/265271880): remove redundant logic after all TF operations take fragmentToken.
-        final Rect taskBounds = taskContainer.getBounds();
         final Rect sanitizedBounds = sanitizeBounds(activityStackAttributes.getRelativeBounds(),
-                getMinDimensions(intent), taskBounds);
+                getMinDimensions(intent), container);
         final int windowingMode = taskContainer
                 .getWindowingModeForTaskFragment(sanitizedBounds);
         mPresenter.createTaskFragment(wct, taskFragmentToken, activityInTask.getActivityToken(),
@@ -1722,17 +1725,14 @@
     @GuardedBy("mLock")
     @Nullable
     TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
-        // Check pending appeared activity first because there can be a delay for the server
-        // update.
-        TaskFragmentContainer taskFragmentContainer =
-                getContainer(container -> container.hasPendingAppearedActivity(activityToken));
-        if (taskFragmentContainer != null) {
-            return taskFragmentContainer;
+        for (int i = mTaskContainers.size() - 1; i >= 0; --i) {
+            final TaskFragmentContainer container = mTaskContainers.valueAt(i)
+                    .getContainerWithActivity(activityToken);
+            if (container != null) {
+                return container;
+            }
         }
-
-
-        // Check appeared activity if there is no such pending appeared activity.
-        return getContainer(container -> container.hasAppearedActivity(activityToken));
+        return null;
     }
 
     @GuardedBy("mLock")
@@ -2096,19 +2096,7 @@
         if (container == null) {
             return null;
         }
-        final List<SplitContainer> splitContainers =
-                container.getTaskContainer().getSplitContainers();
-        if (splitContainers.isEmpty()) {
-            return null;
-        }
-        for (int i = splitContainers.size() - 1; i >= 0; i--) {
-            final SplitContainer splitContainer = splitContainers.get(i);
-            if (container.equals(splitContainer.getSecondaryContainer())
-                    || container.equals(splitContainer.getPrimaryContainer())) {
-                return splitContainer;
-            }
-        }
-        return null;
+        return container.getTaskContainer().getActiveSplitForContainer(container);
     }
 
     /**
@@ -2158,6 +2146,11 @@
             return false;
         }
 
+        if (isAssociatedWithOverlay(activity)) {
+            // Can't launch the placeholder if the activity associates an overlay.
+            return false;
+        }
+
         final TaskFragmentContainer container = getContainerWithActivity(activity);
         if (container != null && !allowLaunchPlaceholder(container)) {
             // We don't allow activity in this TaskFragment to launch placeholder.
@@ -2197,6 +2190,11 @@
      */
     @GuardedBy("mLock")
     private boolean allowLaunchPlaceholder(@NonNull TaskFragmentContainer container) {
+        if (container.isOverlay()) {
+            // Don't launch placeholder if the container is an overlay.
+            return false;
+        }
+
         final TaskFragmentContainer topContainer = container.getTaskContainer()
                 .getTopNonFinishingTaskFragmentContainer();
         if (container != topContainer) {
@@ -2470,13 +2468,10 @@
     @GuardedBy("mLock")
     TaskFragmentContainer getContainer(@NonNull Predicate<TaskFragmentContainer> predicate) {
         for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
-            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
-                    .getTaskFragmentContainers();
-            for (int j = containers.size() - 1; j >= 0; j--) {
-                final TaskFragmentContainer container = containers.get(j);
-                if (predicate.test(container)) {
-                    return container;
-                }
+            final TaskFragmentContainer container = mTaskContainers.valueAt(i)
+                    .getContainer(predicate);
+            if (container != null) {
+                return container;
             }
         }
         return null;
@@ -2641,6 +2636,16 @@
         return overlayContainers;
     }
 
+    @GuardedBy("mLock")
+    private boolean isAssociatedWithOverlay(@NonNull Activity activity) {
+        final TaskContainer taskContainer = getTaskContainer(getTaskId(activity));
+        if (taskContainer == null) {
+            return false;
+        }
+        return taskContainer.getContainer(c -> c.isOverlay() && !c.isFinished()
+                && c.getAssociatedActivityToken() == activity.getActivityToken()) != null;
+    }
+
     /**
      * Creates an overlay container or updates a visible overlay container if its
      * {@link TaskFragmentContainer#getTaskId()}, {@link TaskFragmentContainer#getOverlayTag()}
@@ -2734,7 +2739,7 @@
                 }
                 // Requesting an always-on-top overlay.
                 if (!associateLaunchingActivity) {
-                    if (overlayContainer.isAssociatedWithActivity()) {
+                    if (overlayContainer.isOverlayWithActivityAssociation()) {
                         // Dismiss the overlay container since it has associated with an activity.
                         Log.w(TAG, "The overlay container with tag:"
                                 + overlayContainer.getOverlayTag() + " is dismissed because"
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 6231ea0..0e4fb30 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -591,16 +591,14 @@
             @NonNull TaskFragmentContainer container,
             @NonNull ActivityStackAttributes attributes,
             @Nullable Size minDimensions) {
-        final Rect taskBounds = container.getTaskContainer().getBounds();
         final Rect relativeBounds = sanitizeBounds(attributes.getRelativeBounds(), minDimensions,
-                taskBounds);
+                container);
         final boolean isFillParent = relativeBounds.isEmpty();
         // Note that we only set isolated navigation for overlay container without activity
         // association. Activity will be launched to an expanded container on top of the overlay
         // if the overlay is associated with an activity. Thus, an overlay with activity association
         // will never be isolated navigated.
-        final boolean isIsolatedNavigated = container.isOverlay()
-                && !container.isAssociatedWithActivity() && !isFillParent;
+        final boolean isIsolatedNavigated = container.isAlwaysOnTopOverlay() && !isFillParent;
         final boolean dimOnTask = !isFillParent
                 && attributes.getWindowAttributes().getDimAreaBehavior() == DIM_AREA_ON_TASK
                 && Flags.fullscreenDimFlag();
@@ -624,7 +622,7 @@
      */
     @NonNull
     static Rect sanitizeBounds(@NonNull Rect bounds, @Nullable Size minDimension,
-                               @NonNull Rect taskBounds) {
+                        @NonNull TaskFragmentContainer container) {
         if (bounds.isEmpty()) {
             // Don't need to check if the bounds follows the task bounds.
             return bounds;
@@ -633,10 +631,33 @@
             // Expand the bounds if the bounds are smaller than minimum dimensions.
             return new Rect();
         }
+        final TaskContainer taskContainer = container.getTaskContainer();
+        final Rect taskBounds = taskContainer.getBounds();
         if (!taskBounds.contains(bounds)) {
             // Expand the bounds if the bounds exceed the task bounds.
             return new Rect();
         }
+
+        if (!container.isOverlay()) {
+            // Stop here if the container is not an overlay.
+            return bounds;
+        }
+
+        final IBinder associatedActivityToken = container.getAssociatedActivityToken();
+
+        if (associatedActivityToken == null) {
+            // Stop here if the container is an always-on-top overlay.
+            return bounds;
+        }
+
+        // Expand the overlay with activity association if the associated activity is part of a
+        // split, or we may need to handle three change transition together.
+        final TaskFragmentContainer associatedContainer = taskContainer
+                .getContainerWithActivity(associatedActivityToken);
+        if (taskContainer.getActiveSplitForContainer(associatedContainer) != null) {
+            return new Rect();
+        }
+
         return bounds;
     }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index fdf0910..67d34c7 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -43,6 +43,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.window.extensions.core.util.function.Predicate;
 import androidx.window.extensions.embedding.SplitAttributes.SplitType;
 import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
 import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
@@ -318,6 +319,38 @@
         return null;
     }
 
+    @Nullable
+    TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
+        return getContainer(container -> container.hasAppearedActivity(activityToken)
+                || container.hasPendingAppearedActivity(activityToken));
+    }
+
+    @Nullable
+    TaskFragmentContainer getContainer(@NonNull Predicate<TaskFragmentContainer> predicate) {
+        for (int i = mContainers.size() - 1; i >= 0; i--) {
+            final TaskFragmentContainer container = mContainers.get(i);
+            if (predicate.test(container)) {
+                return container;
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    SplitContainer getActiveSplitForContainer(@Nullable TaskFragmentContainer container) {
+        if (container == null) {
+            return null;
+        }
+        for (int i = mSplitContainers.size() - 1; i >= 0; i--) {
+            final SplitContainer splitContainer = mSplitContainers.get(i);
+            if (container.equals(splitContainer.getSecondaryContainer())
+                    || container.equals(splitContainer.getPrimaryContainer())) {
+                return splitContainer;
+            }
+        }
+        return null;
+    }
+
     /**
      * Returns the always-on-top overlay container in the task, or {@code null} if it doesn't exist.
      */
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 094ebcb..c952dfe 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -465,7 +465,7 @@
             return;
         }
         // Early return if this container is not an overlay with activity association.
-        if (!isOverlay() || !isAssociatedWithActivity()) {
+        if (!isOverlayWithActivityAssociation()) {
             return;
         }
         if (mAssociatedActivityToken == activityToken) {
@@ -500,7 +500,7 @@
         // sure the controller considers this container as the one containing the activity.
         // This is needed when the activity is added as pending appeared activity to one
         // TaskFragment while it is also an appeared activity in another.
-        return mController.getContainerWithActivity(activityToken) == this;
+        return mTaskContainer.getContainerWithActivity(activityToken) == this;
     }
 
     /** Whether this activity has appeared in the TaskFragment on the server side. */
@@ -1019,16 +1019,16 @@
         return mAssociatedActivityToken;
     }
 
-    boolean isAssociatedWithActivity() {
-        return mAssociatedActivityToken != null;
-    }
-
     /**
      * Returns {@code true} if the overlay container should be always on top, which should be
      * a non-fill-parent overlay without activity association.
      */
     boolean isAlwaysOnTopOverlay() {
-        return isOverlay() && !isAssociatedWithActivity();
+        return isOverlay() && mAssociatedActivityToken == null;
+    }
+
+    boolean isOverlayWithActivityAssociation() {
+        return isOverlay() && mAssociatedActivityToken != null;
     }
 
     @Override
@@ -1050,7 +1050,7 @@
                 + " runningActivityCount=" + getRunningActivityCount()
                 + " isFinished=" + mIsFinished
                 + " overlayTag=" + mOverlayTag
-                + " associatedActivity" + mAssociatedActivityToken
+                + " associatedActivityToken=" + mAssociatedActivityToken
                 + " lastRequestedBounds=" + mLastRequestedBounds
                 + " pendingAppearedActivities=" + mPendingAppearedActivities
                 + (includeContainersToFinishOnExit ? " containersToFinishOnExit="
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 50abdfd..fab298d 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -21,11 +21,15 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static androidx.window.extensions.embedding.ActivityEmbeddingOptionsProperties.KEY_OVERLAY_TAG;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.SPLIT_ATTRIBUTES;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_BOUNDS;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.TEST_TAG;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
 import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPairRuleBuilder;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitPlaceholderRuleBuilder;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.createSplitRule;
+import static androidx.window.extensions.embedding.SplitPresenter.sanitizeBounds;
 import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -85,6 +89,7 @@
 import org.mockito.junit.MockitoRule;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -102,6 +107,9 @@
     @Rule
     public MockitoRule rule = MockitoJUnit.rule();
 
+    private static final Intent PLACEHOLDER_INTENT = new Intent().setComponent(
+            new ComponentName("test", "placeholder"));
+
     @Rule
     public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
 
@@ -259,8 +267,7 @@
         mSplitController.setActivityStackAttributesCalculator(params ->
                 new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
         final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
-                mOverlayContainer1.getOverlayTag(),
-                mOverlayContainer1.getTopNonFinishingActivity());
+                mOverlayContainer1.getOverlayTag());
 
         assertWithMessage("overlayContainer1 must be updated since the new overlay container"
                 + " is launched with the same tag and task")
@@ -280,12 +287,13 @@
         mSplitController.setActivityStackAttributesCalculator(params ->
                 new ActivityStackAttributes.Builder().setRelativeBounds(bounds).build());
         final TaskFragmentContainer overlayContainer = createOrUpdateOverlayTaskFragmentIfNeeded(
-                mOverlayContainer1.getOverlayTag(), mActivity);
+                mOverlayContainer1.getOverlayTag(), createMockActivity());
 
         assertWithMessage("overlayContainer1 must be dismissed since the new overlay container"
                 + " is associated with different launching activity")
                 .that(mSplitController.getAllNonFinishingOverlayContainers())
                 .containsExactly(mOverlayContainer2, overlayContainer);
+        assertThat(overlayContainer).isNotEqualTo(mOverlayContainer1);
     }
 
     @Test
@@ -323,7 +331,8 @@
     }
 
     private void createExistingOverlayContainers(boolean visible) {
-        mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible);
+        mOverlayContainer1 = createTestOverlayContainer(TASK_ID, "test1", visible,
+                true /* associatedLaunchingActivity */, mActivity);
         mOverlayContainer2 = createTestOverlayContainer(TASK_ID + 1, "test2", visible);
         List<TaskFragmentContainer> overlayContainers = mSplitController
                 .getAllNonFinishingOverlayContainers();
@@ -335,17 +344,49 @@
         mIntent.setComponent(new ComponentName(ApplicationProvider.getApplicationContext(),
                 MinimumDimensionActivity.class));
         final Rect bounds = new Rect(0, 0, 100, 100);
+        final TaskFragmentContainer overlayContainer =
+                createTestOverlayContainer(TASK_ID, "test1");
 
-        SplitPresenter.sanitizeBounds(bounds, SplitPresenter.getMinDimensions(mIntent),
-                TASK_BOUNDS);
+        assertThat(sanitizeBounds(bounds, SplitPresenter.getMinDimensions(mIntent),
+                overlayContainer).isEmpty()).isTrue();
     }
 
     @Test
     public void testSanitizeBounds_notInTaskBounds_expandOverlay() {
         final Rect bounds = new Rect(TASK_BOUNDS);
         bounds.offset(10, 10);
+        final TaskFragmentContainer overlayContainer =
+                createTestOverlayContainer(TASK_ID, "test1");
 
-        SplitPresenter.sanitizeBounds(bounds, null, TASK_BOUNDS);
+        assertThat(sanitizeBounds(bounds, null, overlayContainer)
+                .isEmpty()).isTrue();
+    }
+
+    @Test
+    public void testSanitizeBounds_visibleSplit_expandOverlay() {
+        // Launch a visible split
+        final Activity primaryActivity = createMockActivity();
+        final Activity secondaryActivity = createMockActivity();
+        final TaskFragmentContainer primaryContainer =
+                createMockTaskFragmentContainer(primaryActivity, true /* isVisible */);
+        final TaskFragmentContainer secondaryContainer =
+                createMockTaskFragmentContainer(secondaryActivity, true /* isVisible */);
+
+        final SplitPairRule splitPairRule = createSplitPairRuleBuilder(
+                activityActivityPair -> true /* activityPairPredicate */,
+                activityIntentPair -> true  /* activityIntentPairPredicate */,
+                parentWindowMetrics -> true /* parentWindowMetricsPredicate */)
+                .build();
+        mSplitController.registerSplit(mTransaction, primaryContainer, primaryActivity,
+                secondaryContainer, splitPairRule,  splitPairRule.getDefaultSplitAttributes());
+
+        final Rect bounds = new Rect(0, 0, 100, 100);
+        final TaskFragmentContainer overlayContainer =
+                createTestOverlayContainer(TASK_ID, "test1", true /* isVisible */,
+                        true /* associatedLaunchingActivity */, secondaryActivity);
+
+        assertThat(sanitizeBounds(bounds, null, overlayContainer)
+                .isEmpty()).isTrue();
     }
 
     @Test
@@ -701,6 +742,70 @@
                 .doesNotContain(overlayWithAssociation);
     }
 
+    @Test
+    public void testLaunchPlaceholderIfNecessary_skipIfActivityAssociateOverlay() {
+        setupPlaceholderRule(mActivity);
+        createTestOverlayContainer(TASK_ID, "test", true /* isVisible */,
+                true /* associateLaunchingActivity */, mActivity);
+
+
+        mSplitController.mTransactionManager.startNewTransaction();
+        assertThat(mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
+                false /* isOnCreated */)).isFalse();
+
+        verify(mTransaction, never()).startActivityInTaskFragment(any(), any(), any(), any());
+    }
+
+    @Test
+    public void testLaunchPlaceholderIfNecessary_skipIfActivityInOverlay() {
+        setupPlaceholderRule(mActivity);
+        createOrUpdateOverlayTaskFragmentIfNeeded("test1", mActivity);
+
+        mSplitController.mTransactionManager.startNewTransaction();
+        assertThat(mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
+                false /* isOnCreated */)).isFalse();
+
+        verify(mTransaction, never()).startActivityInTaskFragment(any(), any(), any(), any());
+    }
+
+    /** Setups a rule to launch placeholder for the given activity. */
+    private void setupPlaceholderRule(@NonNull Activity primaryActivity) {
+        final SplitRule placeholderRule = createSplitPlaceholderRuleBuilder(PLACEHOLDER_INTENT,
+                primaryActivity::equals, i -> false, w -> true)
+                .setDefaultSplitAttributes(SPLIT_ATTRIBUTES)
+                .build();
+        mSplitController.setEmbeddingRules(Collections.singleton(placeholderRule));
+    }
+
+    @Test
+    public void testResolveStartActivityIntent_skipIfAssociateOverlay() {
+        final Intent intent = new Intent();
+        mSplitController.setEmbeddingRules(Collections.singleton(
+                createSplitRule(mActivity, intent)));
+        createTestOverlayContainer(TASK_ID, "test", true /* isVisible */,
+                true /* associateLaunchingActivity */, mActivity);
+        final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+                mTransaction, TASK_ID, intent, mActivity);
+
+        assertThat(container).isNull();
+        verify(mSplitController, never()).resolveStartActivityIntentByRule(any(), anyInt(), any(),
+                any());
+    }
+
+    @Test
+    public void testResolveStartActivityIntent_skipIfLaunchingActivityInOverlay() {
+        final Intent intent = new Intent();
+        mSplitController.setEmbeddingRules(Collections.singleton(
+                createSplitRule(mActivity, intent)));
+        createOrUpdateOverlayTaskFragmentIfNeeded("test1", mActivity);
+        final TaskFragmentContainer container = mSplitController.resolveStartActivityIntent(
+                mTransaction, TASK_ID, intent, mActivity);
+
+        assertThat(container).isNull();
+        verify(mSplitController, never()).resolveStartActivityIntentByRule(any(), anyInt(), any(),
+                any());
+    }
+
     /**
      * A simplified version of {@link SplitController#createOrUpdateOverlayTaskFragmentIfNeeded}
      */
@@ -726,9 +831,16 @@
     /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
     @NonNull
     private TaskFragmentContainer createMockTaskFragmentContainer(@NonNull Activity activity) {
+        return createMockTaskFragmentContainer(activity, false /* isVisible */);
+    }
+
+    /** Creates a mock TaskFragment that has been registered and appeared in the organizer. */
+    @NonNull
+    private TaskFragmentContainer createMockTaskFragmentContainer(
+            @NonNull Activity activity, boolean isVisible) {
         final TaskFragmentContainer container = mSplitController.newContainer(activity,
                 activity.getTaskId());
-        setupTaskFragmentInfo(container, activity, false /* isVisible */);
+        setupTaskFragmentInfo(container, activity, isVisible);
         return container;
     }
 
@@ -745,17 +857,26 @@
                 true /* associateLaunchingActivity */);
     }
 
+    @NonNull
+    private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
+                boolean isVisible, boolean associateLaunchingActivity) {
+        return createTestOverlayContainer(taskId, tag, isVisible, associateLaunchingActivity,
+                null /* launchingActivity */);
+    }
+
     // TODO(b/243518738): add more test coverage on overlay container without activity association
     //  once we have use cases.
     @NonNull
     private TaskFragmentContainer createTestOverlayContainer(int taskId, @NonNull String tag,
-                boolean isVisible, boolean associateLaunchingActivity) {
-        Activity activity = createMockActivity();
+            boolean isVisible, boolean associateLaunchingActivity,
+            @Nullable Activity launchingActivity) {
+        final Activity activity = launchingActivity != null
+                ? launchingActivity : createMockActivity();
         TaskFragmentContainer overlayContainer = mSplitController.newContainer(
                 null /* pendingAppearedActivity */, mIntent, activity, taskId,
                 null /* pairedPrimaryContainer */, tag, Bundle.EMPTY,
                 associateLaunchingActivity);
-        setupTaskFragmentInfo(overlayContainer, activity, isVisible);
+        setupTaskFragmentInfo(overlayContainer, createMockActivity(), isVisible);
         return overlayContainer;
     }
 
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index abfc9c8..44ab2c4 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -538,9 +538,7 @@
         // container1.
         container2.setInfo(mTransaction, mInfo);
 
-        assertTrue(container1.hasActivity(mActivity.getActivityToken()));
-        assertFalse(container2.hasActivity(mActivity.getActivityToken()));
-
+        assertTrue(container2.hasActivity(mActivity.getActivityToken()));
         // When the pending appeared record is removed from container1, we respect the appeared
         // record in container2.
         container1.removePendingAppearedActivity(mActivity.getActivityToken());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 8c36085..7730285 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -261,9 +261,9 @@
     }
 
     /** Whether a particular package is same as current pip package. */
-    public boolean isInPipPackage(String packageName) {
+    public boolean isPackageActiveInPip(String packageName) {
         final TaskInfo inPipTask = mPipOrganizer.getTaskInfo();
-        return packageName != null && inPipTask != null
+        return packageName != null && inPipTask != null && mPipOrganizer.isInPip()
                 && packageName.equals(SplitScreenUtils.getPackageName(inPipTask.baseIntent));
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 2a50b19..5e9451a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -201,7 +201,7 @@
     private final DisplayImeController mDisplayImeController;
     private final DisplayInsetsController mDisplayInsetsController;
     private final TransactionPool mTransactionPool;
-    private final SplitScreenTransitions mSplitTransitions;
+    private SplitScreenTransitions mSplitTransitions;
     private final SplitscreenEventLogger mLogger;
     private final ShellExecutor mMainExecutor;
     // Cache live tile tasks while entering recents, evict them from stages in finish transaction
@@ -399,6 +399,11 @@
         return mSplitTransitions;
     }
 
+    @VisibleForTesting
+    void setSplitTransitions(SplitScreenTransitions splitScreenTransitions) {
+        mSplitTransitions = splitScreenTransitions;
+    }
+
     public boolean isSplitScreenVisible() {
         return mSideStageListener.mVisible && mMainStageListener.mVisible;
     }
@@ -583,7 +588,7 @@
         options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
         wct.startTask(taskId, options);
         // If this should be mixed, send the task to avoid split handle transition directly.
-        if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(taskId, mTaskOrganizer)) {
+        if (mMixedHandler != null && mMixedHandler.isTaskInPip(taskId, mTaskOrganizer)) {
             mTaskOrganizer.applyTransaction(wct);
             return;
         }
@@ -622,7 +627,7 @@
         wct.sendPendingIntent(intent, fillInIntent, options);
 
         // If this should be mixed, just send the intent to avoid split handle transition directly.
-        if (mMixedHandler != null && mMixedHandler.shouldSplitEnterMixed(intent)) {
+        if (mMixedHandler != null && mMixedHandler.isIntentInPip(intent)) {
             mTaskOrganizer.applyTransaction(wct);
             return;
         }
@@ -711,16 +716,7 @@
                 taskId1, taskId2, splitPosition, snapPosition);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         if (taskId2 == INVALID_TASK_ID) {
-            if (mMainStage.containsTask(taskId1) || mSideStage.containsTask(taskId1)) {
-                prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
-            }
-            if (mRecentTasks.isPresent()) {
-                mRecentTasks.get().removeSplitPair(taskId1);
-            }
-            options1 = options1 != null ? options1 : new Bundle();
-            addActivityOptions(options1, null);
-            wct.startTask(taskId1, options1);
-            mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+            startSingleTask(taskId1, options1, wct, remoteTransition);
             return;
         }
 
@@ -741,11 +737,15 @@
                 "startIntentAndTask: intent=%s task1=%d position=%d snapPosition=%d",
                 pendingIntent.getIntent(), taskId, splitPosition, snapPosition);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        if (taskId == INVALID_TASK_ID) {
-            options1 = options1 != null ? options1 : new Bundle();
-            addActivityOptions(options1, null);
-            wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
-            mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+        boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent);
+        boolean secondTaskPipped = mMixedHandler.isTaskInPip(taskId, mTaskOrganizer);
+        if (taskId == INVALID_TASK_ID || secondTaskPipped) {
+            startSingleIntent(pendingIntent, fillInIntent, options1, wct, remoteTransition);
+            return;
+        }
+
+        if (firstIntentPipped) {
+            startSingleTask(taskId, options2, wct, remoteTransition);
             return;
         }
 
@@ -757,6 +757,24 @@
         startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId);
     }
 
+    /**
+     * @param taskId Starts this task in fullscreen, removing it from existing pairs if it was part
+     *               of one.
+     */
+    private void startSingleTask(int taskId, Bundle options, WindowContainerTransaction wct,
+            RemoteTransition remoteTransition) {
+        if (mMainStage.containsTask(taskId) || mSideStage.containsTask(taskId)) {
+            prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
+        }
+        if (mRecentTasks.isPresent()) {
+            mRecentTasks.get().removeSplitPair(taskId);
+        }
+        options = options != null ? options : new Bundle();
+        addActivityOptions(options, null);
+        wct.startTask(taskId, options);
+        mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+    }
+
     /** Starts a shortcut and a task to a split pair in one transition. */
     void startShortcutAndTask(ShortcutInfo shortcutInfo, @Nullable Bundle options1,
             int taskId, @Nullable Bundle options2, @SplitPosition int splitPosition,
@@ -844,6 +862,21 @@
             return;
         }
 
+        boolean handledForPipSplitLaunch = handlePippedSplitIntentsLaunch(
+                pendingIntent1,
+                pendingIntent2,
+                options1,
+                options2,
+                shortcutInfo1,
+                shortcutInfo2,
+                wct,
+                fillInIntent1,
+                fillInIntent2,
+                remoteTransition);
+        if (handledForPipSplitLaunch) {
+            return;
+        }
+
         if (!mMainStage.isActive()) {
             // Build a request WCT that will launch both apps such that task 0 is on the main stage
             // while task 1 is on the side stage.
@@ -878,6 +911,46 @@
         setEnterInstanceId(instanceId);
     }
 
+    /**
+     * Checks if either of the apps in the desired split launch is currently in Pip. If so, it will
+     * launch the non-pipped app as a fullscreen app, otherwise no-op.
+     */
+    private boolean handlePippedSplitIntentsLaunch(PendingIntent pendingIntent1,
+            PendingIntent pendingIntent2, Bundle options1, Bundle options2,
+            ShortcutInfo shortcutInfo1, ShortcutInfo shortcutInfo2, WindowContainerTransaction wct,
+            Intent fillInIntent1, Intent fillInIntent2, RemoteTransition remoteTransition) {
+        // If one of the split apps to start is in Pip, only launch the non-pip app in fullscreen
+        boolean firstIntentPipped = mMixedHandler.isIntentInPip(pendingIntent1);
+        boolean secondIntentPipped = mMixedHandler.isIntentInPip(pendingIntent2);
+        if (firstIntentPipped || secondIntentPipped) {
+            Bundle options = secondIntentPipped ? options1 : options2;
+            options = options == null ? new Bundle() : options;
+            addActivityOptions(options, null);
+            if (shortcutInfo1 != null || shortcutInfo2 != null) {
+                ShortcutInfo infoToLaunch = secondIntentPipped ? shortcutInfo1 : shortcutInfo2;
+                wct.startShortcut(mContext.getPackageName(), infoToLaunch, options);
+                mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+            } else {
+                PendingIntent intentToLaunch = secondIntentPipped ? pendingIntent1 : pendingIntent2;
+                Intent fillInIntentToLaunch = secondIntentPipped ? fillInIntent1 : fillInIntent2;
+                startSingleIntent(intentToLaunch, fillInIntentToLaunch, options, wct,
+                        remoteTransition);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /** @param pendingIntent Starts this intent in fullscreen */
+    private void startSingleIntent(PendingIntent pendingIntent, Intent fillInIntent, Bundle options,
+            WindowContainerTransaction wct,
+            RemoteTransition remoteTransition) {
+        Bundle optionsToLaunch = options != null ? options : new Bundle();
+        addActivityOptions(optionsToLaunch, null);
+        wct.sendPendingIntent(pendingIntent, fillInIntent, optionsToLaunch);
+        mSplitTransitions.startFullscreenTransition(wct, remoteTransition);
+    }
+
     /** Starts a pair of tasks using legacy transition. */
     void startTasksWithLegacyTransition(int taskId1, @Nullable Bundle options1,
             int taskId2, @Nullable Bundle options2, @SplitPosition int splitPosition,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 4bc0dc0..4d02ec2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -563,22 +563,23 @@
 
     /** Use to when split use intent to enter, check if this enter transition should be mixed or
      * not.*/
-    public boolean shouldSplitEnterMixed(PendingIntent intent) {
+    public boolean isIntentInPip(PendingIntent intent) {
         // Check if this intent package is same as pip one or not, if true we want let the pip
         // task enter split.
         if (mPipHandler != null) {
-            return mPipHandler.isInPipPackage(SplitScreenUtils.getPackageName(intent.getIntent()));
+            return mPipHandler
+                    .isPackageActiveInPip(SplitScreenUtils.getPackageName(intent.getIntent()));
         }
         return false;
     }
 
     /** Use to when split use taskId to enter, check if this enter transition should be mixed or
      * not.*/
-    public boolean shouldSplitEnterMixed(int taskId, ShellTaskOrganizer shellTaskOrganizer) {
+    public boolean isTaskInPip(int taskId, ShellTaskOrganizer shellTaskOrganizer) {
         // Check if this intent package is same as pip one or not, if true we want let the pip
         // task enter split.
         if (mPipHandler != null) {
-            return mPipHandler.isInPipPackage(
+            return mPipHandler.isPackageActiveInPip(
                     SplitScreenUtils.getPackageName(taskId, shellTaskOrganizer));
         }
         return false;
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
index 5b2ffec..4dd14f4 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
index 9f7d9fc..5c86a38 100644
--- a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
index 882b200..aa70c09 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
index f5a8655..bf040d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
index 51a55e35..c7c804f2 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
index 05f937a..214bdfa 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
@@ -20,6 +20,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index d819261..d7c3835 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -40,10 +40,12 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.PendingIntent;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -51,6 +53,7 @@
 import android.os.Looper;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.window.RemoteTransition;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
@@ -74,6 +77,7 @@
 import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.DefaultMixedHandler;
 import com.android.wm.shell.transition.HomeTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 
@@ -111,6 +115,8 @@
     private TransactionPool mTransactionPool;
     @Mock
     private LaunchAdjacentController mLaunchAdjacentController;
+    @Mock
+    private DefaultMixedHandler mDefaultMixedHandler;
 
     private final Rect mBounds1 = new Rect(10, 20, 30, 40);
     private final Rect mBounds2 = new Rect(5, 10, 15, 20);
@@ -370,6 +376,96 @@
         }
     }
 
+    @Test
+    public void testSplitIntentAndTaskWithPippedApp_launchFullscreen() {
+        int taskId = 9;
+        SplitScreenTransitions splitScreenTransitions =
+                spy(mStageCoordinator.getSplitTransitions());
+        mStageCoordinator.setSplitTransitions(splitScreenTransitions);
+        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
+        PendingIntent pendingIntent = mock(PendingIntent.class);
+        RemoteTransition remoteTransition = mock(RemoteTransition.class);
+        when(remoteTransition.getDebugName()).thenReturn("");
+        // Test launching second task full screen
+        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
+        mStageCoordinator.startIntentAndTask(
+                pendingIntent,
+                null /*fillInIntent*/,
+                null /*option1*/,
+                taskId,
+                null /*option2*/,
+                0 /*splitPosition*/,
+                1 /*snapPosition*/,
+                remoteTransition /*remoteTransition*/,
+                null /*instanceId*/);
+        verify(splitScreenTransitions, times(1))
+                .startFullscreenTransition(any(), any());
+
+        // Test launching first intent fullscreen
+        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false);
+        when(mDefaultMixedHandler.isTaskInPip(taskId, mTaskOrganizer)).thenReturn(true);
+        mStageCoordinator.startIntentAndTask(
+                pendingIntent,
+                null /*fillInIntent*/,
+                null /*option1*/,
+                taskId,
+                null /*option2*/,
+                0 /*splitPosition*/,
+                1 /*snapPosition*/,
+                remoteTransition /*remoteTransition*/,
+                null /*instanceId*/);
+        verify(splitScreenTransitions, times(2))
+                .startFullscreenTransition(any(), any());
+    }
+
+    @Test
+    public void testSplitIntentsWithPippedApp_launchFullscreen() {
+        SplitScreenTransitions splitScreenTransitions =
+                spy(mStageCoordinator.getSplitTransitions());
+        mStageCoordinator.setSplitTransitions(splitScreenTransitions);
+        mStageCoordinator.setMixedHandler(mDefaultMixedHandler);
+        PendingIntent pendingIntent = mock(PendingIntent.class);
+        PendingIntent pendingIntent2 = mock(PendingIntent.class);
+        RemoteTransition remoteTransition = mock(RemoteTransition.class);
+        when(remoteTransition.getDebugName()).thenReturn("");
+        // Test launching second task full screen
+        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(true);
+        mStageCoordinator.startIntents(
+                pendingIntent,
+                null /*fillInIntent*/,
+                null /*shortcutInfo1*/,
+                new Bundle(),
+                pendingIntent2,
+                null /*fillInIntent2*/,
+                null /*shortcutInfo1*/,
+                new Bundle(),
+                0 /*splitPosition*/,
+                1 /*snapPosition*/,
+                remoteTransition /*remoteTransition*/,
+                null /*instanceId*/);
+        verify(splitScreenTransitions, times(1))
+                .startFullscreenTransition(any(), any());
+
+        // Test launching first intent fullscreen
+        when(mDefaultMixedHandler.isIntentInPip(pendingIntent)).thenReturn(false);
+        when(mDefaultMixedHandler.isIntentInPip(pendingIntent2)).thenReturn(true);
+        mStageCoordinator.startIntents(
+                pendingIntent,
+                null /*fillInIntent*/,
+                null /*shortcutInfo1*/,
+                new Bundle(),
+                pendingIntent2,
+                null /*fillInIntent2*/,
+                null /*shortcutInfo1*/,
+                new Bundle(),
+                0 /*splitPosition*/,
+                1 /*snapPosition*/,
+                remoteTransition /*remoteTransition*/,
+                null /*instanceId*/);
+        verify(splitScreenTransitions, times(2))
+                .startFullscreenTransition(any(), any());
+    }
+
     private Transitions createTestTransitions() {
         ShellInit shellInit = new ShellInit(mMainExecutor);
         final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 45253bb..68b81db 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -22,6 +22,9 @@
     <!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V  -->
     <integer name="config_chargingFastThreshold">7500000</integer>
 
+    <!-- Threshold in micro watts above which a charger is rated as "fast"; 20W  -->
+    <integer name="config_chargingFastThreshold_v2">20000000</integer>
+
     <!-- When true, show 1/2G networks as 3G. -->
     <bool name="config_showMin3G">false</bool>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index 2032328..f659e38 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -145,7 +145,8 @@
         final int slowThreshold = context.getResources().getInteger(
                 R.integer.config_chargingSlowlyThreshold);
         final int fastThreshold = context.getResources().getInteger(
-                R.integer.config_chargingFastThreshold);
+                getFastChargingThresholdResId());
+
         return maxChargingWattage <= 0 ? CHARGING_UNKNOWN :
                 maxChargingWattage < slowThreshold ? CHARGING_SLOWLY :
                         maxChargingWattage > fastThreshold ? CHARGING_FAST :
@@ -382,7 +383,7 @@
                 < context.getResources().getInteger(R.integer.config_chargingSlowlyThreshold)) {
             return CHARGING_SLOWLY;
         } else if (maxChargingMicroWatt
-                > context.getResources().getInteger(R.integer.config_chargingFastThreshold)) {
+                > context.getResources().getInteger(getFastChargingThresholdResId())) {
             return CHARGING_FAST;
         } else {
             return CHARGING_REGULAR;
@@ -410,4 +411,10 @@
             return -1;
         }
     }
+
+    private static int getFastChargingThresholdResId() {
+        return BatteryUtils.isChargingStringV2Enabled()
+                        ? R.integer.config_chargingFastThreshold_v2
+                        : R.integer.config_chargingFastThreshold;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
index 327e470..ca3af53 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryUtils.java
@@ -27,6 +27,7 @@
 import android.util.ArraySet;
 import android.view.accessibility.AccessibilityManager;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import java.util.List;
@@ -97,9 +98,18 @@
     /** Used to override the system property to enable or reset for charging string V2. */
     @VisibleForTesting
     public static void setChargingStringV2Enabled(Boolean enabled) {
-        SystemProperties.set(
-                BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY,
-                enabled == null ? "" : String.valueOf(enabled));
+        setChargingStringV2Enabled(enabled, true /* updateProperty */);
+    }
+
+    /** Used to override the system property to enable or reset for charging string V2. */
+    @VisibleForTesting
+    public static void setChargingStringV2Enabled(
+            @Nullable Boolean enabled, boolean updateProperty) {
+        if (updateProperty) {
+            SystemProperties.set(
+                    BatteryUtils.PROPERTY_CHARGING_STRING_V2_KEY,
+                    enabled == null ? "" : String.valueOf(enabled));
+        }
         BatteryUtils.sChargingStringV2Enabled = enabled;
     }
 }
diff --git a/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
index 6c0c1a7..4940610 100644
--- a/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
+++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/fuelgague/BatteryStatusTest.kt
@@ -38,6 +38,7 @@
 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_SLOWLY
 import com.android.settingslib.fuelgauge.BatteryStatus.CHARGING_UNKNOWN
 import com.android.settingslib.fuelgauge.BatteryStatus.isBatteryDefender
+import com.android.settingslib.fuelgauge.BatteryUtils
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import java.util.Optional
@@ -253,12 +254,17 @@
         private val maxChargingCurrent: Optional<Int>,
         private val maxChargingVoltage: Optional<Int>,
         private val expectedChargingSpeed: Int,
+        private val chargingStringV2Enabled: Boolean,
     ) {
 
         val context: Context = ApplicationProvider.getApplicationContext()
 
         @Test
         fun getChargingSpeed_() {
+            BatteryUtils.setChargingStringV2Enabled(
+                chargingStringV2Enabled,
+                false /* updateProperty */
+            )
             val batteryChangedIntent =
                 Intent(Intent.ACTION_BATTERY_CHANGED).apply {
                     maxChargingCurrent.ifPresent { putExtra(EXTRA_MAX_CHARGING_CURRENT, it) }
@@ -278,37 +284,57 @@
                         "maxCurrent=n/a, maxVoltage=n/a -> UNKNOWN",
                         Optional.empty<Int>(),
                         Optional.empty<Int>(),
-                        CHARGING_UNKNOWN
+                        CHARGING_UNKNOWN,
+                        false /* chargingStringV2Enabled */
                     ),
                     arrayOf(
                         "maxCurrent=0, maxVoltage=9000000 -> UNKNOWN",
                         Optional.of(0),
                         Optional.of(0),
-                        CHARGING_UNKNOWN
+                        CHARGING_UNKNOWN,
+                        false /* chargingStringV2Enabled */
                     ),
                     arrayOf(
                         "maxCurrent=1500000, maxVoltage=5000000 -> CHARGING_REGULAR",
                         Optional.of(1500000),
                         Optional.of(5000000),
-                        CHARGING_REGULAR
+                        CHARGING_REGULAR,
+                        false /* chargingStringV2Enabled */
                     ),
                     arrayOf(
                         "maxCurrent=1000000, maxVoltage=5000000 -> CHARGING_REGULAR",
                         Optional.of(1000000),
                         Optional.of(5000000),
-                        CHARGING_REGULAR
+                        CHARGING_REGULAR,
+                        false /* chargingStringV2Enabled */
                     ),
                     arrayOf(
                         "maxCurrent=1500001, maxVoltage=5000000 -> CHARGING_FAST",
                         Optional.of(1501000),
                         Optional.of(5000000),
-                        CHARGING_FAST
+                        CHARGING_FAST,
+                        false /* chargingStringV2Enabled */
                     ),
                     arrayOf(
                         "maxCurrent=999999, maxVoltage=5000000 -> CHARGING_SLOWLY",
                         Optional.of(999999),
                         Optional.of(5000000),
-                        CHARGING_SLOWLY
+                        CHARGING_SLOWLY,
+                        false /* chargingStringV2Enabled */
+                    ),
+                    arrayOf(
+                        "maxCurrent=3000000, maxVoltage=9000000 -> CHARGING_FAST",
+                        Optional.of(3000000),
+                        Optional.of(9000000),
+                        CHARGING_FAST,
+                        true /* chargingStringV2Enabled */
+                    ),
+                    arrayOf(
+                        "maxCurrent=2200000, maxVoltage=9000000 -> CHARGING_REGULAR",
+                        Optional.of(2200000),
+                        Optional.of(9000000),
+                        CHARGING_REGULAR,
+                        true /* chargingStringV2Enabled */
                     ),
                 )
         }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
index c73656e..f1cc71b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/mediaoutput/MediaOutputModule.kt
@@ -16,9 +16,9 @@
 
 package com.android.systemui.volume.panel.component.mediaoutput
 
-import com.android.systemui.volume.panel.component.mediaoutput.domain.MediaOutputAvailabilityCriteria
 import com.android.systemui.volume.panel.component.mediaoutput.ui.composable.MediaOutputComponent
 import com.android.systemui.volume.panel.component.shared.model.VolumePanelComponents
+import com.android.systemui.volume.panel.domain.AlwaysAvailableCriteria
 import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
 import com.android.systemui.volume.panel.shared.model.VolumePanelUiComponent
 import dagger.Binds
@@ -39,6 +39,6 @@
     @IntoMap
     @StringKey(VolumePanelComponents.MEDIA_OUTPUT)
     fun bindComponentAvailabilityCriteria(
-        criteria: MediaOutputAvailabilityCriteria
+        criteria: AlwaysAvailableCriteria
     ): ComponentAvailabilityCriteria
 }
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index fb8a271..2f50bbd 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -62,7 +62,7 @@
 
 NOTE: in case these instructions become stale and don't actually enable the
 framework, please make sure `SceneContainerFlag.isEnabled` in the
-[`SceneContainerFlags.kt`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt)
+[`SceneContainerFlag.kt`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt)
 file evalutes to `true`.
 
 1.  Set a collection of **aconfig flags** to `true` by running the following
@@ -74,10 +74,9 @@
     $ adb shell device_config override systemui com.android.systemui.keyguard_wm_state_refactor true
     $ adb shell device_config override systemui com.android.systemui.media_in_scene_container true
     $ adb shell device_config override systemui com.android.systemui.migrate_clocks_to_blueprint true
-    $ adb shell device_config override systemui com.android.systemui.notification_heads_up_refactor true
+    $ adb shell device_config override systemui com.android.systemui.notifications_heads_up_refactor true
     $ adb shell device_config override systemui com.android.systemui.predictive_back_sysui true
     $ adb shell device_config override systemui com.android.systemui.device_entry_udfps_refactor true
-    $ adb shell device_config override systemui com.android.systemui.refactor_keyguard_dismiss_intent true
     ```
 2.  **Restart** System UI by issuing the following command:
     ```console
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
similarity index 85%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
index 0a29821..3b6f6a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractorTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -12,20 +12,19 @@
  * 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.systemui.keyguard.domain.interactor
 
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
-import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.common.ui.domain.interactor.configurationInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.doze.util.BurnInHelperWrapper
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.keyguard.data.repository.FakeCommandQueue
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
 import com.android.systemui.keyguard.shared.model.StatusBarState
@@ -33,7 +32,10 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor
+import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.statusbar.phone.SystemUIDialogManager
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.argumentCaptor
@@ -50,15 +52,18 @@
 import org.mockito.Mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @ExperimentalCoroutinesApi
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class UdfpsKeyguardInteractorTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class UdfpsKeyguardInteractorTest(flags: FlagsParameterization?) : SysuiTestCase() {
     val kosmos = testKosmos()
     val testScope = kosmos.testScope
-    val configRepository = kosmos.fakeConfigurationRepository
     val keyguardRepository = kosmos.fakeKeyguardRepository
+    val shadeRepository = kosmos.fakeShadeRepository
+    val shadeTestUtil by lazy { kosmos.shadeTestUtil }
 
     private val burnInProgress = 1f
     private val burnInYOffset = 20
@@ -67,7 +72,6 @@
     private lateinit var bouncerRepository: KeyguardBouncerRepository
     private lateinit var fakeCommandQueue: FakeCommandQueue
     private lateinit var burnInInteractor: BurnInInteractor
-    private lateinit var shadeRepository: FakeShadeRepository
     private lateinit var powerInteractor: PowerInteractor
 
     @Mock private lateinit var burnInHelper: BurnInHelperWrapper
@@ -75,11 +79,22 @@
 
     private lateinit var underTest: UdfpsKeyguardInteractor
 
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf().andSceneContainer()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         bouncerRepository = FakeKeyguardBouncerRepository()
-        shadeRepository = FakeShadeRepository()
         fakeCommandQueue = FakeCommandQueue()
         burnInInteractor =
             BurnInInteractor(
@@ -93,10 +108,10 @@
 
         underTest =
             UdfpsKeyguardInteractor(
-                configRepository,
                 burnInInteractor,
                 kosmos.keyguardInteractor,
-                shadeRepository,
+                kosmos.shadeInteractor,
+                kosmos.shadeLockscreenInteractor,
                 dialogManager,
             )
     }
@@ -183,13 +198,13 @@
             val qsProgress by collectLastValue(underTest.qsProgress)
             assertThat(qsProgress).isEqualTo(0f)
 
-            shadeRepository.setQsExpansion(.22f)
+            shadeTestUtil.setQsExpansion(.22f)
             assertThat(qsProgress).isEqualTo(.44f)
 
-            shadeRepository.setQsExpansion(.5f)
+            shadeTestUtil.setQsExpansion(.5f)
             assertThat(qsProgress).isEqualTo(1f)
 
-            shadeRepository.setQsExpansion(.7f)
+            shadeTestUtil.setQsExpansion(.7f)
             assertThat(qsProgress).isEqualTo(1f)
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
deleted file mode 100644
index 96b4dae..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.volume.panel.component.mediaoutput.domain
-
-import android.media.AudioManager
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.testKosmos
-import com.android.systemui.volume.data.repository.audioRepository
-import com.android.systemui.volume.domain.interactor.audioModeInteractor
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@RunWithLooper(setAsMainLooper = true)
-class MediaOutputAvailabilityCriteriaTest : SysuiTestCase() {
-
-    private val kosmos = testKosmos()
-
-    private lateinit var underTest: MediaOutputAvailabilityCriteria
-
-    @Before
-    fun setup() {
-        underTest =
-            MediaOutputAvailabilityCriteria(
-                kosmos.audioModeInteractor,
-            )
-    }
-
-    @Test
-    fun notInCall_isAvailable_true() {
-        with(kosmos) {
-            testScope.runTest {
-                audioRepository.setMode(AudioManager.MODE_NORMAL)
-
-                val isAvailable by collectLastValue(underTest.isAvailable())
-                runCurrent()
-
-                assertThat(isAvailable).isTrue()
-            }
-        }
-    }
-
-    @Test
-    fun inCall_isAvailable_false() {
-        with(kosmos) {
-            testScope.runTest {
-                audioRepository.setMode(AudioManager.MODE_IN_CALL)
-
-                val isAvailable by collectLastValue(underTest.isAvailable())
-                runCurrent()
-
-                assertThat(isAvailable).isFalse()
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
index b5c5809..64c9429 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractorTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.volume.localMediaController
 import com.android.systemui.volume.mediaControllerRepository
 import com.android.systemui.volume.mediaOutputInteractor
+import com.android.systemui.volume.panel.shared.model.filterData
 import com.android.systemui.volume.remoteMediaController
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -67,7 +68,8 @@
     fun playbackInfo_returnsPlaybackInfo() {
         with(kosmos) {
             testScope.runTest {
-                val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+                val session by
+                    collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
                 runCurrent()
                 val info by collectLastValue(underTest.playbackInfo(session!!))
                 runCurrent()
@@ -81,7 +83,8 @@
     fun playbackState_returnsPlaybackState() {
         with(kosmos) {
             testScope.runTest {
-                val session by collectLastValue(mediaOutputInteractor.defaultActiveMediaSession)
+                val session by
+                    collectLastValue(mediaOutputInteractor.defaultActiveMediaSession.filterData())
                 runCurrent()
                 val state by collectLastValue(underTest.playbackState(session!!))
                 runCurrent()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
index 30524d9..49f82d4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModelTest.kt
@@ -30,6 +30,8 @@
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
+import com.android.systemui.volume.domain.interactor.audioOutputInteractor
 import com.android.systemui.volume.localMediaController
 import com.android.systemui.volume.localMediaRepository
 import com.android.systemui.volume.mediaControllerRepository
@@ -64,6 +66,8 @@
                     testScope.backgroundScope,
                     mediaOutputActionsInteractor,
                     mediaDeviceSessionInteractor,
+                    audioOutputInteractor,
+                    audioModeInteractor,
                     mediaOutputInteractor,
                     uiEventLogger,
                 )
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 40d863d..dcdd4f0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1634,12 +1634,15 @@
     <!-- Hint for accessibility. A stream name is a parameter. For example: double tap to unmute media [CHAR_LIMIT=NONE] -->
     <string name="volume_panel_hint_unmute">unmute %s</string>
 
-    <!-- Title with application label for media output settings. [CHAR LIMIT=20] -->
+    <!-- Title with application label for media output settings when there is media playing. [CHAR LIMIT=20] -->
     <string name="media_output_label_title">Playing <xliff:g id="label" example="Music Player">%s</xliff:g> on</string>
 
     <!-- Title for media output settings without media is playing. [CHAR LIMIT=20] -->
     <string name="media_output_title_without_playing">Audio will play on</string>
 
+    <!-- Title for media output settings when there is an ongoing call in progress. [CHAR LIMIT=20] -->
+    <string name="media_output_title_ongoing_call">Calling on</string>
+
     <!-- Name of special SystemUI debug settings -->
     <string name="system_ui_tuner">System UI Tuner</string>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index b916fc2..91fb688 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -81,7 +81,6 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardWmStateRefactor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
@@ -304,7 +303,7 @@
          */
         @Override
         public void finish(int targetUserId) {
-            if (!RefactorKeyguardDismissIntent.isEnabled()) {
+            if (!SceneContainerFlag.isEnabled()) {
                 // If there's a pending runnable because the user interacted with a widget
                 // and we're leaving keyguard, then run it.
                 boolean deferKeyguardDone = false;
@@ -614,7 +613,7 @@
      * @param action callback to be invoked when keyguard disappear animation completes.
      */
     public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
-        if (RefactorKeyguardDismissIntent.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             return;
         }
         if (mCancelAction != null) {
@@ -908,7 +907,7 @@
             mUiEventLogger.log(uiEvent, getSessionId());
         }
 
-        if (RefactorKeyguardDismissIntent.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             if (authenticatedWithPrimaryAuth) {
                 mPrimaryBouncerInteractor.get()
                         .notifyKeyguardAuthenticatedPrimaryAuth(targetUserId);
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index b8af59d..4c9af66 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -121,6 +121,9 @@
             SystemProperties.getBoolean("debug.disable_screen_decorations", false);
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
             SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
+
+    private static final boolean sToolkitSetFrameRateReadOnly =
+            android.view.flags.Flags.toolkitSetFrameRateReadOnly();
     private boolean mDebug = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
     private int mDebugColor = Color.RED;
 
@@ -892,6 +895,10 @@
         lp.width = MATCH_PARENT;
         lp.height = MATCH_PARENT;
         lp.setTitle("ScreenDecorHwcOverlay");
+        if (sToolkitSetFrameRateReadOnly) {
+            lp.setFrameRateBoostOnTouchEnabled(false);
+            lp.setFrameRatePowerSavingsBalanced(false);
+        }
         lp.gravity = Gravity.TOP | Gravity.START;
         if (!mDebug) {
             lp.setColorMode(ActivityInfo.COLOR_MODE_A8);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
index f5cd767..63bfba6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/UdfpsKeyguardInteractor.kt
@@ -19,10 +19,10 @@
 
 import android.animation.FloatEvaluator
 import android.animation.IntEvaluator
-import com.android.systemui.common.ui.data.repository.ConfigurationRepository
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.StatusBarState
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialogManager
 import com.android.systemui.statusbar.phone.hideAffordancesRequest
 import javax.inject.Inject
@@ -38,17 +38,16 @@
 class UdfpsKeyguardInteractor
 @Inject
 constructor(
-    configRepo: ConfigurationRepository,
     burnInInteractor: BurnInInteractor,
     keyguardInteractor: KeyguardInteractor,
-    shadeRepository: ShadeRepository,
+    shadeInteractor: ShadeInteractor,
+    shadeLockscreenInteractor: ShadeLockscreenInteractor,
     dialogManager: SystemUIDialogManager,
 ) {
     private val intEvaluator = IntEvaluator()
     private val floatEvaluator = FloatEvaluator()
 
     val dozeAmount = keyguardInteractor.dozeAmount
-    val scaleForResolution = configRepo.scaleForResolution
 
     /** Burn-in offsets for the UDFPS view to mitigate burn-in on AOD. */
     val burnInOffsets: Flow<Offsets> =
@@ -68,13 +67,14 @@
     val dialogHideAffordancesRequest: Flow<Boolean> = dialogManager.hideAffordancesRequest
 
     val qsProgress: Flow<Float> =
-        shadeRepository.qsExpansion // swipe from top of LS
+        shadeInteractor.qsExpansion // swipe from top of LS
             .map { (it * 2).coerceIn(0f, 1f) }
             .onStart { emit(0f) }
 
     val shadeExpansion: Flow<Float> =
         combine(
-                shadeRepository.udfpsTransitionToFullShadeProgress, // swipe from middle of LS
+                shadeLockscreenInteractor
+                    .udfpsTransitionToFullShadeProgress, // swipe from middle of LS
                 keyguardInteractor.statusBarState, // quick swipe from middle of LS
             ) { shadeProgress, statusBarState ->
                 if (statusBarState == StatusBarState.SHADE_LOCKED) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
deleted file mode 100644
index a43eb71..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/RefactorKeyguardDismissIntent.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.keyguard.shared
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the refactor_keyguard_dismiss_intent flag. */
-@Suppress("NOTHING_TO_INLINE")
-object RefactorKeyguardDismissIntent {
-    /** The aconfig flag name */
-    const val FLAG_NAME = Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
-
-    /** A token used for dependency declaration */
-    val token: FlagToken
-        get() = FlagToken(FLAG_NAME, isEnabled)
-
-    /** Is the refactor enabled */
-    @JvmStatic
-    inline val isEnabled
-        get() = Flags.refactorKeyguardDismissIntent()
-
-    /**
-     * Called to ensure code is only run when the flag is enabled. This protects users from the
-     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
-     * build to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun isUnexpectedlyInLegacyMode() =
-        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
-    /**
-     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
-     * the flag is enabled to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
index 93b3ba5..b293027 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
@@ -20,8 +20,8 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.log.core.LogLevel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -40,7 +40,7 @@
 ) : CoreStartable {
 
     override fun start() {
-        if (!RefactorKeyguardDismissIntent.isEnabled) {
+        if (!SceneContainerFlag.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
index f77d012..ac24591 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissBinder.kt
@@ -22,9 +22,9 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardDone
 import com.android.systemui.log.core.LogLevel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -44,7 +44,7 @@
 ) : CoreStartable {
 
     override fun start() {
-        if (!RefactorKeyguardDismissIntent.isEnabled) {
+        if (!SceneContainerFlag.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
index 24429fa..e0a3af6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/BouncerToGoneFlows.kt
@@ -19,11 +19,11 @@
 import com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import dagger.Lazy
@@ -48,7 +48,7 @@
 ) {
     /** Common fade for scrim alpha values during *BOUNCER->GONE */
     fun scrimAlpha(duration: Duration, fromState: KeyguardState): Flow<ScrimAlpha> {
-        return if (RefactorKeyguardDismissIntent.isEnabled) {
+        return if (SceneContainerFlag.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index a08a234..b1fa710 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -20,11 +20,11 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import dagger.Lazy
 import javax.inject.Inject
@@ -80,7 +80,7 @@
 
     /** Bouncer container alpha */
     val bouncerAlpha: Flow<Float> =
-        if (RefactorKeyguardDismissIntent.isEnabled) {
+        if (SceneContainerFlag.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
@@ -104,7 +104,7 @@
 
     /** Lockscreen alpha */
     val lockscreenAlpha: Flow<Float> =
-        if (RefactorKeyguardDismissIntent.isEnabled) {
+        if (SceneContainerFlag.isEnabled) {
             keyguardDismissActionInteractor
                 .get()
                 .willAnimateDismissActionOnLockscreen
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 4e77d13..6a6eba1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -51,8 +51,7 @@
     fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
 
     /** Check whether to use scene framework */
-    fun isSceneContainerEnabled() =
-        SceneContainerFlag.isEnabled && MediaInSceneContainerFlag.isEnabled
+    fun isSceneContainerEnabled() = SceneContainerFlag.isEnabled
 
     /** Check whether to use media refactor code */
     fun isMediaControlsRefactorEnabled() = MediaControlsRefactorFlag.isEnabled
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt
deleted file mode 100644
index 77279f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 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.systemui.media.controls.util
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the media_in_scene_container flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object MediaInSceneContainerFlag {
-    /** The aconfig flag name */
-    const val FLAG_NAME = Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
-
-    /** A token used for dependency declaration */
-    val token: FlagToken
-        get() = FlagToken(FLAG_NAME, isEnabled)
-
-    /** Is the flag enabled? */
-    @JvmStatic
-    inline val isEnabled
-        get() = Flags.mediaInSceneContainer()
-
-    /**
-     * Called to ensure code is only run when the flag is enabled. This protects users from the
-     * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
-     * build to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun isUnexpectedlyInLegacyMode() =
-        RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
-    /**
-     * Called to ensure code is only run when the flag is disabled. This will throw an exception if
-     * the flag is enabled to ensure that the refactor author catches issues in testing.
-     */
-    @JvmStatic
-    inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
index d863dcc..710142b6 100644
--- a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java
@@ -96,7 +96,7 @@
                     if (messages2 == null) {
                         return -1;
                     }
-                    return (int) (n2.when - n1.when);
+                    return (int) (n2.getWhen() - n1.getWhen());
                 }
             };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 042fb63f..4ee2db7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -75,10 +75,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        // set layer to make alpha animation of brightness slider nicer - otherwise elements
-        // of slider are animated separately and it doesn't look good. See b/329244723
-        setLayerType(LAYER_TYPE_HARDWARE, null);
-
         mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
         mQSPanel = findViewById(R.id.quick_settings_panel);
         mHeader = findViewById(R.id.header);
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
index 234eda8..cf33c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -27,8 +27,6 @@
 import com.android.systemui.keyguard.KeyguardWmStateRefactor
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.ComposeLockscreen
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent
-import com.android.systemui.media.controls.util.MediaInSceneContainerFlag
 import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor
 import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag
 
@@ -44,12 +42,10 @@
             ComposeLockscreen.isEnabled &&
                 KeyguardBottomAreaRefactor.isEnabled &&
                 KeyguardWmStateRefactor.isEnabled &&
-                MediaInSceneContainerFlag.isEnabled &&
                 MigrateClocksToBlueprint.isEnabled &&
                 NotificationsHeadsUpRefactor.isEnabled &&
                 PredictiveBackSysUiFlag.isEnabled &&
-                DeviceEntryUdfpsRefactor.isEnabled &&
-                RefactorKeyguardDismissIntent.isEnabled
+                DeviceEntryUdfpsRefactor.isEnabled
     // NOTE: Changes should also be made in getSecondaryFlags and @EnableSceneContainer
 
     /** The main aconfig flag. */
@@ -61,12 +57,10 @@
             ComposeLockscreen.token,
             KeyguardBottomAreaRefactor.token,
             KeyguardWmStateRefactor.token,
-            MediaInSceneContainerFlag.token,
             MigrateClocksToBlueprint.token,
             NotificationsHeadsUpRefactor.token,
             PredictiveBackSysUiFlag.token,
             DeviceEntryUdfpsRefactor.token,
-            RefactorKeyguardDismissIntent.token,
             // NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
         )
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index e051dab..92006a4 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -63,6 +63,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        setLayerType(LAYER_TYPE_HARDWARE, null);
 
         mSlider = requireViewById(R.id.slider);
         mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 67211b1..4d4d177 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -244,6 +244,7 @@
 
 import kotlinx.coroutines.CoroutineDispatcher;
 import kotlinx.coroutines.flow.Flow;
+import kotlinx.coroutines.flow.StateFlow;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -3991,7 +3992,12 @@
                 mExpandLatencyTracking = false;
             }
             float maxPanelHeight = getMaxPanelTransitionDistance();
-            if (mHeightAnimator == null) {
+            if (mHeightAnimator == null && !MigrateClocksToBlueprint.isEnabled()) {
+                // MigrateClocksToBlueprint - There is an edge case where swiping up slightly,
+                // and then swiping down will trigger overscroll logic. Even without this flag
+                // enabled, the notifications can then run into UDFPS. At this point it is
+                // safer to remove overscroll for this one case to prevent overlap.
+
                 // Split shade has its own overscroll logic
                 if (isTracking()) {
                     float overExpansionPixels = Math.max(0, h - maxPanelHeight);
@@ -4055,6 +4061,11 @@
     }
 
     @Override
+    public StateFlow<Float> getUdfpsTransitionToFullShadeProgress() {
+        return mShadeRepository.getUdfpsTransitionToFullShadeProgress();
+    }
+
+    @Override
     public Flow<Float> getLegacyPanelExpansion() {
         return  mShadeRepository.getLegacyShadeExpansion();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
index 0c41efd..9322d31 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
 import java.util.function.Consumer
 import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.flowOf
 
 /** Empty implementation of ShadeViewController for variants with no shade. */
@@ -92,6 +93,7 @@
     override val shadeFoldAnimator = ShadeFoldAnimatorEmptyImpl()
     @Deprecated("Use SceneInteractor.currentScene instead.")
     override val legacyPanelExpansion = flowOf(0f)
+    override val udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
 }
 
 class ShadeHeadsUpTrackerEmptyImpl : ShadeHeadsUpTracker {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 5c79e1e..b934d63 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -28,7 +28,7 @@
      * Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
      * Settings can be expanded without the full shade expansion.
      */
-    val qsExpansion: StateFlow<Float>
+    @Deprecated("Use ShadeInteractor.qsExpansion instead") val qsExpansion: StateFlow<Float>
 
     /** Amount shade has expanded with regard to the UDFPS location */
     val udfpsTransitionToFullShadeProgress: StateFlow<Float>
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
index 2611092..987c016 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
@@ -15,9 +15,14 @@
  */
 package com.android.systemui.shade.domain.interactor
 
+import kotlinx.coroutines.flow.StateFlow
+
 /** Allows the lockscreen to control the shade. */
 interface ShadeLockscreenInteractor {
 
+    /** Amount shade has expanded with regard to the UDFPS location */
+    val udfpsTransitionToFullShadeProgress: StateFlow<Float>
+
     /**
      * Expand shade so that notifications are visible. Non-split shade: just expanding shade or
      * collapsing QS when they're expanded. Split shade: only expanding shade, notifications are
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
index 318da55..6a8b9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.shade.data.repository.ShadeRepository
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
@@ -32,7 +33,12 @@
     private val shadeInteractor: ShadeInteractor,
     private val sceneInteractor: SceneInteractor,
     private val lockIconViewController: LockIconViewController,
+    shadeRepository: ShadeRepository,
 ) : ShadeLockscreenInteractor {
+
+    override val udfpsTransitionToFullShadeProgress =
+        shadeRepository.udfpsTransitionToFullShadeProgress
+
     override fun expandToNotifications() {
         changeToShadeScene()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d465973..4d7dacd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 
 import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
 import com.android.systemui.media.controls.shared.model.MediaData;
@@ -47,6 +48,7 @@
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.concurrent.Executor;
 
 /**
  * Handles tasks and state related to media notifications. For example, there is a 'current' media
@@ -75,6 +77,8 @@
     private final Context mContext;
     private final ArrayList<MediaListener> mMediaListeners;
 
+    private final Executor mBackgroundExecutor;
+
     protected NotificationPresenter mPresenter;
     private MediaController mMediaController;
     private String mMediaNotificationKey;
@@ -115,13 +119,15 @@
             NotifPipeline notifPipeline,
             NotifCollection notifCollection,
             MediaDataManager mediaDataManager,
-            DumpManager dumpManager) {
+            DumpManager dumpManager,
+            @Background Executor backgroundExecutor) {
         mContext = context;
         mMediaListeners = new ArrayList<>();
         mVisibilityProvider = visibilityProvider;
         mMediaDataManager = mediaDataManager;
         mNotifPipeline = notifPipeline;
         mNotifCollection = notifCollection;
+        mBackgroundExecutor = backgroundExecutor;
 
         setupNotifPipeline();
 
@@ -381,9 +387,11 @@
                 Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
                         + mMediaController.getPackageName());
             }
-            mMediaController.unregisterCallback(mMediaListener);
+            mBackgroundExecutor.execute(() -> {
+                mMediaController.unregisterCallback(mMediaListener);
+                mMediaController = null;
+            });
         }
-        mMediaController = null;
     }
 
     public interface MediaListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 8a53e0c..c17da4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -31,6 +31,7 @@
 import com.android.systemui.animation.DialogTransitionAnimator;
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dump.DumpHandler;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
@@ -68,6 +69,8 @@
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
 
+import java.util.concurrent.Executor;
+
 import javax.inject.Provider;
 
 /**
@@ -94,14 +97,16 @@
             NotifPipeline notifPipeline,
             NotifCollection notifCollection,
             MediaDataManager mediaDataManager,
-            DumpManager dumpManager) {
+            DumpManager dumpManager,
+            @Background Executor backgroundExecutor) {
         return new NotificationMediaManager(
                 context,
                 visibilityProvider,
                 notifPipeline,
                 notifCollection,
                 mediaDataManager,
-                dumpManager);
+                dumpManager,
+                backgroundExecutor);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 240ae0c..9c1d073 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -1243,8 +1243,9 @@
         if (cmp != 0) return cmp;
 
         cmp = -1 * Long.compare(
-                o1.getRepresentativeEntry().getSbn().getNotification().when,
-                o2.getRepresentativeEntry().getSbn().getNotification().when);
+                o1.getRepresentativeEntry().getSbn().getNotification().getWhen(),
+                o2.getRepresentativeEntry().getSbn().getNotification().getWhen());
+
         return cmp;
     };
 
@@ -1256,8 +1257,8 @@
         if (cmp != 0) return cmp;
 
         cmp = -1 * Long.compare(
-                o1.getRepresentativeEntry().getSbn().getNotification().when,
-                o2.getRepresentativeEntry().getSbn().getNotification().when);
+                o1.getRepresentativeEntry().getSbn().getNotification().getWhen(),
+                o2.getRepresentativeEntry().getSbn().getNotification().getWhen());
         return cmp;
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
index 5ce1db2..f253100 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupWhenCoordinator.kt
@@ -89,7 +89,7 @@
         var futureTime = Long.MAX_VALUE
         groupEntry.children
             .asSequence()
-            .mapNotNull { child -> child.sbn.notification.`when`.takeIf { it > 0 } }
+            .mapNotNull { child -> child.sbn.notification.getWhen().takeIf { it > 0 } }
             .forEach { time ->
                 val isInThePast = currentTimeMillis - time > 0
                 if (isInThePast) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index fb67f7c..f98f77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -296,7 +296,9 @@
         locationLookupByKey: (String) -> GroupLocation,
     ): NotificationEntry? = postedEntries.asSequence()
         .filter { posted -> !posted.entry.sbn.notification.isGroupSummary }
-        .sortedBy { posted -> -posted.entry.sbn.notification.`when` }
+        .sortedBy { posted ->
+            -posted.entry.sbn.notification.getWhen()
+        }
         .firstOrNull()
         ?.let { posted ->
             posted.entry.takeIf { entry ->
@@ -317,7 +319,7 @@
         .filter { locationLookupByKey(it.key) != GroupLocation.Detached }
         .sortedWith(compareBy(
             { !mPostedEntries.contains(it.key) },
-            { -it.sbn.notification.`when` },
+            { -it.sbn.notification.getWhen() },
         ))
         .firstOrNull()
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
index 9619aca..bfc5932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
@@ -153,12 +153,12 @@
         uiEventId = HUN_SUPPRESSED_OLD_WHEN
     ) {
     private fun whenAge(entry: NotificationEntry) =
-        systemClock.currentTimeMillis() - entry.sbn.notification.`when`
+        systemClock.currentTimeMillis() - entry.sbn.notification.getWhen()
 
     override fun shouldSuppress(entry: NotificationEntry): Boolean =
         when {
             // Ignore a "when" of 0, as it is unlikely to be a meaningful timestamp.
-            entry.sbn.notification.`when` <= 0L -> false
+            entry.sbn.notification.getWhen() <= 0L -> false
 
             // Assume all HUNs with FSIs, foreground services, or user-initiated jobs are
             // time-sensitive, regardless of their "when".
@@ -278,7 +278,7 @@
     private fun calculateState(entry: NotificationEntry): State {
         if (
             entry.ranking.isConversation &&
-                entry.sbn.notification.`when` > avalancheProvider.startTime
+                entry.sbn.notification.getWhen() > avalancheProvider.startTime
         ) {
             return State.ALLOW_CONVERSATION_AFTER_AVALANCHE
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index d591114..9c6a423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -623,7 +623,7 @@
             return false;
         }
 
-        final long when = notification.when;
+        final long when = notification.getWhen();
         final long now = mSystemClock.currentTimeMillis();
         final long age = now - when;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index bdeaabf..5e3df7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2769,7 +2769,7 @@
         }
         if (!mIsSummaryWithChildren && wasSummary) {
             // Reset the 'when' once the row stops being a summary
-            mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().when);
+            mPublicLayout.setNotificationWhen(mEntry.getSbn().getNotification().getWhen());
         }
         getShowingLayout().updateBackgroundColor(false /* animate */);
         mPrivateLayout.updateExpandButtons(isExpandable());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index b2b2cea..7630d43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -855,6 +855,7 @@
         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
         mBubblesOptional.ifPresent(this::initBubbles);
+        mKeyguardBypassController.listenForQsExpandedChange();
 
         mStatusBarSignalPolicy.init();
         mKeyguardIndicationController.init();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index a8941bb..97791ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -21,7 +21,6 @@
 import android.content.res.Resources
 import android.hardware.biometrics.BiometricSourceType
 import android.provider.Settings
-import androidx.annotation.VisibleForTesting
 import com.android.app.tracing.ListenersTracing.forEachTraced
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.SysUISingleton
@@ -32,7 +31,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm
@@ -41,23 +40,24 @@
 import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.tuner.TunerService
+import dagger.Lazy
+import java.io.PrintWriter
+import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
-import java.io.PrintWriter
-import javax.inject.Inject
 
 @SysUISingleton
 class KeyguardBypassController @Inject constructor(
         @Main resources: Resources,
         packageManager: PackageManager,
-        @Application applicationScope: CoroutineScope,
+        @Application private val applicationScope: CoroutineScope,
         tunerService: TunerService,
         private val statusBarStateController: StatusBarStateController,
         lockscreenUserManager: NotificationLockscreenUserManager,
         private val keyguardStateController: KeyguardStateController,
-        private val shadeRepository: ShadeRepository,
+        private val shadeInteractorLazy: Lazy<ShadeInteractor>,
         devicePostureController: DevicePostureController,
         private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
         dumpManager: DumpManager
@@ -144,7 +144,6 @@
                     }
                 }
             })
-            listenForQsExpandedChange(applicationScope)
             val dismissByDefault = if (resources.getBoolean(
                             com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
             tunerService.addTunable({ key, _ ->
@@ -159,10 +158,9 @@
         }
     }
 
-    @VisibleForTesting
-    fun listenForQsExpandedChange(scope: CoroutineScope) =
-        scope.launch {
-            shadeRepository.qsExpansion.map { it > 0f }.distinctUntilChanged()
+    fun listenForQsExpandedChange() =
+        applicationScope.launch {
+            shadeInteractorLazy.get().qsExpansion.map { it > 0f }.distinctUntilChanged()
                 .collect { isQsExpanded ->
                     val changed = qsExpanded != isQsExpanded
                     qsExpanded = isQsExpanded
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f35d199..7301b87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -72,7 +72,6 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor;
-import com.android.systemui.keyguard.shared.RefactorKeyguardDismissIntent;
 import com.android.systemui.keyguard.shared.model.DismissAction;
 import com.android.systemui.keyguard.shared.model.KeyguardDone;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -800,7 +799,7 @@
 
     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
             boolean afterKeyguardGone, String message) {
-        if (RefactorKeyguardDismissIntent.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             if (r == null) {
                 return;
             }
@@ -852,7 +851,7 @@
                     return;
                 }
 
-                if (!RefactorKeyguardDismissIntent.isEnabled()) {
+                if (!SceneContainerFlag.isEnabled()) {
                     mAfterKeyguardGoneAction = r;
                     mKeyguardGoneCancelAction = cancelAction;
                     mDismissActionWillAnimateOnKeyguard = r != null
@@ -920,7 +919,7 @@
      * Adds a {@param runnable} to be executed after Keyguard is gone.
      */
     public void addAfterKeyguardGoneRunnable(Runnable runnable) {
-        if (RefactorKeyguardDismissIntent.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             if (runnable != null) {
                 mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable);
             }
@@ -1112,7 +1111,7 @@
             // We update the state (which will show the keyguard) only if an animation will run on
             // the keyguard. If there is no animation, we wait before updating the state so that we
             // go directly from bouncer to launcher/app.
-            if (RefactorKeyguardDismissIntent.isEnabled()) {
+            if (SceneContainerFlag.isEnabled()) {
                 if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) {
                     updateStates();
                 }
@@ -1239,7 +1238,7 @@
     }
 
     private void executeAfterKeyguardGoneAction() {
-        if (RefactorKeyguardDismissIntent.isEnabled()) {
+        if (SceneContainerFlag.isEnabled()) {
             return;
         }
         if (mAfterKeyguardGoneAction != null) {
@@ -1629,8 +1628,8 @@
         pw.println("  isBouncerShowing(): " + isBouncerShowing());
         pw.println("  bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing());
         pw.println("  Registered KeyguardViewManagerCallbacks:");
-        pw.println(" refactorKeyguardDismissIntent enabled:"
-                + RefactorKeyguardDismissIntent.isEnabled());
+        pw.println(" SceneContainerFlag enabled:"
+                + SceneContainerFlag.isEnabled());
         for (KeyguardViewManagerCallback callback : mCallbacks) {
             pw.println("      " + callback);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index a20468f..ec88b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -98,7 +98,7 @@
                     (entry.sbn.key == callNotificationInfo?.key)) {
                 val newOngoingCallInfo = CallNotificationInfo(
                         entry.sbn.key,
-                        entry.sbn.notification.`when`,
+                        entry.sbn.notification.getWhen(),
                         entry.sbn.notification.contentIntent,
                         entry.sbn.uid,
                         entry.sbn.notification.extras.getInt(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
index ed44699..19d9c3f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
 import javax.inject.Inject
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
@@ -69,6 +70,7 @@
                     }
                 } else {
                     mediaOutputInteractor.defaultActiveMediaSession
+                        .filterData()
                         .flatMapLatest {
                             localMediaRepositoryFactory
                                 .create(it?.packageName)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
deleted file mode 100644
index bac7d15..0000000
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteria.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.volume.panel.component.mediaoutput.domain
-
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-
-/** Determines if the Media Output Volume Panel component is available. */
-@VolumePanelScope
-class MediaOutputAvailabilityCriteria
-@Inject
-constructor(
-    private val audioModeInteractor: AudioModeInteractor,
-) : ComponentAvailabilityCriteria {
-
-    override fun isAvailable(): Flow<Boolean> = audioModeInteractor.isOngoingCall.map { !it }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 83b8029..b974f90 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -28,6 +28,9 @@
 import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSessions
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
 import javax.inject.Inject
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
@@ -72,7 +75,7 @@
         }
 
     /** Returns the default [MediaDeviceSession] from [activeMediaDeviceSessions] */
-    val defaultActiveMediaSession: StateFlow<MediaDeviceSession?> =
+    val defaultActiveMediaSession: StateFlow<Result<MediaDeviceSession?>> =
         activeMediaControllers
             .map {
                 when {
@@ -82,11 +85,13 @@
                     else -> null
                 }
             }
+            .wrapInResult()
             .flowOn(backgroundCoroutineContext)
-            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+            .stateIn(coroutineScope, SharingStarted.Eagerly, Result.Loading())
 
     private val localMediaRepository: SharedFlow<LocalMediaRepository> =
         defaultActiveMediaSession
+            .filterData()
             .map { it?.packageName }
             .distinctUntilChanged()
             .map { localMediaRepositoryFactory.create(it) }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index d60d981..192e0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -18,16 +18,21 @@
 
 import android.content.Context
 import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.Color
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.res.R
+import com.android.systemui.volume.domain.interactor.AudioOutputInteractor
+import com.android.systemui.volume.domain.model.AudioOutputDevice
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.panel.shared.model.filterData
+import com.android.systemui.volume.panel.shared.model.wrapInResult
 import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -35,6 +40,7 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.mapNotNull
@@ -50,25 +56,25 @@
     @VolumePanelScope private val coroutineScope: CoroutineScope,
     private val actionsInteractor: MediaOutputActionsInteractor,
     private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
+    audioOutputInteractor: AudioOutputInteractor,
+    audioModeInteractor: AudioModeInteractor,
     interactor: MediaOutputInteractor,
     private val uiEventLogger: UiEventLogger,
 ) {
 
     private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> =
         interactor.defaultActiveMediaSession
+            .filterData()
             .flatMapLatest { session ->
                 if (session == null) {
-                    flowOf(Result.Data<SessionWithPlaybackState?>(null))
+                    flowOf(null)
                 } else {
                     mediaDeviceSessionInteractor.playbackState(session).mapNotNull { playback ->
-                        playback?.let {
-                            Result.Data<SessionWithPlaybackState?>(
-                                SessionWithPlaybackState(session, playback.isActive())
-                            )
-                        }
+                        playback?.let { SessionWithPlaybackState(session, playback.isActive) }
                     }
                 }
             }
+            .wrapInResult()
             .stateIn(
                 coroutineScope,
                 SharingStarted.Eagerly,
@@ -76,23 +82,24 @@
             )
 
     val connectedDeviceViewModel: StateFlow<ConnectedDeviceViewModel?> =
-        combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
-                mediaDeviceSession,
-                currentConnectedDevice ->
-                if (mediaDeviceSession !is Result.Data) {
-                    return@combine null
-                }
-                ConnectedDeviceViewModel(
-                    if (mediaDeviceSession.data?.isPlaybackActive == true) {
-                        context.getString(
-                            R.string.media_output_label_title,
-                            mediaDeviceSession.data.session.appLabel
-                        )
-                    } else {
-                        context.getString(R.string.media_output_title_without_playing)
-                    },
-                    currentConnectedDevice?.name,
-                )
+        combine(
+                sessionWithPlaybackState.filterData(),
+                audioModeInteractor.isOngoingCall,
+                audioOutputInteractor.currentAudioDevice.filter {
+                    it !is AudioOutputDevice.Unknown
+                },
+            ) { mediaDeviceSession, isOngoingCall, currentConnectedDevice ->
+                val label =
+                    when {
+                        isOngoingCall -> context.getString(R.string.media_output_title_ongoing_call)
+                        mediaDeviceSession?.isPlaybackActive == true ->
+                            context.getString(
+                                R.string.media_output_label_title,
+                                mediaDeviceSession.session.appLabel
+                            )
+                        else -> context.getString(R.string.media_output_title_without_playing)
+                    }
+                ConnectedDeviceViewModel(label, currentConnectedDevice.name)
             }
             .stateIn(
                 coroutineScope,
@@ -101,16 +108,16 @@
             )
 
     val deviceIconViewModel: StateFlow<DeviceIconViewModel?> =
-        combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
+        combine(sessionWithPlaybackState.filterData(), audioOutputInteractor.currentAudioDevice) {
                 mediaDeviceSession,
                 currentConnectedDevice ->
-                if (mediaDeviceSession !is Result.Data) {
-                    return@combine null
-                }
                 val icon: Icon =
-                    currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
+                    currentConnectedDevice
+                        .takeIf { currentConnectedDevice !is AudioOutputDevice.Unknown }
+                        ?.icon
+                        ?.let { Icon.Loaded(it, null) }
                         ?: Icon.Resource(R.drawable.ic_media_home_devices, null)
-                if (mediaDeviceSession.data?.isPlaybackActive == true) {
+                if (mediaDeviceSession?.isPlaybackActive == true) {
                     DeviceIconViewModel.IsPlaying(
                         icon = icon,
                         iconColor =
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
index ac8092c..fa40059 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
 import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.coroutineScope
@@ -46,7 +47,7 @@
     val volumePanelSliders: StateFlow<List<SliderType>> =
         combineTransform(
                 mediaOutputInteractor.activeMediaDeviceSessions,
-                mediaOutputInteractor.defaultActiveMediaSession,
+                mediaOutputInteractor.defaultActiveMediaSession.filterData(),
                 audioRepository.communicationDevice,
             ) { activeSessions, defaultSession, communicationDevice ->
                 coroutineScope {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
index 741f5cf..26d6a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel
 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import com.android.systemui.volume.panel.shared.model.filterData
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -80,9 +81,13 @@
     val isExpanded: StateFlow<Boolean> =
         merge(
                 mutableIsExpanded,
-                mediaOutputInteractor.defaultActiveMediaSession.flatMapLatest {
-                    if (it == null) flowOf(true)
-                    else mediaDeviceSessionInteractor.playbackState(it).map { it?.isActive != true }
+                mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session
+                    ->
+                    if (session == null) flowOf(true)
+                    else
+                        mediaDeviceSessionInteractor.playbackState(session).map {
+                            it?.isActive != true
+                        }
                 },
             )
             .stateIn(scope, SharingStarted.Eagerly, false)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
index 8793538..5daed99 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/shared/model/Result.kt
@@ -16,6 +16,10 @@
 
 package com.android.systemui.volume.panel.shared.model
 
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
+
 /** Models a loadable result */
 sealed interface Result<T> {
 
@@ -25,3 +29,9 @@
     /** The data is loaded successfully */
     data class Data<T>(val data: T) : Result<T>
 }
+
+/** Wraps flow into [Result]. */
+fun <T> Flow<T>.wrapInResult(): Flow<Result<T>> = map { Result.Data(it) }
+
+/** Filters only [Result.Data] from the flow. */
+fun <T> Flow<Result<T>>.filterData(): Flow<T> = mapNotNull { it as? Result.Data<T> }.map { it.data }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 0a9bac9..7ade053 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -49,6 +49,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.app.Flags;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.PendingIntent;
@@ -58,6 +59,7 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.platform.test.annotations.DisableFlags;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.filters.SmallTest;
@@ -469,6 +471,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_SORT_SECTION_BY_TIME)
     public void testShouldHeadsUp_oldWhen_whenZero() throws Exception {
         ensureStateForHeadsUpWhenAwake();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
index 4dd97bc..9b4f931 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBypassControllerTest.kt
@@ -17,19 +17,21 @@
 package com.android.systemui.statusbar.phone
 
 import android.content.pm.PackageManager
-import android.testing.AndroidTestingRunner
+import android.platform.test.flag.junit.FlagsParameterization
 import android.testing.TestableLooper
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.policy.DevicePostureController
 import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_CLOSED
@@ -58,15 +60,17 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.junit.MockitoJUnit
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
 @TestableLooper.RunWithLooper
-class KeyguardBypassControllerTest : SysuiTestCase() {
+class KeyguardBypassControllerTest(flags: FlagsParameterization?) : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val featureFlags = FakeFeatureFlags()
-    private val shadeRepository = FakeShadeRepository()
+    private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
 
     private lateinit var keyguardBypassController: KeyguardBypassController
     private lateinit var postureControllerCallback: DevicePostureController.Callback
@@ -79,6 +83,18 @@
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var packageManager: PackageManager
 
+    companion object {
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf().andSceneContainer()
+        }
+    }
+
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Captor
     private val postureCallbackCaptor =
         ArgumentCaptor.forClass(DevicePostureController.Callback::class.java)
@@ -148,7 +164,7 @@
                 statusBarStateController,
                 lockscreenUserManager,
                 keyguardStateController,
-                shadeRepository,
+                { kosmos.shadeInteractor },
                 devicePostureController,
                 keyguardTransitionInteractor,
                 dumpManager,
@@ -293,13 +309,13 @@
         testScope.runTest {
             initKeyguardBypassController()
             assertThat(keyguardBypassController.qsExpanded).isFalse()
-            val job = keyguardBypassController.listenForQsExpandedChange(this)
-            shadeRepository.setQsExpansion(0.5f)
+            val job = keyguardBypassController.listenForQsExpandedChange()
+            shadeTestUtil.setQsExpansion(0.5f)
             runCurrent()
 
             assertThat(keyguardBypassController.qsExpanded).isTrue()
 
-            shadeRepository.setQsExpansion(0f)
+            shadeTestUtil.setQsExpansion(0f)
             runCurrent()
 
             assertThat(keyguardBypassController.qsExpanded).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index efd7f99..05464f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -23,6 +23,7 @@
 import android.app.PendingIntent
 import android.app.Person
 import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.service.notification.NotificationListenerService.REASON_USER_STOPPED
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
@@ -194,7 +195,7 @@
 
     /** Regression test for b/192379214. */
     @Test
-    @DisableFlags(android.app.Flags.FLAG_UPDATE_RANKING_TIME)
+    @DisableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
     fun onEntryUpdated_notificationWhenIsZero_timeHidden() {
         val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
         notification.modifyNotification(context).setWhen(0)
@@ -210,6 +211,22 @@
     }
 
     @Test
+    @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
+    fun onEntryUpdated_notificationWhenIsZero_timeShown() {
+        val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
+        notification.modifyNotification(context).setWhen(0)
+
+        notifCollectionListener.onEntryUpdated(notification.build())
+        chipView.measure(
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+        )
+
+        assertThat(chipView.findViewById<View>(R.id.ongoing_call_chip_time)?.measuredWidth)
+                .isGreaterThan(0)
+    }
+
+    @Test
     fun onEntryUpdated_notificationWhenIsValid_timeShown() {
         val notification = NotificationEntryBuilder(createOngoingCallNotifEntry())
         notification.modifyNotification(context).setWhen(clock.currentTimeMillis())
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
index e83205c5..1107971 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
@@ -21,11 +21,9 @@
 import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR
 import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR
 import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
-import com.android.systemui.Flags.FLAG_MEDIA_IN_SCENE_CONTAINER
 import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.Flags.FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR
 import com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_SYSUI
-import com.android.systemui.Flags.FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT
 import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
 
 /**
@@ -36,13 +34,11 @@
     FLAG_COMPOSE_LOCKSCREEN,
     FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR,
     FLAG_KEYGUARD_WM_STATE_REFACTOR,
-    FLAG_MEDIA_IN_SCENE_CONTAINER,
     FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
     FLAG_NOTIFICATIONS_HEADS_UP_REFACTOR,
     FLAG_PREDICTIVE_BACK_SYSUI,
     FLAG_SCENE_CONTAINER,
     FLAG_DEVICE_ENTRY_UDFPS_REFACTOR,
-    FLAG_REFACTOR_KEYGUARD_DISMISS_INTENT,
 )
 @Retention(AnnotationRetention.RUNTIME)
 @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
index 4221d06..297d1d8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorKosmos.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.util.mockito.mock
 
 val Kosmos.shadeLockscreenInteractor by
@@ -28,5 +29,6 @@
             shadeInteractor = shadeInteractorImpl,
             sceneInteractor = sceneInteractor,
             lockIconViewController = mock(),
+            shadeRepository = shadeRepository,
         )
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c47e42d..1b59c18 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5034,7 +5034,7 @@
     }
 
     @Override
-    public final void finishAttachApplication(long startSeq) {
+    public final void finishAttachApplication(long startSeq, long timestampApplicationOnCreateNs) {
         final int pid = Binder.getCallingPid();
         final int uid = Binder.getCallingUid();
 
@@ -5054,6 +5054,11 @@
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
+
+        if (android.app.Flags.appStartInfoTimestamps() && timestampApplicationOnCreateNs > 0) {
+            addStartInfoTimestampInternal(ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE,
+                    timestampApplicationOnCreateNs, UserHandle.getUserId(uid), uid);
+        }
     }
 
     private void handleBindApplicationTimeoutSoft(ProcessRecord app, int softTimeoutMillis) {
@@ -10253,10 +10258,15 @@
         mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId, true,
                 ALLOW_NON_FULL, "addStartInfoTimestamp", null);
 
-        final String packageName = Settings.getPackageNameForUid(mContext, callingUid);
+        addStartInfoTimestampInternal(key, timestampNs, userId, callingUid);
+    }
 
-        mProcessList.getAppStartInfoTracker().addTimestampToStart(packageName,
-                UserHandle.getUid(userId, UserHandle.getAppId(callingUid)), timestampNs, key);
+    private void addStartInfoTimestampInternal(int key, long timestampNs, int userId, int uid) {
+        mProcessList.getAppStartInfoTracker().addTimestampToStart(
+                Settings.getPackageNameForUid(mContext, uid),
+                UserHandle.getUid(userId, UserHandle.getAppId(uid)),
+                timestampNs,
+                key);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
index 94baf88..2285826 100644
--- a/services/core/java/com/android/server/appop/AttributedOp.java
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
@@ -24,6 +24,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.companion.virtual.VirtualDeviceManager;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
@@ -134,7 +135,7 @@
         AppOpsManager.OpEventProxyInfo proxyInfo = null;
         if (proxyUid != Process.INVALID_UID) {
             proxyInfo = mAppOpsService.mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
-                    proxyAttributionTag);
+                            proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
         }
 
         AppOpsManager.NoteOpEvent existingEvent = mAccessEvents.get(key);
@@ -855,7 +856,7 @@
             AppOpsManager.OpEventProxyInfo proxyInfo = null;
             if (proxyUid != Process.INVALID_UID) {
                 proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
-                        proxyAttributionTag);
+                        proxyAttributionTag, VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
             }
 
             if (recycled != null) {
@@ -881,10 +882,11 @@
 
         AppOpsManager.OpEventProxyInfo acquire(@IntRange(from = 0) int uid,
                 @Nullable String packageName,
-                @Nullable String attributionTag) {
+                @Nullable String attributionTag,
+                @Nullable String deviceId) {
             AppOpsManager.OpEventProxyInfo recycled = acquire();
             if (recycled != null) {
-                recycled.reinit(uid, packageName, attributionTag);
+                recycled.reinit(uid, packageName, attributionTag, deviceId);
                 return recycled;
             }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 559462a..b0e7575 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -218,6 +218,7 @@
     }
 
     @VisibleForTesting @Nullable protected AidlSession getSessionForUser(int userId) {
+        Slog.d(TAG, "getSessionForUser: mCurrentSession: " + mCurrentSession);
         if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
             return mCurrentSession;
         } else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index b7e3f70..1c6dfe0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -242,6 +242,7 @@
     }
 
     @Nullable protected AidlSession getSessionForUser(int userId) {
+        Slog.d(TAG, "getSessionForUser: mCurrentSession: " + mCurrentSession);
         if (mCurrentSession != null && mCurrentSession.getUserId() == userId) {
             return mCurrentSession;
         } else {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 3bd0a9f..326ef7e0 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -98,7 +98,10 @@
         final int size = imList.size();
         mIms = new InputMethodInfo[size];
         mSubtypeIds = new int[size];
-        int checkedItem = 0;
+        // No items are checked by default. When we have a list of explicitly enabled subtypes,
+        // the implicit subtype is no longer listed, but if it is still the selected one,
+        // no items will be shown as checked.
+        int checkedItem = -1;
         for (int i = 0; i < size; ++i) {
             final ImeSubtypeListItem item = imList.get(i);
             mIms[i] = item.mImi;
@@ -113,6 +116,12 @@
             }
         }
 
+        if (checkedItem == -1) {
+            Slog.w(TAG, "Switching menu shown with no item selected"
+                    + ", IME id: " + preferredInputMethodId
+                    + ", subtype index: " + preferredInputMethodSubtypeId);
+        }
+
         if (mDialogWindowContext == null) {
             mDialogWindowContext = new InputMethodDialogWindowContext();
         }
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index 96f32f3..bf49671 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.server.notification;
 
-import static android.app.Flags.updateRankingTime;
+import static android.app.Flags.sortSectionByTime;
 import static android.app.Notification.FLAG_INSISTENT;
 import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
@@ -497,7 +497,7 @@
                     Slog.v(TAG, "INTERRUPTIVENESS: "
                             + record.getKey() + " is interruptive: alerted");
                 }
-                if (updateRankingTime()) {
+                if (sortSectionByTime()) {
                     if (buzz || beep) {
                         record.resetRankingTime();
                     }
@@ -1528,7 +1528,7 @@
 
             // recent conversation
             if (record.isConversation()
-                    && record.getNotification().when > mLastAvalancheTriggerTimestamp) {
+                    && record.getNotification().getWhen() > mLastAvalancheTriggerTimestamp) {
                 return true;
             }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9d4ab11..ca6ae63 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -25,6 +25,7 @@
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
 import static android.app.Flags.lifetimeExtensionRefactor;
+import static android.app.Flags.sortSectionByTime;
 import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
 import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO;
 import static android.app.Notification.EXTRA_LARGE_ICON_BIG;
@@ -8593,7 +8594,7 @@
                         r.isUpdate = true;
                         final boolean isInterruptive = isVisuallyInterruptive(old, r);
                         r.setTextChanged(isInterruptive);
-                        if (android.app.Flags.updateRankingTime()) {
+                        if (sortSectionByTime()) {
                             if (isInterruptive) {
                                 r.resetRankingTime();
                             }
@@ -8738,7 +8739,7 @@
             return false;
         }
 
-        if (android.app.Flags.updateRankingTime()) {
+        if (sortSectionByTime()) {
             // Ignore visual interruptions from FGS/UIJs because users
             // consider them one 'session'. Count them for everything else.
             if (r.getSbn().getNotification().isFgsOrUij()) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 38c95f7..0c6a6c8 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -18,7 +18,7 @@
 import static android.app.Flags.restrictAudioAttributesAlarm;
 import static android.app.Flags.restrictAudioAttributesCall;
 import static android.app.Flags.restrictAudioAttributesMedia;
-import static android.app.Flags.updateRankingTime;
+import static android.app.Flags.sortSectionByTime;
 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -580,7 +580,7 @@
         pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
         pw.println(prefix + "number=" + notification.number);
         pw.println(prefix + "groupAlertBehavior=" + notification.getGroupAlertBehavior());
-        pw.println(prefix + "when=" + notification.when);
+        pw.println(prefix + "when=" + notification.when + "/" + notification.getWhen());
 
         pw.print(prefix + "tickerText=");
         if (!TextUtils.isEmpty(notification.tickerText)) {
@@ -1092,9 +1092,9 @@
     private long calculateRankingTimeMs(long previousRankingTimeMs) {
         Notification n = getNotification();
         // Take developer provided 'when', unless it's in the future.
-        if (updateRankingTime()) {
-            if (n.hasAppProvidedWhen() && n.when <= getSbn().getPostTime()){
-                return n.when;
+        if (sortSectionByTime()) {
+            if (n.hasAppProvidedWhen() && n.getWhen() <= getSbn().getPostTime()){
+                return n.getWhen();
             }
         } else {
             if (n.when != 0 && n.when <= getSbn().getPostTime()) {
@@ -1211,7 +1211,7 @@
     }
 
     public void resetRankingTime() {
-        if (updateRankingTime()) {
+        if (sortSectionByTime()) {
             mRankingTimeMs = calculateRankingTimeMs(getSbn().getPostTime());
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 9a6ea2c2..65ef53f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -542,7 +542,7 @@
             this.is_locked = p.r.isLocked();
 
             this.age_in_minutes = NotificationRecordLogger.getAgeInMinutes(
-                    p.r.getSbn().getPostTime(), p.r.getSbn().getNotification().when);
+                    p.r.getSbn().getPostTime(), p.r.getSbn().getNotification().getWhen());
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 1f2ad07e..309e945 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -26,6 +26,7 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
+import static android.os.UserHandle.USER_SYSTEM;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
@@ -139,6 +140,8 @@
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
     private static final String ATT_UID = "uid";
+
+    private static final String ATT_USERID = "userid";
     private static final String ATT_ID = "id";
     private static final String ATT_ALLOW_BUBBLE = "allow_bubble";
     private static final String ATT_PRIORITY = "priority";
@@ -268,7 +271,7 @@
                 }
                 if (type == XmlPullParser.START_TAG) {
                     if (TAG_STATUS_ICONS.equals(tag)) {
-                        if (forRestore && userId != UserHandle.USER_SYSTEM) {
+                        if (forRestore && userId != USER_SYSTEM) {
                             continue;
                         }
                         mHideSilentStatusBarIcons = parser.getAttributeBoolean(null,
@@ -311,8 +314,16 @@
                     : parser.getAttributeInt(null, ATT_ALLOW_BUBBLE, DEFAULT_BUBBLE_PREFERENCE);
             int appImportance = parser.getAttributeInt(null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
 
+            // when data is loaded from disk it's loaded as USER_ALL, but restored data that
+            // is pending app install needs the user id that the data was restored to
+            int fixedUserId = userId;
+            if (Flags.persistIncompleteRestoreData()) {
+                if (!forRestore && uid == UNKNOWN_UID) {
+                    fixedUserId = parser.getAttributeInt(null, ATT_USERID, USER_SYSTEM);
+                }
+            }
             PackagePreferences r = getOrCreatePackagePreferencesLocked(
-                    name, userId, uid,
+                    name, fixedUserId, uid,
                     appImportance,
                     parser.getAttributeInt(null, ATT_PRIORITY, DEFAULT_PRIORITY),
                     parser.getAttributeInt(null, ATT_VISIBILITY, DEFAULT_VISIBILITY),
@@ -504,6 +515,9 @@
             }
 
             if (r.uid == UNKNOWN_UID) {
+                if (Flags.persistIncompleteRestoreData()) {
+                    r.userId = userId;
+                }
                 mRestoredWithoutUids.put(unrestoredPackageKey(pkg, userId), r);
             } else {
                 mPackagePreferences.put(key, r);
@@ -674,6 +688,7 @@
 
         if (Flags.persistIncompleteRestoreData() && r.uid == UNKNOWN_UID) {
             out.attributeLong(null, ATT_CREATION_TIME, r.creationTime);
+            out.attributeInt(null, ATT_USERID, r.userId);
         }
 
         if (!forBackup) {
@@ -2947,6 +2962,8 @@
         boolean migrateToPm = false;
         long creationTime;
 
+        @UserIdInt int userId;
+
         Delegate delegate = null;
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
         Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7756801..03dd935 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -147,11 +147,9 @@
                 if (sortSectionByTime()) {
                     final String groupKey = record.getGroupKey();
                     NotificationRecord existingProxy = mProxyByGroupTmp.get(groupKey);
-                    // summaries are mostly hidden in systemui - if there is a child notification
-                    // with better information, use its rank
-                    if (existingProxy == null
-                            || (existingProxy.getNotification().isGroupSummary()
-                            && !existingProxy.getNotification().hasAppProvidedWhen())) {
+                    // summaries are mostly hidden in systemui - if there is a child notification,
+                    // use its rank
+                    if (existingProxy == null || existingProxy.getNotification().isGroupSummary()) {
                         mProxyByGroupTmp.put(groupKey, record);
                     }
                 } else {
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index b2c6c49..47ee1d0 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -513,7 +513,11 @@
                 // Legacy behavior to report appId as UID here.
                 // The final broadcasts will contain a per-user UID.
                 outInfo.mUid = ps.getAppId();
-                outInfo.mIsAppIdRemoved = true;
+                // Only send Intent.ACTION_UID_REMOVED when flag & DELETE_KEEP_DATA is 0
+                // i.e. the mDataRemoved is true
+                if (outInfo.mDataRemoved) {
+                    outInfo.mIsAppIdRemoved = true;
+                }
                 mPm.scheduleWritePackageRestrictions(user);
                 return;
             }
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 2e67b2f..9ab6016 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -170,6 +170,7 @@
             }
         }
 
+        boolean isPendingRestoreBefore = false;
         if (pkgSetting != null && oldSharedUserSetting != sharedUserSetting) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
                     "Package " + parsedPackage.getPackageName() + " shared user changed from "
@@ -178,6 +179,9 @@
                             + " to "
                             + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
                             + "; replacing with new");
+            // Preserve the value of isPendingRestore. We need to set it to the new PackageSetting
+            // if the value is true to restore the app
+            isPendingRestoreBefore = pkgSetting.isPendingRestore();
             pkgSetting = null;
         }
 
@@ -224,6 +228,11 @@
                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
                     newDomainSetId,
                     parsedPackage.getTargetSdkVersion(), parsedPackage.getRestrictUpdateHash());
+
+            // If isPendingRestore is true before, set the value true to the PackageSetting
+            if (isPendingRestoreBefore) {
+                pkgSetting.setPendingRestore(true);
+            }
         } else {
             // make a deep copy to avoid modifying any existing system state.
             pkgSetting = new PackageSetting(pkgSetting);
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 98499417..deaa8d8 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -494,6 +494,7 @@
         PhoneCarrierPrivilegesCallback(int phoneId) {
             mPhoneId = phoneId;
         }
+
         @Override
         public void onCarrierPrivilegesChanged(
                 @NonNull Set<String> privilegedPackageNames,
@@ -563,7 +564,11 @@
 
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
         t.traceBegin("Permission_grant_default_permissions-" + userId);
-        grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);
+        if (mPackageManagerInternal.isPermissionUpgradeNeeded(userId)) {
+            grantOrUpgradeDefaultRuntimePermissions(userId);
+            updateUserSensitive(userId);
+            mPackageManagerInternal.updateRuntimePermissionsFingerprint(userId);
+        }
         t.traceEnd();
 
         final OnInitializedCallback callback;
@@ -595,59 +600,56 @@
         }
     }
 
-    private void grantOrUpgradeDefaultRuntimePermissionsIfNeeded(@UserIdInt int userId) {
+    private void grantOrUpgradeDefaultRuntimePermissions(@UserIdInt int userId) {
         if (PermissionManager.USE_ACCESS_CHECKING_SERVICE) {
             return;
         }
 
-        if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPermsIfNeeded(" + userId + ")");
+        if (DEBUG) Slog.i(LOG_TAG, "grantOrUpgradeDefaultPerms(" + userId + ")");
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
 
-        final PackageManagerInternal packageManagerInternal =
-                LocalServices.getService(PackageManagerInternal.class);
-        final PermissionManagerServiceInternal permissionManagerInternal =
-                LocalServices.getService(PermissionManagerServiceInternal.class);
-        if (packageManagerInternal.isPermissionUpgradeNeeded(userId)) {
-            if (DEBUG) Slog.i(LOG_TAG, "defaultPermsWereGrantedSinceBoot(" + userId + ")");
+        // Now call into the permission controller to apply policy around permissions
+        final AndroidFuture<Boolean> future = new AndroidFuture<>();
 
-            // Now call into the permission controller to apply policy around permissions
-            final AndroidFuture<Boolean> future = new AndroidFuture<>();
-
-            // We need to create a local manager that does not schedule work on the main
-            // there as we are on the main thread and want to block until the work is
-            // completed or we time out.
-            final PermissionControllerManager permissionControllerManager =
-                    new PermissionControllerManager(
-                            getUserContext(getContext(), UserHandle.of(userId)),
-                            PermissionThread.getHandler());
-            permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
-                    PermissionThread.getExecutor(), successful -> {
-                        if (successful) {
-                            future.complete(null);
-                        } else {
-                            // We are in an undefined state now, let us crash and have
-                            // rescue party suggest a wipe to recover to a good one.
-                            final String message = "Error granting/upgrading runtime permissions"
-                                    + " for user " + userId;
-                            Slog.wtf(LOG_TAG, message);
-                            future.completeExceptionally(new IllegalStateException(message));
-                        }
-                    });
-            try {
-                t.traceBegin("Permission_callback_waiting-" + userId);
-                future.get();
-            } catch (InterruptedException | ExecutionException e) {
-                throw new IllegalStateException(e);
-            } finally {
-                t.traceEnd();
-            }
-
-            permissionControllerManager.updateUserSensitive();
-
-            packageManagerInternal.updateRuntimePermissionsFingerprint(userId);
+        // We need to create a local manager that does not schedule work on the main
+        // there as we are on the main thread and want to block until the work is
+        // completed or we time out.
+        final PermissionControllerManager permissionControllerManager =
+                new PermissionControllerManager(
+                        getUserContext(getContext(), UserHandle.of(userId)),
+                        PermissionThread.getHandler());
+        permissionControllerManager.grantOrUpgradeDefaultRuntimePermissions(
+                PermissionThread.getExecutor(), successful -> {
+                    if (successful) {
+                        future.complete(null);
+                    } else {
+                        // We are in an undefined state now, let us crash and have
+                        // rescue party suggest a wipe to recover to a good one.
+                        final String message = "Error granting/upgrading runtime permissions"
+                                + " for user " + userId;
+                        Slog.wtf(LOG_TAG, message);
+                        future.completeExceptionally(new IllegalStateException(message));
+                    }
+                });
+        try {
+            t.traceBegin("Permission_callback_waiting-" + userId);
+            future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            throw new IllegalStateException(e);
+        } finally {
+            t.traceEnd();
         }
     }
 
+    private void updateUserSensitive(@UserIdInt int userId) {
+        if (DEBUG) Slog.i(LOG_TAG, "updateUserSensitive(" + userId + ")");
+        final PermissionControllerManager permissionControllerManager =
+                new PermissionControllerManager(
+                        getUserContext(getContext(), UserHandle.of(userId)),
+                        PermissionThread.getHandler());
+        permissionControllerManager.updateUserSensitive();
+    }
+
     private static @Nullable Context getUserContext(@NonNull Context context,
             @Nullable UserHandle user) {
         if (context.getUser().equals(user)) {
@@ -695,12 +697,10 @@
         if (DEBUG) Slog.i(LOG_TAG, "synchronizePermissionsAndAppOpsForUser(" + userId + ")");
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
 
-        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
         final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
                 getUserContext(getContext(), UserHandle.of(userId)));
         t.traceBegin("Permission_synchronize_addPackages-" + userId);
-        packageManagerInternal.forEachPackage(
+        mPackageManagerInternal.forEachPackage(
                 (pkg) -> synchronizer.addPackage(pkg.getPackageName()));
         t.traceEnd();
         t.traceBegin("Permission_syncPackages-" + userId);
@@ -1052,13 +1052,11 @@
          * @param pkgName The package to add for later processing.
          */
         void addPackage(@NonNull String pkgName) {
-            PackageManagerInternal pmInternal =
-                    LocalServices.getService(PackageManagerInternal.class);
             final PackageInfo pkgInfo;
             final AndroidPackage pkg;
             try {
                 pkgInfo = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
-                pkg = pmInternal.getPackage(pkgName);
+                pkg = mPackageManagerInternal.getPackage(pkgName);
             } catch (NameNotFoundException e) {
                 return;
             }
diff --git a/services/core/java/com/android/server/policy/SideFpsEventHandler.java b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
index 2d76c50..4ad4353 100644
--- a/services/core/java/com/android/server/policy/SideFpsEventHandler.java
+++ b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
@@ -38,6 +38,7 @@
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -66,6 +67,7 @@
     private final int mDismissDialogTimeout;
     @Nullable
     private SideFpsToast mDialog;
+    private final AccessibilityManager mAccessibilityManager;
     private final Runnable mTurnOffDialog =
             () -> {
                 dismissDialog("mTurnOffDialog");
@@ -96,6 +98,7 @@
             DialogProvider provider) {
         mContext = context;
         mHandler = handler;
+        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
         mPowerManager = powerManager;
         mBiometricState = STATE_IDLE;
         mSideFpsEventHandlerReady = new AtomicBoolean(false);
@@ -157,7 +160,9 @@
                                 mHandler.removeCallbacks(mTurnOffDialog);
                             }
                             showDialog(eventTime, "Enroll Power Press");
-                            mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
+                            if (!mAccessibilityManager.isEnabled()) {
+                                mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
+                            }
                         });
                 return true;
             case STATE_BP_AUTH:
@@ -231,6 +236,10 @@
                                         public void onBiometricAction(
                                                 @BiometricStateListener.Action int action) {
                                             Log.d(TAG, "onBiometricAction " + action);
+                                            if (mAccessibilityManager != null
+                                                    && mAccessibilityManager.isEnabled()) {
+                                                dismissDialog("mTurnOffDialog");
+                                            }
                                         }
                                     });
                             mSideFpsEventHandlerReady.set(true);
@@ -256,6 +265,9 @@
         mLastPowerPressTime = time;
         mDialog.show();
         mDialog.setOnClickListener(this);
+        if (mAccessibilityManager.isEnabled()) {
+            mDialog.addAccessibilityDelegate();
+        }
     }
 
     interface DialogProvider {
diff --git a/services/core/java/com/android/server/policy/SideFpsToast.java b/services/core/java/com/android/server/policy/SideFpsToast.java
index db07467..c27753c 100644
--- a/services/core/java/com/android/server/policy/SideFpsToast.java
+++ b/services/core/java/com/android/server/policy/SideFpsToast.java
@@ -16,6 +16,7 @@
 
 package com.android.server.policy;
 
+import android.annotation.NonNull;
 import android.app.Dialog;
 import android.content.Context;
 import android.os.Bundle;
@@ -23,6 +24,7 @@
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.Button;
 
 import com.android.internal.R;
@@ -34,7 +36,6 @@
  * This dialog is used by {@link SideFpsEventHandler}
  */
 public class SideFpsToast extends Dialog {
-
     SideFpsToast(Context context) {
         super(context);
     }
@@ -66,4 +67,27 @@
             turnOffScreen.setOnClickListener(listener);
         }
     }
+
+    /**
+     * When accessibility mode is on, add AccessibilityDelegate to dismiss dialog when focus is
+     * moved away from the dialog.
+     */
+    public void addAccessibilityDelegate() {
+        final Button turnOffScreen = findViewById(R.id.turn_off_screen);
+        if (turnOffScreen != null) {
+            turnOffScreen.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+                @Override
+                public void onInitializeAccessibilityEvent(@NonNull View host,
+                        @NonNull AccessibilityEvent event) {
+                    if (event.getEventType()
+                            == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
+                            && isShowing()) {
+                        dismiss();
+                    }
+                    super.onInitializeAccessibilityEvent(host, event);
+                }
+            });
+
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index bbb59ce..76cedd8 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -444,6 +444,9 @@
     // Refer to autosuspend.h.
     private boolean mHalAutoSuspendModeEnabled;
 
+    // True if the device uses auto-suspend mode.
+    private final boolean mUseAutoSuspend;
+
     // True if interactive mode is enabled.
     // Refer to power.h.
     private boolean mHalInteractiveModeEnabled;
@@ -1203,6 +1206,9 @@
 
         mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
 
+        mUseAutoSuspend = mContext.getResources().getBoolean(com.android.internal.R.bool
+                .config_useAutoSuspend);
+
         // Save brightness values:
         // Get float values from config.
         // Store float if valid
@@ -3918,6 +3924,9 @@
 
     @GuardedBy("mLock")
     private void setHalAutoSuspendModeLocked(boolean enable) {
+        if (!mUseAutoSuspend) {
+            return;
+        }
         if (enable != mHalAutoSuspendModeEnabled) {
             if (DEBUG) {
                 Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
@@ -4661,6 +4670,7 @@
                 pw.println("  mEnhancedDischargePredictionIsPersonalized="
                         + mEnhancedDischargePredictionIsPersonalized);
             }
+            pw.println("  mUseAutoSuspend=" + mUseAutoSuspend);
             pw.println("  mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
             pw.println("  mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
             pw.println("  mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index da29998..2f37e88 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2030,12 +2030,11 @@
         }
         // Update directly because the app which will change the orientation of display is ready.
         if (mDisplayRotation.updateOrientation(getOrientation(), false /* forceUpdate */)) {
-            // Run rotation change on display thread. See Transition#shouldApplyOnDisplayThread().
-            mWmService.mH.post(() -> {
-                synchronized (mWmService.mGlobalLock) {
-                    sendNewConfiguration();
-                }
-            });
+            // If a transition is collecting, let the transition apply the rotation change on
+            // display thread. See Transition#shouldApplyOnDisplayThread().
+            if (!mTransitionController.isCollecting(this)) {
+                sendNewConfiguration();
+            }
             return;
         }
         if (mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange()) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9b98380..56e5d76 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -43,12 +43,10 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
@@ -171,12 +169,10 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
-import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.RemoteAnimationAdapter;
 import android.view.Surface;
 import android.view.SurfaceControl;
-import android.view.TaskTransitionSpec;
 import android.view.WindowManager;
 import android.view.WindowManager.TransitionOldType;
 import android.window.ITaskOrganizer;
@@ -641,8 +637,6 @@
         mLastTaskSnapshotData = _lastSnapshotData != null
                 ? _lastSnapshotData
                 : new PersistedTaskSnapshotData();
-        // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
-        setOrientation(SCREEN_ORIENTATION_UNSET);
         affinityIntent = _affinityIntent;
         affinity = _affinity;
         rootAffinity = _rootAffinity;
@@ -2942,33 +2936,6 @@
         return;
     }
 
-    /**
-     * Account for specified insets to crop the animation bounds by to avoid the animation
-     * occurring over "out of bounds" regions
-     *
-     * For example this is used to make sure the tasks are cropped to be fully above the expanded
-     * taskbar when animating.
-     *
-     * TEMPORARY FIELD (b/202383002)
-     * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
-     *       or when shell transitions are fully enabled
-     *
-     * @param animationBounds The animation bounds to adjust to account for the custom spec insets.
-     */
-    void adjustAnimationBoundsForTransition(Rect animationBounds) {
-        TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
-        if (spec != null) {
-            final InsetsState state =
-                    getDisplayContent().getInsetsStateController().getRawInsetsState();
-            for (int i = state.sourceSize() - 1; i >= 0; i--) {
-                final InsetsSource source = state.sourceAt(i);
-                if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
-                    animationBounds.inset(source.calculateVisibleInsets(animationBounds));
-                }
-            }
-        }
-    }
-
     void setDragResizing(boolean dragResizing) {
         if (mDragResizing != dragResizing) {
             // No need to check if allowed if it's leaving dragResize
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a437914..d70ca02 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -44,7 +44,6 @@
 import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
 import static com.android.server.wm.AppTransition.isActivityTransitOld;
 import static com.android.server.wm.AppTransition.isTaskFragmentTransitOld;
-import static com.android.server.wm.AppTransition.isTaskTransitOld;
 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
@@ -72,7 +71,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.ScreenOrientation;
 import android.content.res.Configuration;
@@ -103,7 +101,6 @@
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceControlViewHost;
 import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
 import android.view.WindowManager;
 import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
@@ -186,7 +183,7 @@
     // The specified orientation for this window container.
     // Shouldn't be accessed directly since subclasses can override getOverrideOrientation.
     @ScreenOrientation
-    private int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+    private int mOverrideOrientation = SCREEN_ORIENTATION_UNSET;
 
     /**
      * The window container which decides its orientation since the last time
@@ -1683,8 +1680,6 @@
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
 
-            // TODO: Maybe mOverrideOrientation should default to SCREEN_ORIENTATION_UNSET vs.
-            // SCREEN_ORIENTATION_UNSPECIFIED?
             final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
                     ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
             if (orientation == SCREEN_ORIENTATION_BEHIND) {
@@ -1700,7 +1695,7 @@
                 continue;
             }
 
-            if (wc.providesOrientation() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+            if (orientation != SCREEN_ORIENTATION_UNSPECIFIED || wc.providesOrientation()) {
                 // Use the orientation if the container can provide or requested an explicit
                 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
                 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
@@ -3148,9 +3143,6 @@
         // Separate position and size for use in animators.
         final Rect screenBounds = getAnimationBounds(appRootTaskClipMode);
         mTmpRect.set(screenBounds);
-        if (this.asTask() != null && isTaskTransitOld(transit)) {
-            this.asTask().adjustAnimationBoundsForTransition(mTmpRect);
-        }
         getAnimationPosition(mTmpPoint);
         mTmpRect.offsetTo(0, 0);
 
@@ -3285,10 +3277,6 @@
 
             AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
 
-            if (isTaskTransitOld(transit) && getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
-                animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
-            }
-
             // Check if the animation requests to show background color for Activity and embedded
             // TaskFragment.
             final ActivityRecord activityRecord = asActivityRecord();
@@ -3342,18 +3330,6 @@
         }
     }
 
-    private @ColorInt int getTaskAnimationBackgroundColor() {
-        Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
-        TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
-        @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
-
-        if (customSpec != null && customSpec.backgroundColor != 0) {
-            return customSpec.backgroundColor;
-        }
-
-        return defaultFallbackColor;
-    }
-
     final SurfaceAnimationRunner getSurfaceAnimationRunner() {
         return mWmService.mSurfaceAnimationRunner;
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b19f0be..feede01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,7 +20,6 @@
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INPUT_CONSUMER;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
-import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.MODIFY_TOUCH_MODE_STATE;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -295,7 +294,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.SurfaceSession;
-import android.view.TaskTransitionSpec;
 import android.view.View;
 import android.view.View.FocusDirection;
 import android.view.ViewDebug;
@@ -763,11 +761,6 @@
      */
     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
 
-    /**
-     * Used during task transitions to allow SysUI and launcher to customize task transitions.
-     */
-    TaskTransitionSpec mTaskTransitionSpec;
-
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
 
@@ -9932,24 +9925,6 @@
     }
 
     @Override
-    public void setTaskTransitionSpec(TaskTransitionSpec spec) {
-        if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "setTaskTransitionSpec()")) {
-            throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
-        }
-
-        mTaskTransitionSpec = spec;
-    }
-
-    @Override
-    public void clearTaskTransitionSpec() {
-        if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "clearTaskTransitionSpec()")) {
-            throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
-        }
-
-        mTaskTransitionSpec = null;
-    }
-
-    @Override
     @RequiresPermission(Manifest.permission.ACCESS_FPS_COUNTER)
     public void registerTaskFpsCallback(@IntRange(from = 0) int taskId,
             ITaskFpsCallback callback) {
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 25c5db1..64cbb0d1 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,6 +12,7 @@
 per-file com_android_server_Usb* = file:/services/usb/OWNERS
 per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
 per-file com_android_server_accessibility_* = file:/services/accessibility/OWNERS
+per-file com_android_server_adb_* = file:/services/core/java/com/android/server/adb/OWNERS
 per-file com_android_server_display_* = file:/services/core/java/com/android/server/display/OWNERS
 per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
 per-file com_android_server_lights_* = file:/services/core/java/com/android/server/lights/OWNERS
diff --git a/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
index 9c834aa..c7b6852 100644
--- a/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
+++ b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
@@ -18,58 +18,22 @@
 
 #define LOG_NDEBUG 0
 
-#include <algorithm>
 #include <condition_variable>
 #include <mutex>
 #include <optional>
-#include <random>
-#include <string>
-#include <vector>
 
 #include <adb/pairing/pairing_server.h>
 #include <android-base/properties.h>
-#include <utils/Log.h>
-
+#include <jni.h>
 #include <nativehelper/JNIHelp.h>
-#include "jni.h"
+#include <nativehelper/utils.h>
+#include <utils/Log.h>
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 namespace {
 
-template <class T, class N>
-class JSmartWrapper {
-public:
-    JSmartWrapper(JNIEnv* env, T* jData) : mEnv(env), mJData(jData) {}
-
-    virtual ~JSmartWrapper() = default;
-
-    const N* data() const { return mRawData; }
-
-    jsize size() const { return mSize; }
-
-protected:
-    N* mRawData = nullptr;
-    JNIEnv* mEnv = nullptr;
-    T* mJData = nullptr;
-    jsize mSize = 0;
-}; // JSmartWrapper
-
-class JStringUTFWrapper : public JSmartWrapper<jstring, const char> {
-public:
-    explicit JStringUTFWrapper(JNIEnv* env, jstring* str) : JSmartWrapper(env, str) {
-        mRawData = env->GetStringUTFChars(*str, NULL);
-        mSize = env->GetStringUTFLength(*str);
-    }
-
-    virtual ~JStringUTFWrapper() {
-        if (data()) {
-            mEnv->ReleaseStringUTFChars(*mJData, mRawData);
-        }
-    }
-}; // JStringUTFWrapper
-
 struct ServerDeleter {
     void operator()(PairingServerCtx* p) { pairing_server_destroy(p); }
 };
@@ -97,19 +61,19 @@
 std::unique_ptr<PairingResultWaiter> sWaiter;
 } // namespace
 
-static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring guid, jstring password) {
+static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring javaGuid, jstring javaPassword) {
     // Server-side only sends its GUID on success.
-    PeerInfo system_info = {};
-    system_info.type = ADB_DEVICE_GUID;
-    JStringUTFWrapper guidWrapper(env, &guid);
-    memcpy(system_info.data, guidWrapper.data(), guidWrapper.size());
+    PeerInfo system_info = { .type = ADB_DEVICE_GUID };
 
-    JStringUTFWrapper passwordWrapper(env, &password);
+    ScopedUtfChars guid = GET_UTF_OR_RETURN(env, javaGuid);
+    memcpy(system_info.data, guid.c_str(), guid.size());
+
+    ScopedUtfChars password = GET_UTF_OR_RETURN(env, javaPassword);
 
     // Create the pairing server
     sServer = PairingServerPtr(
-            pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(passwordWrapper.data()),
-                                       passwordWrapper.size(), &system_info, 0));
+            pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(password.c_str()),
+                                       password.size(), &system_info, 0));
 
     sWaiter.reset(new PairingResultWaiter);
     uint16_t port = pairing_server_start(sServer.get(), sWaiter->ResultCallback, sWaiter.get());
@@ -137,11 +101,16 @@
         return JNI_FALSE;
     }
 
-    std::string peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
-    // Write to PairingThread's member variables
+    // Create a Java string for the public key.
+    char* peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
+    jstring jpublickey = env->NewStringUTF(peer_public_key);
+    if (jpublickey == nullptr) {
+      return JNI_FALSE;
+    }
+
+    // Write to PairingThread.mPublicKey.
     jclass clazz = env->GetObjectClass(thiz);
     jfieldID mPublicKey = env->GetFieldID(clazz, "mPublicKey", "Ljava/lang/String;");
-    jstring jpublickey = env->NewStringUTF(peer_public_key.c_str());
     env->SetObjectField(thiz, mPublicKey, jpublickey);
     return JNI_TRUE;
 }
@@ -157,12 +126,9 @@
 };
 
 int register_android_server_AdbDebuggingManager(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env,
-                                       "com/android/server/adb/AdbDebuggingManager$PairingThread",
-                                       gPairingThreadMethods, NELEM(gPairingThreadMethods));
-    (void)res; // Faked use when LOG_NDEBUG.
-    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
-    return 0;
+    return jniRegisterNativeMethods(env,
+                                    "com/android/server/adb/AdbDebuggingManager$PairingThread",
+                                    gPairingThreadMethods, NELEM(gPairingThreadMethods));
 }
 
 } /* namespace android */
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
index a8b792e..80f7a06 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AsyncProcessStartTest.java
@@ -197,7 +197,7 @@
                     + Arrays.toString(invocation.getArguments()));
             if (!wedge) {
                 if (mRealAms.mConstants.mEnableWaitForFinishAttachApplication) {
-                    mRealAms.finishAttachApplication(0);
+                    mRealAms.finishAttachApplication(0, 0);
                 }
             }
             return null;
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
index 67be93b..89c67d5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ProcessObserverTest.java
@@ -200,7 +200,7 @@
             Log.v(TAG, "Intercepting bindApplication() for "
                     + Arrays.toString(invocation.getArguments()));
             if (mRealAms.mConstants.mEnableWaitForFinishAttachApplication) {
-                mRealAms.finishAttachApplication(0);
+                mRealAms.finishAttachApplication(0, 0);
             }
             return null;
         }).when(thread).bindApplication(
diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
index 5c74a80..7f165e0 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -3241,6 +3241,48 @@
         }
     }
 
+    @Test
+    public void testHalAutoSuspendMode_enabledByConfiguration() {
+        AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            callback.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).initPowerManagement(any(), any(), any());
+        when(mResourcesSpy.getBoolean(
+                com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay))
+                .thenReturn(false);
+        when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_useAutoSuspend))
+                .thenReturn(true);
+
+        createService();
+        startSystem();
+        callback.get().onDisplayStateChange(/* allInactive= */ true, /* allOff= */ true);
+
+        verify(mNativeWrapperMock).nativeSetAutoSuspend(true);
+    }
+
+    @Test
+    public void testHalAutoSuspendMode_disabledByConfiguration() {
+        AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
+                new AtomicReference<>();
+        doAnswer((Answer<Void>) invocation -> {
+            callback.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).initPowerManagement(any(), any(), any());
+        when(mResourcesSpy.getBoolean(
+                com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay))
+                .thenReturn(false);
+        when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_useAutoSuspend))
+                .thenReturn(false);
+
+        createService();
+        startSystem();
+        callback.get().onDisplayStateChange(/* allInactive= */ true, /* allOff= */ true);
+
+        verify(mNativeWrapperMock, never()).nativeSetAutoSuspend(true);
+    }
+
     private void setCachedUidProcState(int uid) {
         mService.updateUidProcStateInternal(uid, PROCESS_STATE_TOP_SLEEPING);
     }
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 94a71be..753db12 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -279,7 +279,7 @@
 test_module_config {
     name: "FrameworksServicesTests_contentprotection",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.contentprotection"],
     exclude_annotations: FLAKY_AND_IGNORED,
 }
@@ -287,7 +287,7 @@
 test_module_config {
     name: "FrameworksServicesTests_om",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.om."],
     exclude_annotations: FLAKY_AND_IGNORED,
 }
@@ -296,7 +296,7 @@
 test_module_config {
     name: "FrameworksServicesTests_contexthub_presubmit",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.location.contexthub."],
     // TODO(ron): are these right, does it run anything?
     include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -306,7 +306,7 @@
 test_module_config {
     name: "FrameworksServicesTests_contexthub_postsubmit",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.location.contexthub."],
     // TODO(ron): are these right, does it run anything?
     include_annotations: ["android.platform.test.annotations.Postsubmit"],
@@ -317,7 +317,7 @@
 test_module_config {
     name: "FrameworksServicesTests_contentcapture",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.contentcapture"],
     exclude_annotations: FLAKY_AND_IGNORED,
 }
@@ -325,7 +325,7 @@
 test_module_config {
     name: "FrameworksServicesTests_recoverysystem",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.recoverysystem."],
     exclude_annotations: ["androidx.test.filters.FlakyTest"],
 }
@@ -334,7 +334,7 @@
 test_module_config {
     name: "FrameworksServicesTests_pm_presubmit",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_annotations: ["android.platform.test.annotations.Presubmit"],
     include_filters: ["com.android.server.pm."],
     exclude_annotations: FLAKY_AND_IGNORED,
@@ -343,7 +343,7 @@
 test_module_config {
     name: "FrameworksServicesTests_pm_postsubmit",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_annotations: ["android.platform.test.annotations.Postsubmit"],
     include_filters: ["com.android.server.pm."],
     exclude_annotations: FLAKY_AND_IGNORED,
@@ -353,6 +353,6 @@
 test_module_config {
     name: "FrameworksServicesTests_os",
     base: "FrameworksServicesTests",
-    test_suites: ["general-tests"],
+    test_suites: ["device-tests"],
     include_filters: ["com.android.server.os."],
 }
diff --git a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
index 669eedf..dabf531 100644
--- a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
@@ -31,11 +31,13 @@
 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
 import android.os.Handler;
 import android.os.PowerManager;
+import android.os.RemoteException;
 import android.os.test.TestLooper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
 import android.testing.TestableResources;
 import android.view.Window;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -48,7 +50,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.List;
 
@@ -72,9 +75,15 @@
     private static final Integer AUTO_DISMISS_DIALOG = 500;
 
     @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    @Rule
     public TestableContext mContext =
             new TestableContext(InstrumentationRegistry.getContext(), null);
 
+    private final AccessibilityManager mAccessibilityManager =
+            mContext.getSystemService(AccessibilityManager.class);
+
     @Mock
     private PackageManager mPackageManager;
     @Mock
@@ -89,9 +98,8 @@
     private BiometricStateListener mBiometricStateListener;
 
     @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-
+    public void setup() throws RemoteException {
+        disableAccessibility();
         mContext.addMockSystemService(PackageManager.class, mPackageManager);
         mContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
         TestableResources resources = mContext.getOrCreateTestableResources();
@@ -192,9 +200,8 @@
     }
 
     @Test
-    public void dialogDismissesAfterTime() throws Exception {
+    public void dialogDismissesAfterTime_accessibilityDisabled() throws Exception {
         setupWithSensor(true /* hasSfps */, true /* initialized */);
-
         setBiometricState(BiometricStateListener.STATE_ENROLLING);
         when(mDialog.isShowing()).thenReturn(true);
         assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -207,9 +214,23 @@
     }
 
     @Test
-    public void dialogDoesNotDismissOnSensorTouch() throws Exception {
+    public void dialogDoesNotDismissAfterTime_accessibilityEnabled() throws Exception {
+        enableAccessibility();
         setupWithSensor(true /* hasSfps */, true /* initialized */);
+        setBiometricState(BiometricStateListener.STATE_ENROLLING);
+        when(mDialog.isShowing()).thenReturn(true);
+        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
 
+        mLooper.dispatchAll();
+        verify(mDialog).show();
+        mLooper.moveTimeForward(AUTO_DISMISS_DIALOG);
+        mLooper.dispatchAll();
+        verify(mDialog, never()).dismiss();
+    }
+
+    @Test
+    public void dialogDoesNotDismissOnSensorTouch_accessibilityDisabled() throws Exception {
+        setupWithSensor(true /* hasSfps */, true /* initialized */);
         setBiometricState(BiometricStateListener.STATE_ENROLLING);
         when(mDialog.isShowing()).thenReturn(true);
         assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -218,12 +239,26 @@
         verify(mDialog).show();
 
         mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
-        mLooper.moveTimeForward(AUTO_DISMISS_DIALOG - 1);
         mLooper.dispatchAll();
-
         verify(mDialog, never()).dismiss();
     }
 
+    @Test
+    public void dialogDismissesOnSensorTouch_accessibilityEnabled() throws Exception {
+        enableAccessibility();
+        setupWithSensor(true /* hasSfps */, true /* initialized */);
+        setBiometricState(BiometricStateListener.STATE_ENROLLING);
+        when(mDialog.isShowing()).thenReturn(true);
+        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
+
+        mLooper.dispatchAll();
+        verify(mDialog).show();
+
+        mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
+        mLooper.dispatchAll();
+        verify(mDialog).dismiss();
+    }
+
     private void setBiometricState(@BiometricStateListener.State int newState) {
         if (mBiometricStateListener != null) {
             mBiometricStateListener.onStateChanged(newState);
@@ -231,6 +266,20 @@
         }
     }
 
+    private void enableAccessibility() throws RemoteException {
+        if (mAccessibilityManager != null) {
+            mAccessibilityManager.getClient().setState(1);
+            mLooper.dispatchAll();
+        }
+    }
+
+    private void disableAccessibility() throws RemoteException {
+        if (mAccessibilityManager != null) {
+            mAccessibilityManager.getClient().setState(0);
+            mLooper.dispatchAll();
+        }
+    }
+
     private void setupWithSensor(boolean hasSfps, boolean initialized) throws Exception {
         when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_FINGERPRINT)))
                 .thenReturn(true);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
index 0d6fdc9..4af20a9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -2638,7 +2638,7 @@
 
     @Test
     public void testSoundResetsRankingTime() throws Exception {
-        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_UPDATE_RANKING_TIME);
+        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME);
         TestableFlagResolver flagResolver = new TestableFlagResolver();
         initAttentionHelper(flagResolver);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 74d8433..3a0eba1 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -24,7 +24,7 @@
 import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
-import static android.app.Flags.FLAG_UPDATE_RANKING_TIME;
+import static android.app.Flags.FLAG_SORT_SECTION_BY_TIME;
 import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
 import static android.app.Notification.EXTRA_PICTURE;
 import static android.app.Notification.EXTRA_PICTURE_ICON;
@@ -7376,7 +7376,7 @@
     }
 
     @Test
-    @EnableFlags({android.app.Flags.FLAG_UPDATE_RANKING_TIME})
+    @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME})
     public void testVisualDifference_userInitiatedJob() {
         Notification.Builder nb1 = new Notification.Builder(mContext, "")
                 .setContentTitle("foo");
@@ -15283,7 +15283,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+    @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
     public void rankingTime_newNotification_noisy_matchesSbn() throws Exception {
         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, mUserId);
 
@@ -15297,7 +15297,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+    @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
     public void rankingTime_newNotification_silent_matchesSbn() throws Exception {
         NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
         NotificationRecord nr = generateNotificationRecord(low, mUserId);
@@ -15312,7 +15312,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+    @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
     public void rankingTime_updatedNotification_silentSameText_originalPostTime() throws Exception {
         NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
         NotificationRecord nr = generateNotificationRecord(low, mUserId);
@@ -15332,7 +15332,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+    @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
     public void rankingTime_updatedNotification_silentNewText_newPostTime() throws Exception {
         NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
         NotificationRecord nr = generateNotificationRecord(low, 0, mUserId);
@@ -15357,7 +15357,7 @@
     }
 
     @Test
-    @EnableFlags(FLAG_UPDATE_RANKING_TIME)
+    @EnableFlags(FLAG_SORT_SECTION_BY_TIME)
     public void rankingTime_updatedNotification_noisySameText_newPostTime() throws Exception {
         NotificationChannel low = new NotificationChannel("low", "low", IMPORTANCE_LOW);
         NotificationRecord nr = generateNotificationRecord(low, mUserId);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 9a58594..d1880d2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -1561,14 +1561,14 @@
         mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                 false, mClock);
-        loadByteArrayXml(baos.toByteArray(), false, USER_SYSTEM);
+        loadByteArrayXml(baos.toByteArray(), false, USER_ALL);
 
         // Trigger 2nd restore pass
-        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_P);
+        when(mPm.getPackageUidAsUser(PKG_R, USER_SYSTEM)).thenReturn(UID_R);
         mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
-                new int[]{UID_P});
+                new int[]{UID_R});
 
-        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_P, id,
+        NotificationChannel channel = mXmlHelper.getNotificationChannel(PKG_R, UID_R, id,
                 false);
         assertThat(channel.getImportance()).isEqualTo(2);
         assertThat(channel.canShowBadge()).isTrue();
@@ -1616,7 +1616,7 @@
         mXmlHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles,
                 false, mClock);
-        loadByteArrayXml(xml.getBytes(), false, USER_SYSTEM);
+        loadByteArrayXml(xml.getBytes(), false, USER_ALL);
 
         // Trigger 2nd restore pass
         mXmlHelper.onPackagesChanged(false, USER_SYSTEM, new String[]{PKG_R},
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 527001d..9a6e818 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -378,7 +378,7 @@
     }
 
     @Test
-    @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+    @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
     public void testSort_oldWhenChildren_unspecifiedSummary() {
         NotificationRecord child1 = new NotificationRecord(mContext,
                 new StatusBarNotification(
@@ -430,7 +430,7 @@
     }
 
     @Test
-    @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+    @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
     public void testSort_oldChildren_unspecifiedSummary() {
         NotificationRecord child1 = new NotificationRecord(mContext,
                 new StatusBarNotification(
@@ -480,7 +480,7 @@
     }
 
     @Test
-    @EnableFlags({android.app.Flags.FLAG_SORT_SECTION_BY_TIME, Flags.FLAG_UPDATE_RANKING_TIME})
+    @EnableFlags(android.app.Flags.FLAG_SORT_SECTION_BY_TIME)
     public void testSort_oldChildren_oldSummary() {
         NotificationRecord child1 = new NotificationRecord(mContext,
                 new StatusBarNotification(
@@ -517,10 +517,10 @@
                         mUser, null, System.currentTimeMillis()), getLowChannel());
 
         ArrayList<NotificationRecord> expected = new ArrayList<>();
+        expected.add(unrelated);
         expected.add(summary);
         expected.add(child2);
         expected.add(child1);
-        expected.add(unrelated);
 
         ArrayList<NotificationRecord> actual = new ArrayList<>();
         actual.addAll(expected);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 7356b43..27d9d13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1071,6 +1071,7 @@
     @Test
     public void testAllowsTopmostFullscreenOrientation() {
         final DisplayContent dc = createNewDisplay();
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, dc.getOrientation());
         dc.getDisplayRotation().setFixedToUserRotation(
                 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
 
@@ -1717,7 +1718,6 @@
         // The display should be rotated after the launch is finished.
         doReturn(false).when(app).isAnimating(anyInt(), anyInt());
         mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
-        waitHandlerIdle(mWm.mH);
         mStatusBarWindow.finishSeamlessRotation(t);
         mNavBarWindow.finishSeamlessRotation(t);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 48fc2dc..9f85acb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -565,36 +565,17 @@
 
     @Test
     public void testGetOrientation_childSpecified() {
-        testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE,
-                SCREEN_ORIENTATION_LANDSCAPE);
-        testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET,
-                SCREEN_ORIENTATION_UNSPECIFIED);
-    }
-
-    private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation,
-            int expectedOrientation) {
         final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
-        final TestWindowContainer root = builder.setLayer(0).build();
+        final TestWindowContainer root = builder.build();
         root.setFillsParent(true);
+        assertEquals(SCREEN_ORIENTATION_UNSET, root.getOrientation());
 
-        builder.setIsVisible(childVisible);
+        final TestWindowContainer child = root.addChildWindow();
+        child.setFillsParent(true);
+        assertEquals(SCREEN_ORIENTATION_UNSET, root.getOrientation());
 
-        if (childOrientation != SCREEN_ORIENTATION_UNSET) {
-            builder.setOrientation(childOrientation);
-        }
-
-        final TestWindowContainer child1 = root.addChildWindow(builder);
-        child1.setFillsParent(true);
-
-        assertEquals(expectedOrientation, root.getOrientation());
-    }
-
-    @Test
-    public void testGetOrientation_Unset() {
-        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
-        final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
-        // Unspecified well because we didn't specify anything...
-        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
+        child.setOverrideOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation());
     }
 
     @Test
diff --git a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
index 439cf13..1dc1037 100644
--- a/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/ActivityEmbedding/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
index 4b6224e..57a58c8 100644
--- a/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppClose/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
index 583bcb7..2cb86e0 100644
--- a/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AppLaunch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
index d6ae2b3..2cf85fa 100644
--- a/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/FlickerService/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/IME/AndroidTestTemplate.xml b/tests/FlickerTests/IME/AndroidTestTemplate.xml
index 38442db..b93e1be 100644
--- a/tests/FlickerTests/IME/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/IME/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- enable AOD -->
diff --git a/tests/FlickerTests/Notification/AndroidTestTemplate.xml b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
index 4036858..9c6a17d3 100644
--- a/tests/FlickerTests/Notification/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Notification/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
index 797ca4e..ecbed28 100644
--- a/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/QuickSwitch/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->
diff --git a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
index b5ea739..1eacdfd 100644
--- a/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/Rotation/AndroidTestTemplate.xml
@@ -8,6 +8,8 @@
     <option name="isolated-storage" value="false"/>
 
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- disable DeprecatedTargetSdk warning -->
+        <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1"/>
         <!-- keeps the screen on during tests -->
         <option name="screen-always-on" value="on"/>
         <!-- prevents the phone from restarting -->