Merge "Allow NotificationListenerService to be unbound by default"
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4daf12a..4bddbd6 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -244,7 +244,7 @@
          label="LIGHT_STATE_INACTIVE\nScreen off AND Not charging",
          color=black,shape=diamond
        ]
-       LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=blue,shape=oval]
+       LIGHT_STATE_IDLE [label="LIGHT_STATE_IDLE\n",color=red,shape=box]
        LIGHT_STATE_WAITING_FOR_NETWORK [
          label="LIGHT_STATE_WAITING_FOR_NETWORK\n"
              + "Coming out of LIGHT_STATE_IDLE, waiting for network",
@@ -490,9 +490,9 @@
     @GuardedBy("this")
     private long mNextLightIdleDelay;
     @GuardedBy("this")
-    private long mNextLightAlarmTime;
+    private long mNextLightIdleDelayFlex;
     @GuardedBy("this")
-    private long mNextLightMaintenanceAlarmTime;
+    private long mNextLightAlarmTime;
     @GuardedBy("this")
     private long mNextSensingTimeoutAlarmTime;
 
@@ -689,15 +689,6 @@
         }
     };
 
-    private final AlarmManager.OnAlarmListener mLightMaintenanceAlarmListener = () -> {
-        if (DEBUG) {
-            Slog.d(TAG, "Light maintenance alarm fired");
-        }
-        synchronized (DeviceIdleController.this) {
-            stepLightIdleStateLocked("s:alarm");
-        }
-    };
-
     /** AlarmListener to start monitoring motion if there are registered stationary listeners. */
     private final AlarmManager.OnAlarmListener mMotionRegistrationAlarmListener = () -> {
         synchronized (DeviceIdleController.this) {
@@ -962,6 +953,9 @@
         private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT =
                 "light_after_inactive_to";
         private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
+        private static final String KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX =
+                "light_idle_to_initial_flex";
+        private static final String KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX = "light_max_idle_to_flex";
         private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
         private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
         private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET =
@@ -1010,6 +1004,10 @@
                 !COMPRESS_TIME ? 4 * 60 * 1000L : 30 * 1000L;
         private long mDefaultLightIdleTimeout =
                 !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L;
+        private long mDefaultLightIdleTimeoutInitialFlex =
+                !COMPRESS_TIME ? 60 * 1000L : 5 * 1000L;
+        private long mDefaultLightIdleTimeoutMaxFlex =
+                !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
         private float mDefaultLightIdleFactor = 2f;
         private long mDefaultLightMaxIdleTimeout =
                 !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L;
@@ -1084,6 +1082,22 @@
         public long LIGHT_IDLE_TIMEOUT = mDefaultLightIdleTimeout;
 
         /**
+         * This is the initial alarm window size that we will tolerate for light idle maintenance
+         * timing.
+         *
+         * @see #KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX
+         * @see #mNextLightIdleDelayFlex
+         */
+        public long LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = mDefaultLightIdleTimeoutInitialFlex;
+
+        /**
+         * This is the maximum value that {@link #mNextLightIdleDelayFlex} should take.
+         *
+         * @see #KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX
+         */
+        public long LIGHT_IDLE_TIMEOUT_MAX_FLEX = mDefaultLightIdleTimeoutMaxFlex;
+
+        /**
          * Scaling factor to apply to the light idle mode time each time we complete a cycle.
          *
          * @see #KEY_LIGHT_IDLE_FACTOR
@@ -1321,6 +1335,14 @@
             mDefaultLightIdleTimeout = getTimeout(
                     res.getInteger(com.android.internal.R.integer.device_idle_light_idle_to_ms),
                     mDefaultLightIdleTimeout);
+            mDefaultLightIdleTimeoutInitialFlex = getTimeout(
+                    res.getInteger(
+                            com.android.internal.R.integer.device_idle_light_idle_to_init_flex_ms),
+                    mDefaultLightIdleTimeoutInitialFlex);
+            mDefaultLightIdleTimeoutMaxFlex = getTimeout(
+                    res.getInteger(
+                            com.android.internal.R.integer.device_idle_light_idle_to_max_flex_ms),
+                    mDefaultLightIdleTimeoutMaxFlex);
             mDefaultLightIdleFactor = res.getFloat(
                     com.android.internal.R.integer.device_idle_light_idle_factor);
             mDefaultLightMaxIdleTimeout = getTimeout(
@@ -1400,6 +1422,8 @@
             FLEX_TIME_SHORT = mDefaultFlexTimeShort;
             LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mDefaultLightIdleAfterInactiveTimeout;
             LIGHT_IDLE_TIMEOUT = mDefaultLightIdleTimeout;
+            LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = mDefaultLightIdleTimeoutInitialFlex;
+            LIGHT_IDLE_TIMEOUT_MAX_FLEX = mDefaultLightIdleTimeoutMaxFlex;
             LIGHT_IDLE_FACTOR = mDefaultLightIdleFactor;
             LIGHT_MAX_IDLE_TIMEOUT = mDefaultLightMaxIdleTimeout;
             LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mDefaultLightIdleMaintenanceMinBudget;
@@ -1457,6 +1481,16 @@
                             LIGHT_IDLE_TIMEOUT = properties.getLong(
                                     KEY_LIGHT_IDLE_TIMEOUT, mDefaultLightIdleTimeout);
                             break;
+                        case KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX:
+                            LIGHT_IDLE_TIMEOUT_INITIAL_FLEX = properties.getLong(
+                                    KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX,
+                                    mDefaultLightIdleTimeoutInitialFlex);
+                            break;
+                        case KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX:
+                            LIGHT_IDLE_TIMEOUT_MAX_FLEX = properties.getLong(
+                                    KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX,
+                                    mDefaultLightIdleTimeoutMaxFlex);
+                            break;
                         case KEY_LIGHT_IDLE_FACTOR:
                             LIGHT_IDLE_FACTOR = Math.max(1, properties.getFloat(
                                     KEY_LIGHT_IDLE_FACTOR, mDefaultLightIdleFactor));
@@ -1613,6 +1647,14 @@
             TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
             pw.println();
 
+            pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT_INITIAL_FLEX); pw.print("=");
+            TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT_INITIAL_FLEX, pw);
+            pw.println();
+
+            pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT_MAX_FLEX); pw.print("=");
+            TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT_MAX_FLEX, pw);
+            pw.println();
+
             pw.print("    "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
             pw.print(LIGHT_IDLE_FACTOR);
             pw.println();
@@ -3209,7 +3251,7 @@
             if (conn != mNetworkConnected) {
                 mNetworkConnected = conn;
                 if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
-                    stepLightIdleStateLocked("network", /* forceProgression */ true);
+                    stepLightIdleStateLocked("network");
                 }
             }
         }
@@ -3454,11 +3496,7 @@
             moveToLightStateLocked(LIGHT_STATE_INACTIVE, "no activity");
             resetLightIdleManagementLocked();
             scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
-                    mConstants.FLEX_TIME_SHORT);
-            // After moving in INACTIVE, the maintenance window should start the time inactive
-            // timeout and a single light idle period.
-            scheduleLightMaintenanceAlarmLocked(
-                    mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT + mConstants.LIGHT_IDLE_TIMEOUT);
+                    mConstants.FLEX_TIME_SHORT, true);
         }
     }
 
@@ -3480,8 +3518,9 @@
     private void resetLightIdleManagementLocked() {
         mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
         mMaintenanceStartTime = 0;
+        mNextLightIdleDelayFlex = mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX;
         mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
-        cancelAllLightAlarmsLocked();
+        cancelLightAlarmLocked();
     }
 
     @GuardedBy("this")
@@ -3515,14 +3554,9 @@
     }
 
     @GuardedBy("this")
-    private void stepLightIdleStateLocked(String reason) {
-        stepLightIdleStateLocked(reason, false);
-    }
-
-    @GuardedBy("this")
     @VisibleForTesting
     @SuppressLint("WakelockTimeout")
-    void stepLightIdleStateLocked(String reason, boolean forceProgression) {
+    void stepLightIdleStateLocked(String reason) {
         if (mLightState == LIGHT_STATE_ACTIVE || mLightState == LIGHT_STATE_OVERRIDE) {
             // If we are already in deep device idle mode, then
             // there is nothing left to do for light mode.
@@ -3530,91 +3564,67 @@
         }
 
         if (DEBUG) {
-            Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + lightStateToString(mLightState)
-                    + " force=" + forceProgression);
+            Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + lightStateToString(mLightState));
         }
         EventLogTags.writeDeviceIdleLightStep();
 
-        final long nowElapsed = mInjector.getElapsedRealtime();
-        final boolean crossedMaintenanceTime =
-                mNextLightMaintenanceAlarmTime > 0 && nowElapsed >= mNextLightMaintenanceAlarmTime;
-        final boolean crossedProgressionTime =
-                mNextLightAlarmTime > 0 && nowElapsed >= mNextLightAlarmTime;
-        final boolean enterMaintenance;
-        if (crossedMaintenanceTime) {
-            if (crossedProgressionTime) {
-                enterMaintenance = (mNextLightAlarmTime <= mNextLightMaintenanceAlarmTime);
-            } else {
-                enterMaintenance = true;
-            }
-        } else if (crossedProgressionTime) {
-            enterMaintenance = false;
-        } else if (forceProgression) {
-            // This will happen for adb commands, unit tests,
-            // and when we're in WAITING_FOR_NETWORK and the network connects.
-            enterMaintenance =
-                    mLightState == LIGHT_STATE_IDLE
-                            || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK;
-        } else {
-            Slog.wtfStack(TAG, "stepLightIdleStateLocked called in invalid state: " + mLightState);
-            return;
-        }
-
-        if (enterMaintenance) {
-            if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
-                // We have been idling long enough, now it is time to do some work.
-                mActiveIdleOpCount = 1;
-                mActiveIdleWakeLock.acquire();
-                mMaintenanceStartTime = SystemClock.elapsedRealtime();
-                if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
-                    mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
-                } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
-                    mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
+        switch (mLightState) {
+            case LIGHT_STATE_INACTIVE:
+                mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
+                // Reset the upcoming idle delays.
+                mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
+                mNextLightIdleDelayFlex = mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX;
+                mMaintenanceStartTime = 0;
+                // Fall through to immediately idle.
+            case LIGHT_STATE_IDLE_MAINTENANCE:
+                if (mMaintenanceStartTime != 0) {
+                    long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
+                    if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
+                        // We didn't use up all of our minimum budget; add this to the reserve.
+                        mCurLightIdleBudget +=
+                                (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration);
+                    } else {
+                        // We used more than our minimum budget; this comes out of the reserve.
+                        mCurLightIdleBudget -=
+                                (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
+                    }
                 }
+                mMaintenanceStartTime = 0;
+                scheduleLightAlarmLocked(mNextLightIdleDelay, mNextLightIdleDelayFlex, true);
                 mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
                         (long) (mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
-                // We're entering MAINTENANCE. It should end curLightIdleBudget time from now.
-                // The next maintenance window should be curLightIdleBudget + nextLightIdleDelay
-                // time from now.
-                scheduleLightAlarmLocked(mCurLightIdleBudget, mConstants.FLEX_TIME_SHORT);
-                scheduleLightMaintenanceAlarmLocked(mCurLightIdleBudget + mNextLightIdleDelay);
-                moveToLightStateLocked(LIGHT_STATE_IDLE_MAINTENANCE, reason);
-                addEvent(EVENT_LIGHT_MAINTENANCE, null);
-                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
-            } else {
-                // We'd like to do maintenance, but currently don't have network
-                // connectivity...  let's try to wait until the network comes back.
-                // We'll only wait for another full idle period, however, and then give up.
-                scheduleLightMaintenanceAlarmLocked(mNextLightIdleDelay);
-                cancelLightAlarmLocked();
-                moveToLightStateLocked(LIGHT_STATE_WAITING_FOR_NETWORK, reason);
-            }
-        } else {
-            if (mMaintenanceStartTime != 0) {
-                // Cap duration at budget since the non-wakeup alarm to exit maintenance may
-                // not fire at the exact intended time, but once the system is up, we will stop
-                // more ongoing work.
-                long duration = Math.min(mCurLightIdleBudget,
-                        SystemClock.elapsedRealtime() - mMaintenanceStartTime);
-                if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
-                    // We didn't use up all of our minimum budget; add this to the reserve.
-                    mCurLightIdleBudget +=
-                            (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET - duration);
+                mNextLightIdleDelayFlex = Math.min(mConstants.LIGHT_IDLE_TIMEOUT_MAX_FLEX,
+                        (long) (mNextLightIdleDelayFlex * mConstants.LIGHT_IDLE_FACTOR));
+                moveToLightStateLocked(LIGHT_STATE_IDLE, reason);
+                addEvent(EVENT_LIGHT_IDLE, null);
+                mGoingIdleWakeLock.acquire();
+                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
+                break;
+            case LIGHT_STATE_IDLE:
+            case LIGHT_STATE_WAITING_FOR_NETWORK:
+                if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
+                    // We have been idling long enough, now it is time to do some work.
+                    mActiveIdleOpCount = 1;
+                    mActiveIdleWakeLock.acquire();
+                    mMaintenanceStartTime = SystemClock.elapsedRealtime();
+                    if (mCurLightIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
+                        mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
+                    } else if (mCurLightIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
+                        mCurLightIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
+                    }
+                    scheduleLightAlarmLocked(mCurLightIdleBudget, mConstants.FLEX_TIME_SHORT, true);
+                    moveToLightStateLocked(LIGHT_STATE_IDLE_MAINTENANCE, reason);
+                    addEvent(EVENT_LIGHT_MAINTENANCE, null);
+                    mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
                 } else {
-                    // We used more than our minimum budget; this comes out of the reserve.
-                    mCurLightIdleBudget -=
-                            (duration - mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
+                    // We'd like to do maintenance, but currently don't have network
+                    // connectivity...  let's try to wait until the network comes back.
+                    // We'll only wait for another full idle period, however, and then give up.
+                    scheduleLightAlarmLocked(mNextLightIdleDelay,
+                            mNextLightIdleDelayFlex / 2, true);
+                    moveToLightStateLocked(LIGHT_STATE_WAITING_FOR_NETWORK, reason);
                 }
-            }
-            mMaintenanceStartTime = 0;
-            // We're entering IDLE. We may have used less than curLightIdleBudget for the
-            // maintenance window, so reschedule the alarm starting from now.
-            scheduleLightMaintenanceAlarmLocked(mNextLightIdleDelay);
-            cancelLightAlarmLocked();
-            moveToLightStateLocked(LIGHT_STATE_IDLE, reason);
-            addEvent(EVENT_LIGHT_IDLE, null);
-            mGoingIdleWakeLock.acquire();
-            mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
+                break;
         }
     }
 
@@ -3749,7 +3759,7 @@
                 moveToStateLocked(STATE_IDLE, reason);
                 if (mLightState != LIGHT_STATE_OVERRIDE) {
                     moveToLightStateLocked(LIGHT_STATE_OVERRIDE, "deep");
-                    cancelAllLightAlarmsLocked();
+                    cancelLightAlarmLocked();
                 }
                 addEvent(EVENT_DEEP_IDLE, null);
                 mGoingIdleWakeLock.acquire();
@@ -3995,7 +4005,7 @@
                 if (mState == STATE_IDLE_MAINTENANCE) {
                     stepIdleStateLocked("s:early");
                 } else {
-                    stepLightIdleStateLocked("s:early", /* forceProgression */ true);
+                    stepLightIdleStateLocked("s:early");
                 }
             }
         }
@@ -4103,12 +4113,6 @@
     }
 
     @GuardedBy("this")
-    private void cancelAllLightAlarmsLocked() {
-        cancelLightAlarmLocked();
-        cancelLightMaintenanceAlarmLocked();
-    }
-
-    @GuardedBy("this")
     private void cancelLightAlarmLocked() {
         if (mNextLightAlarmTime != 0) {
             mNextLightAlarmTime = 0;
@@ -4117,14 +4121,6 @@
     }
 
     @GuardedBy("this")
-    private void cancelLightMaintenanceAlarmLocked() {
-        if (mNextLightMaintenanceAlarmTime != 0) {
-            mNextLightMaintenanceAlarmTime = 0;
-            mAlarmManager.cancel(mLightMaintenanceAlarmListener);
-        }
-    }
-
-    @GuardedBy("this")
     void cancelLocatingLocked() {
         if (mLocating) {
             LocationManager locationManager = mInjector.getLocationManager();
@@ -4188,40 +4184,26 @@
     }
 
     @GuardedBy("this")
-    @VisibleForTesting
-    void scheduleLightAlarmLocked(long delay, long flex) {
+    void scheduleLightAlarmLocked(long delay, long flex, boolean wakeup) {
         if (DEBUG) {
             Slog.d(TAG, "scheduleLightAlarmLocked(" + delay
                     + (mConstants.USE_WINDOW_ALARMS ? "/" + flex : "")
-                    + ")");
+                    + ", wakeup=" + wakeup + ")");
         }
         mNextLightAlarmTime = mInjector.getElapsedRealtime() + delay;
         if (mConstants.USE_WINDOW_ALARMS) {
             mAlarmManager.setWindow(
-                    AlarmManager.ELAPSED_REALTIME,
+                    wakeup ? AlarmManager.ELAPSED_REALTIME_WAKEUP : AlarmManager.ELAPSED_REALTIME,
                     mNextLightAlarmTime, flex,
                     "DeviceIdleController.light", mLightAlarmListener, mHandler);
         } else {
             mAlarmManager.set(
-                    AlarmManager.ELAPSED_REALTIME,
+                    wakeup ? AlarmManager.ELAPSED_REALTIME_WAKEUP : AlarmManager.ELAPSED_REALTIME,
                     mNextLightAlarmTime,
                     "DeviceIdleController.light", mLightAlarmListener, mHandler);
         }
     }
 
-    @GuardedBy("this")
-    @VisibleForTesting
-    void scheduleLightMaintenanceAlarmLocked(long delay) {
-        if (DEBUG) {
-            Slog.d(TAG, "scheduleLightMaintenanceAlarmLocked(" + delay + ")");
-        }
-        mNextLightMaintenanceAlarmTime = mInjector.getElapsedRealtime() + delay;
-        mAlarmManager.setWindow(
-                AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                mNextLightMaintenanceAlarmTime, mConstants.FLEX_TIME_SHORT,
-                "DeviceIdleController.light", mLightMaintenanceAlarmListener, mHandler);
-    }
-
     @VisibleForTesting
     long getNextLightAlarmTimeForTesting() {
         synchronized (this) {
@@ -4229,13 +4211,6 @@
         }
     }
 
-    @VisibleForTesting
-    long getNextLightMaintenanceAlarmTimeForTesting() {
-        synchronized (this) {
-            return mNextLightMaintenanceAlarmTime;
-        }
-    }
-
     private void scheduleMotionRegistrationAlarmLocked() {
         if (DEBUG) Slog.d(TAG, "scheduleMotionRegistrationAlarmLocked");
         long nextMotionRegistrationAlarmTime =
@@ -4605,7 +4580,7 @@
                         pw.print("Stepped to deep: ");
                         pw.println(stateToString(mState));
                     } else if ("light".equals(arg)) {
-                        stepLightIdleStateLocked("s:shell", /* forceProgression */ true);
+                        stepLightIdleStateLocked("s:shell");
                         pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
                     } else {
                         pw.println("Unknown idle mode: " + arg);
@@ -4645,7 +4620,7 @@
                         becomeInactiveIfAppropriateLocked();
                         int curLightState = mLightState;
                         while (curLightState != LIGHT_STATE_IDLE) {
-                            stepLightIdleStateLocked("s:shell", /* forceProgression */ true);
+                            stepLightIdleStateLocked("s:shell");
                             if (curLightState == mLightState) {
                                 pw.print("Unable to go light idle; stopped at ");
                                 pw.println(lightStateToString(mLightState));
@@ -5266,19 +5241,19 @@
             if (mNextLightIdleDelay != 0) {
                 pw.print("  mNextLightIdleDelay=");
                 TimeUtils.formatDuration(mNextLightIdleDelay, pw);
-                pw.println();
+                if (mConstants.USE_WINDOW_ALARMS) {
+                    pw.print(" (flex=");
+                    TimeUtils.formatDuration(mNextLightIdleDelayFlex, pw);
+                    pw.println(")");
+                } else {
+                    pw.println();
+                }
             }
             if (mNextLightAlarmTime != 0) {
                 pw.print("  mNextLightAlarmTime=");
                 TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
                 pw.println();
             }
-            if (mNextLightMaintenanceAlarmTime != 0) {
-                pw.print("  mNextLightMaintenanceAlarmTime=");
-                TimeUtils.formatDuration(
-                        mNextLightMaintenanceAlarmTime, SystemClock.elapsedRealtime(), pw);
-                pw.println();
-            }
             if (mCurLightIdleBudget != 0) {
                 pw.print("  mCurLightIdleBudget=");
                 TimeUtils.formatDuration(mCurLightIdleBudget, pw);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index c5510b7..6a7904c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -3744,7 +3744,7 @@
         // Enforce that only the app itself (or shared uid participant) can schedule a
         // job that runs one of the app's services, as well as verifying that the
         // named service properly requires the BIND_JOB_SERVICE permission
-        private void enforceValidJobRequest(int uid, JobInfo job) {
+        private void enforceValidJobRequest(int uid, int pid, JobInfo job) {
             final PackageManager pm = getContext()
                     .createContextAsUser(UserHandle.getUserHandleForUid(uid), 0)
                     .getPackageManager();
@@ -3768,6 +3768,10 @@
                 throw new IllegalArgumentException(
                         "Tried to schedule job for non-existent component: " + service);
             }
+            if (job.isPersisted() && !canPersistJobs(pid, uid)) {
+                throw new IllegalArgumentException("Requested job cannot be persisted without"
+                        + " holding android.permission.RECEIVE_BOOT_COMPLETED permission");
+            }
         }
 
         private boolean canPersistJobs(int pid, int uid) {
@@ -3915,13 +3919,7 @@
             final int uid = Binder.getCallingUid();
             final int userId = UserHandle.getUserId(uid);
 
-            enforceValidJobRequest(uid, job);
-            if (job.isPersisted()) {
-                if (!canPersistJobs(pid, uid)) {
-                    throw new IllegalArgumentException("Error: requested job be persisted without"
-                            + " holding RECEIVE_BOOT_COMPLETED permission.");
-                }
-            }
+            enforceValidJobRequest(uid, pid, job);
 
             final int result = validateJob(job, uid, -1, null, null);
             if (result != JobScheduler.RESULT_SUCCESS) {
@@ -3948,9 +3946,10 @@
                 Slog.d(TAG, "Enqueueing job: " + job.toString() + " work: " + work);
             }
             final int uid = Binder.getCallingUid();
+            final int pid = Binder.getCallingPid();
             final int userId = UserHandle.getUserId(uid);
 
-            enforceValidJobRequest(uid, job);
+            enforceValidJobRequest(uid, pid, job);
             if (work == null) {
                 throw new NullPointerException("work is null");
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index d048cca..ceb47ea 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -107,6 +107,8 @@
     private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
     /** Amount of time the JobScheduler will wait for a response from an app for a message. */
     private static final long OP_TIMEOUT_MILLIS = 8 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
+    /** Amount of time the JobScheduler will wait for a job to provide a required notification. */
+    private static final long NOTIFICATION_TIMEOUT_MILLIS = 10_000L * Build.HW_TIMEOUT_MULTIPLIER;
 
     private static final String[] VERB_STRINGS = {
             "VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED"
@@ -190,6 +192,8 @@
     private long mMinExecutionGuaranteeMillis;
     /** The absolute maximum amount of time the job can run */
     private long mMaxExecutionTimeMillis;
+    /** Whether this job is required to provide a notification and we're still waiting for it. */
+    private boolean mAwaitingNotification;
 
     private long mEstimatedDownloadBytes;
     private long mEstimatedUploadBytes;
@@ -348,6 +352,7 @@
             mEstimatedDownloadBytes = job.getEstimatedNetworkDownloadBytes();
             mEstimatedUploadBytes = job.getEstimatedNetworkUploadBytes();
             mTransferredDownloadBytes = mTransferredUploadBytes = 0;
+            mAwaitingNotification = job.isUserVisibleJob();
 
             final long whenDeferred = job.getWhenStandbyDeferred();
             if (whenDeferred > 0) {
@@ -771,6 +776,12 @@
                 mNotificationCoordinator.enqueueNotification(this, callingPkgName,
                         callingPid, callingUid, notificationId,
                         notification, jobEndNotificationPolicy);
+                if (mAwaitingNotification) {
+                    mAwaitingNotification = false;
+                    if (mVerb == VERB_EXECUTING) {
+                        scheduleOpTimeOutLocked();
+                    }
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -1183,6 +1194,8 @@
                 }
                 final long latestStopTimeElapsed =
                         mExecutionStartTimeElapsed + mMaxExecutionTimeMillis;
+                final long earliestStopTimeElapsed =
+                        mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis;
                 final long nowElapsed = sElapsedRealtimeClock.millis();
                 if (nowElapsed >= latestStopTimeElapsed) {
                     // Not an error - client ran out of time.
@@ -1191,7 +1204,7 @@
                     mParams.setStopReason(JobParameters.STOP_REASON_TIMEOUT,
                             JobParameters.INTERNAL_STOP_REASON_TIMEOUT, "client timed out");
                     sendStopMessageLocked("timeout while executing");
-                } else {
+                } else if (nowElapsed >= earliestStopTimeElapsed) {
                     // We've given the app the minimum execution time. See if we should stop it or
                     // let it continue running
                     final String reason = mJobConcurrencyManager.shouldStopRunningJobLocked(this);
@@ -1209,6 +1222,14 @@
                                 + " continue to run past min execution time");
                         scheduleOpTimeOutLocked();
                     }
+                } else if (mAwaitingNotification) {
+                    onSlowAppResponseLocked(/* reschedule */ true, /* updateStopReasons */ true,
+                            /* debugReason */ "timed out while stopping",
+                            /* anrMessage */ "required notification not provided",
+                            /* triggerAnr */ true);
+                } else {
+                    Slog.e(TAG, "Unexpected op timeout while EXECUTING");
+                    scheduleOpTimeOutLocked();
                 }
                 break;
             default:
@@ -1402,20 +1423,24 @@
     private void scheduleOpTimeOutLocked() {
         removeOpTimeOutLocked();
 
-        // TODO(260848384): enforce setNotification timeout for user-initiated jobs
         final long timeoutMillis;
         switch (mVerb) {
             case VERB_EXECUTING:
+                long minTimeout;
                 final long earliestStopTimeElapsed =
                         mExecutionStartTimeElapsed + mMinExecutionGuaranteeMillis;
                 final long latestStopTimeElapsed =
                         mExecutionStartTimeElapsed + mMaxExecutionTimeMillis;
                 final long nowElapsed = sElapsedRealtimeClock.millis();
                 if (nowElapsed < earliestStopTimeElapsed) {
-                    timeoutMillis = earliestStopTimeElapsed - nowElapsed;
+                    minTimeout = earliestStopTimeElapsed - nowElapsed;
                 } else {
-                    timeoutMillis = latestStopTimeElapsed - nowElapsed;
+                    minTimeout = latestStopTimeElapsed - nowElapsed;
                 }
+                if (mAwaitingNotification) {
+                    minTimeout = Math.min(minTimeout, NOTIFICATION_TIMEOUT_MILLIS);
+                }
+                timeoutMillis = minTimeout;
                 break;
 
             case VERB_BINDING:
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 9909764..a3d566b 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -286,7 +286,7 @@
 
     /**
      * Map of uids to their current app-op mode for
-     * {@link AppOpsManager#OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY}.
+     * {@link AppOpsManager#OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS}.
      */
     @GuardedBy("mSystemExemptionAppOpMode")
     private final SparseIntArray mSystemExemptionAppOpMode = new SparseIntArray();
@@ -670,7 +670,7 @@
             IAppOpsService iAppOpsService = mInjector.getAppOpsService();
             try {
                 iAppOpsService.startWatchingMode(
-                        AppOpsManager.OP_SYSTEM_EXEMPT_FROM_APP_STANDBY,
+                        AppOpsManager.OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
                         /*packageName=*/ null,
                         new IAppOpsCallback.Stub() {
                             @Override
@@ -1482,7 +1482,8 @@
                     }
                 } else {
                     int mode = mAppOpsManager.checkOpNoThrow(
-                            AppOpsManager.OP_SYSTEM_EXEMPT_FROM_APP_STANDBY, uid, packageName);
+                            AppOpsManager.OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS, uid,
+                            packageName);
                     mSystemExemptionAppOpMode.put(uid, mode);
                     if (mode == AppOpsManager.MODE_ALLOWED) {
                         return STANDBY_BUCKET_EXEMPTED;
diff --git a/core/api/current.txt b/core/api/current.txt
index 765974a..8216f89 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -147,6 +147,7 @@
     field public static final String MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE = "android.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE";
     field public static final String MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES = "android.permission.MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES";
     field public static final String MANAGE_DEVICE_POLICY_DEFAULT_SMS = "android.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS";
+    field public static final String MANAGE_DEVICE_POLICY_DEVICE_IDENTIFIERS = "android.permission.MANAGE_DEVICE_POLICY_DEVICE_IDENTIFIERS";
     field public static final String MANAGE_DEVICE_POLICY_DISPLAY = "android.permission.MANAGE_DEVICE_POLICY_DISPLAY";
     field public static final String MANAGE_DEVICE_POLICY_FACTORY_RESET = "android.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET";
     field public static final String MANAGE_DEVICE_POLICY_FUN = "android.permission.MANAGE_DEVICE_POLICY_FUN";
@@ -2048,16 +2049,16 @@
     field public static final int system_primary_container_light;
     field public static final int system_primary_dark;
     field public static final int system_primary_fixed_dark;
-    field public static final int system_primary_fixed_darker_dark;
-    field public static final int system_primary_fixed_darker_light;
+    field public static final int system_primary_fixed_dim_dark;
+    field public static final int system_primary_fixed_dim_light;
     field public static final int system_primary_fixed_light;
     field public static final int system_primary_light;
     field public static final int system_secondary_container_dark;
     field public static final int system_secondary_container_light;
     field public static final int system_secondary_dark;
     field public static final int system_secondary_fixed_dark;
-    field public static final int system_secondary_fixed_darker_dark;
-    field public static final int system_secondary_fixed_darker_light;
+    field public static final int system_secondary_fixed_dim_dark;
+    field public static final int system_secondary_fixed_dim_light;
     field public static final int system_secondary_fixed_light;
     field public static final int system_secondary_light;
     field public static final int system_surface_bright_dark;
@@ -2082,8 +2083,8 @@
     field public static final int system_tertiary_container_light;
     field public static final int system_tertiary_dark;
     field public static final int system_tertiary_fixed_dark;
-    field public static final int system_tertiary_fixed_darker_dark;
-    field public static final int system_tertiary_fixed_darker_light;
+    field public static final int system_tertiary_fixed_dim_dark;
+    field public static final int system_tertiary_fixed_dim_light;
     field public static final int system_tertiary_fixed_light;
     field public static final int system_tertiary_light;
     field public static final int system_text_hint_inverse_dark;
@@ -7724,27 +7725,27 @@
 
   public class DevicePolicyManager {
     method public void acknowledgeDeviceCompliant();
-    method public void addCrossProfileIntentFilter(@NonNull android.content.ComponentName, android.content.IntentFilter, int);
-    method public boolean addCrossProfileWidgetProvider(@NonNull android.content.ComponentName, String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional=true) public void addCrossProfileIntentFilter(@Nullable android.content.ComponentName, android.content.IntentFilter, int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional=true) public boolean addCrossProfileWidgetProvider(@Nullable android.content.ComponentName, String);
     method public int addOverrideApn(@NonNull android.content.ComponentName, @NonNull android.telephony.data.ApnSetting);
-    method public void addPersistentPreferredActivity(@NonNull android.content.ComponentName, android.content.IntentFilter, @NonNull android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public void addPersistentPreferredActivity(@Nullable android.content.ComponentName, android.content.IntentFilter, @NonNull android.content.ComponentName);
     method public void addUserRestriction(@NonNull android.content.ComponentName, String);
     method public void addUserRestrictionGlobally(@NonNull String);
     method public boolean bindDeviceAdminServiceAsUser(@NonNull android.content.ComponentName, android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull android.os.UserHandle);
     method public boolean canAdminGrantSensorsPermissions();
     method public boolean canUsbDataSignalingBeDisabled();
     method public void clearApplicationUserData(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.OnClearApplicationUserDataListener);
-    method public void clearCrossProfileIntentFilters(@NonNull android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional=true) public void clearCrossProfileIntentFilters(@Nullable android.content.ComponentName);
     method @Deprecated public void clearDeviceOwnerApp(String);
-    method public void clearPackagePersistentPreferredActivities(@NonNull android.content.ComponentName, String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public void clearPackagePersistentPreferredActivities(@Nullable android.content.ComponentName, String);
     method @Deprecated public void clearProfileOwner(@NonNull android.content.ComponentName);
-    method public boolean clearResetPasswordToken(android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional=true) public boolean clearResetPasswordToken(@Nullable android.content.ComponentName);
     method public void clearUserRestriction(@NonNull android.content.ComponentName, String);
     method public android.content.Intent createAdminSupportIntent(@NonNull String);
     method @Nullable public android.os.UserHandle createAndManageUser(@NonNull android.content.ComponentName, @NonNull String, @NonNull android.content.ComponentName, @Nullable android.os.PersistableBundle, int);
     method public void enableSystemApp(@NonNull android.content.ComponentName, String);
     method public int enableSystemApp(@NonNull android.content.ComponentName, android.content.Intent);
-    method public android.security.AttestedKeyPair generateKeyPair(@Nullable android.content.ComponentName, @NonNull String, @NonNull android.security.keystore.KeyGenParameterSpec, int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public android.security.AttestedKeyPair generateKeyPair(@Nullable android.content.ComponentName, @NonNull String, @NonNull android.security.keystore.KeyGenParameterSpec, int);
     method @Nullable public String[] getAccountTypesWithManagementDisabled();
     method @Nullable public java.util.List<android.content.ComponentName> getActiveAdmins();
     method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
@@ -7752,19 +7753,19 @@
     method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
     method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
     method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
-    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeEnabled(@NonNull android.content.ComponentName);
+    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeEnabled(@Nullable android.content.ComponentName);
     method @Deprecated public boolean getAutoTimeRequired();
-    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME_ZONE, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeZoneEnabled(@NonNull android.content.ComponentName);
+    method @RequiresPermission(anyOf={android.Manifest.permission.SET_TIME_ZONE, "android.permission.QUERY_ADMIN_POLICY"}, conditional=true) public boolean getAutoTimeZoneEnabled(@Nullable android.content.ComponentName);
     method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
     method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
-    method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA, conditional=true) public boolean getCameraDisabled(@Nullable android.content.ComponentName);
     method @Deprecated @Nullable public String getCertInstallerPackage(@NonNull android.content.ComponentName) throws java.lang.SecurityException;
     method @Nullable public android.app.admin.PackagePolicy getCredentialManagerPolicy();
     method @Deprecated @Nullable public java.util.Set<java.lang.String> getCrossProfileCalendarPackages(@NonNull android.content.ComponentName);
     method @Deprecated public boolean getCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName);
     method @Deprecated public boolean getCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName);
     method @NonNull public java.util.Set<java.lang.String> getCrossProfilePackages(@NonNull android.content.ComponentName);
-    method @NonNull public java.util.List<java.lang.String> getCrossProfileWidgetProviders(@NonNull android.content.ComponentName);
+    method @NonNull @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional=true) public java.util.List<java.lang.String> getCrossProfileWidgetProviders(@Nullable android.content.ComponentName);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public int getCurrentFailedPasswordAttempts();
     method @Nullable public java.util.List<java.lang.String> getDelegatePackages(@NonNull android.content.ComponentName, @NonNull String);
     method @NonNull public java.util.List<java.lang.String> getDelegatedScopes(@Nullable android.content.ComponentName, @NonNull String);
@@ -7779,8 +7780,8 @@
     method @Nullable public java.util.List<java.lang.String> getKeepUninstalledPackages(@Nullable android.content.ComponentName);
     method @NonNull public java.util.Map<java.lang.Integer,java.util.Set<java.lang.String>> getKeyPairGrants(@NonNull String);
     method public int getKeyguardDisabledFeatures(@Nullable android.content.ComponentName);
-    method public int getLockTaskFeatures(@NonNull android.content.ComponentName);
-    method @NonNull public String[] getLockTaskPackages(@NonNull android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public int getLockTaskFeatures(@Nullable android.content.ComponentName);
+    method @NonNull @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public String[] getLockTaskPackages(@Nullable android.content.ComponentName);
     method @Nullable public CharSequence getLongSupportMessage(@NonNull android.content.ComponentName);
     method @Nullable public android.app.admin.PackagePolicy getManagedProfileCallerIdAccessPolicy();
     method @Nullable public android.app.admin.PackagePolicy getManagedProfileContactsAccessPolicy();
@@ -7794,7 +7795,7 @@
     method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyAppStreamingPolicy();
     method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyNotificationStreamingPolicy();
     method @Deprecated @ColorInt public int getOrganizationColor(@NonNull android.content.ComponentName);
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public CharSequence getOrganizationName(@Nullable android.content.ComponentName);
+    method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, conditional=true) public CharSequence getOrganizationName(@Nullable android.content.ComponentName);
     method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
     method @NonNull public android.app.admin.DevicePolicyManager getParentProfileInstance(@NonNull android.content.ComponentName);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY}, conditional=true) public int getPasswordComplexity();
@@ -7811,7 +7812,7 @@
     method @Deprecated public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName);
     method @Deprecated public int getPasswordQuality(@Nullable android.content.ComponentName);
     method @Nullable public android.app.admin.SystemUpdateInfo getPendingSystemUpdate(@NonNull android.content.ComponentName);
-    method public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, conditional=true) public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
     method public int getPermissionPolicy(android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getPermittedAccessibilityServices(@NonNull android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
@@ -7823,14 +7824,14 @@
     method @NonNull public android.app.admin.DevicePolicyResourcesManager getResources();
     method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
     method public java.util.List<android.os.UserHandle> getSecondaryUsers(@NonNull android.content.ComponentName);
-    method public CharSequence getShortSupportMessage(@NonNull android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE, conditional=true) public CharSequence getShortSupportMessage(@Nullable android.content.ComponentName);
     method public CharSequence getStartUserSessionMessage(@NonNull android.content.ComponentName);
     method @Deprecated public boolean getStorageEncryption(@Nullable android.content.ComponentName);
     method public int getStorageEncryptionStatus();
     method @Nullable public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
     method @Nullable public android.os.PersistableBundle getTransferOwnershipBundle();
     method @Nullable public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(@Nullable android.content.ComponentName, @NonNull android.content.ComponentName);
-    method @NonNull public java.util.List<java.lang.String> getUserControlDisabledPackages(@NonNull android.content.ComponentName);
+    method @NonNull @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional=true) public java.util.List<java.lang.String> getUserControlDisabledPackages(@Nullable android.content.ComponentName);
     method @NonNull public android.os.Bundle getUserRestrictions(@NonNull android.content.ComponentName);
     method @NonNull public android.os.Bundle getUserRestrictionsGlobally();
     method @Nullable public String getWifiMacAddress(@Nullable android.content.ComponentName);
@@ -7839,13 +7840,13 @@
     method public boolean grantKeyPairToWifiAuth(@NonNull String);
     method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int);
-    method public boolean hasKeyPair(@NonNull String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean hasKeyPair(@NonNull String);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public boolean hasLockdownAdminConfiguredNetworks(@Nullable android.content.ComponentName);
     method public boolean installCaCert(@Nullable android.content.ComponentName, byte[]);
     method public boolean installExistingPackage(@NonNull android.content.ComponentName, String);
-    method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String);
-    method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean);
-    method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate, @NonNull String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void installSystemUpdate(@Nullable android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public boolean isActivePasswordSufficient();
     method public boolean isActivePasswordSufficientForDeviceRequirement();
@@ -7868,11 +7869,11 @@
     method public boolean isNetworkLoggingEnabled(@Nullable android.content.ComponentName);
     method public boolean isOrganizationOwnedDeviceWithManagedProfile();
     method public boolean isOverrideApnEnabled(@NonNull android.content.ComponentName);
-    method public boolean isPackageSuspended(@NonNull android.content.ComponentName, String) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional=true) public boolean isPackageSuspended(@Nullable android.content.ComponentName, String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public boolean isPreferentialNetworkServiceEnabled();
     method public boolean isProfileOwnerApp(String);
     method public boolean isProvisioningAllowed(@NonNull String);
-    method public boolean isResetPasswordTokenActive(android.content.ComponentName);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional=true) public boolean isResetPasswordTokenActive(@Nullable android.content.ComponentName);
     method public boolean isSafeOperation(int);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName);
     method public boolean isStatusBarDisabled();
@@ -7886,40 +7887,41 @@
     method public int logoutUser(@NonNull android.content.ComponentName);
     method public void reboot(@NonNull android.content.ComponentName);
     method public void removeActiveAdmin(@NonNull android.content.ComponentName);
-    method public boolean removeCrossProfileWidgetProvider(@NonNull android.content.ComponentName, String);
-    method public boolean removeKeyPair(@Nullable android.content.ComponentName, @NonNull String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional=true) public boolean removeCrossProfileWidgetProvider(@Nullable android.content.ComponentName, String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean removeKeyPair(@Nullable android.content.ComponentName, @NonNull String);
     method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
     method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
     method public boolean requestBugreport(@NonNull android.content.ComponentName);
     method @Deprecated public boolean resetPassword(String, int);
-    method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional=true) public boolean resetPasswordWithToken(@Nullable android.content.ComponentName, String, byte[], int);
     method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
     method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(@Nullable android.content.ComponentName);
     method @Nullable @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(@Nullable android.content.ComponentName);
     method public boolean revokeKeyPairFromApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
     method public boolean revokeKeyPairFromWifiAuth(@NonNull String);
-    method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, conditional=true) public void setAccountManagementDisabled(@Nullable android.content.ComponentName, String, boolean);
     method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
     method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
     method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean, @Nullable java.util.Set<java.lang.String>) throws android.content.pm.PackageManager.NameNotFoundException;
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional=true) public boolean setApplicationHidden(@Nullable android.content.ComponentName, String, boolean);
     method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
     method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimeEnabled(@NonNull android.content.ComponentName, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public void setAutoTimeEnabled(@Nullable android.content.ComponentName, boolean);
     method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
-    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZoneEnabled(@NonNull android.content.ComponentName, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZoneEnabled(@Nullable android.content.ComponentName, boolean);
     method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA, conditional=true) public void setCameraDisabled(@Nullable android.content.ComponentName, boolean);
     method @Deprecated public void setCertInstallerPackage(@NonNull android.content.ComponentName, @Nullable String) throws java.lang.SecurityException;
-    method public void setCommonCriteriaModeEnabled(@NonNull android.content.ComponentName, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE, conditional=true) public void setCommonCriteriaModeEnabled(@Nullable android.content.ComponentName, boolean);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setConfiguredNetworksLockdownState(@Nullable android.content.ComponentName, boolean);
     method public void setCredentialManagerPolicy(@Nullable android.app.admin.PackagePolicy);
     method @Deprecated public void setCrossProfileCalendarPackages(@NonNull android.content.ComponentName, @Nullable java.util.Set<java.lang.String>);
     method @Deprecated public void setCrossProfileCallerIdDisabled(@NonNull android.content.ComponentName, boolean);
     method @Deprecated public void setCrossProfileContactsSearchDisabled(@NonNull android.content.ComponentName, boolean);
     method public void setCrossProfilePackages(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
-    method public void setDefaultSmsApplication(@NonNull android.content.ComponentName, @NonNull String);
+    method public void setDefaultDialerApplication(@NonNull String);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS, conditional=true) public void setDefaultSmsApplication(@Nullable android.content.ComponentName, @NonNull String);
     method public void setDelegatedScopes(@NonNull android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.lang.String>);
     method public void setDeviceOwnerLockScreenInfo(@NonNull android.content.ComponentName, CharSequence);
     method public void setEndUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
@@ -7928,12 +7930,12 @@
     method @WorkerThread public int setGlobalPrivateDnsModeSpecifiedHost(@NonNull android.content.ComponentName, @NonNull String);
     method public void setGlobalSetting(@NonNull android.content.ComponentName, String, String);
     method public void setKeepUninstalledPackages(@Nullable android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
-    method public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES, conditional=true) public boolean setKeyPairCertificate(@Nullable android.content.ComponentName, @NonNull String, @NonNull java.util.List<java.security.cert.Certificate>, boolean);
     method public boolean setKeyguardDisabled(@NonNull android.content.ComponentName, boolean);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD, conditional=true) public void setKeyguardDisabledFeatures(@Nullable android.content.ComponentName, int);
     method public void setLocationEnabled(@NonNull android.content.ComponentName, boolean);
-    method public void setLockTaskFeatures(@NonNull android.content.ComponentName, int);
-    method public void setLockTaskPackages(@NonNull android.content.ComponentName, @NonNull String[]) throws java.lang.SecurityException;
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public void setLockTaskFeatures(@Nullable android.content.ComponentName, int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK, conditional=true) public void setLockTaskPackages(@Nullable android.content.ComponentName, @NonNull String[]) throws java.lang.SecurityException;
     method public void setLogoutEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setLongSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
     method public void setManagedProfileCallerIdAccessPolicy(@Nullable android.app.admin.PackagePolicy);
@@ -7951,9 +7953,9 @@
     method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
     method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
     method public void setOrganizationId(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public void setOrganizationName(@Nullable android.content.ComponentName, @Nullable CharSequence);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, conditional=true) public void setOrganizationName(@Nullable android.content.ComponentName, @Nullable CharSequence);
     method public void setOverrideApnsEnabled(@NonNull android.content.ComponentName, boolean);
-    method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean);
+    method @NonNull @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional=true) public String[] setPackagesSuspended(@Nullable android.content.ComponentName, @NonNull String[], boolean);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setPasswordExpirationTimeout(@Nullable android.content.ComponentName, long);
     method public void setPasswordHistoryLength(@NonNull android.content.ComponentName, int);
     method @Deprecated public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int);
@@ -7964,7 +7966,7 @@
     method @Deprecated public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int);
     method @Deprecated public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int);
     method @Deprecated public void setPasswordQuality(@NonNull android.content.ComponentName, int);
-    method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, @NonNull String, @NonNull String, int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, conditional=true) public boolean setPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String, int);
     method public void setPermissionPolicy(@NonNull android.content.ComponentName, int);
     method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
@@ -7977,23 +7979,23 @@
     method public void setRecommendedGlobalProxy(@NonNull android.content.ComponentName, @Nullable android.net.ProxyInfo);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setRequiredPasswordComplexity(int);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, conditional=true) public void setRequiredStrongAuthTimeout(@Nullable android.content.ComponentName, long);
-    method public boolean setResetPasswordToken(android.content.ComponentName, byte[]);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional=true) public boolean setResetPasswordToken(@Nullable android.content.ComponentName, byte[]);
     method public void setRestrictionsProvider(@NonNull android.content.ComponentName, @Nullable android.content.ComponentName);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE, conditional=true) public void setScreenCaptureDisabled(@Nullable android.content.ComponentName, boolean);
     method public void setSecureSetting(@NonNull android.content.ComponentName, String, String);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional=true) public void setSecurityLoggingEnabled(@Nullable android.content.ComponentName, boolean);
-    method public void setShortSupportMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE, conditional=true) public void setShortSupportMessage(@Nullable android.content.ComponentName, @Nullable CharSequence);
     method public void setStartUserSessionMessage(@NonNull android.content.ComponentName, @Nullable CharSequence);
-    method public boolean setStatusBarDisabled(@NonNull android.content.ComponentName, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR, conditional=true) public boolean setStatusBarDisabled(@Nullable android.content.ComponentName, boolean);
     method @Deprecated public int setStorageEncryption(@NonNull android.content.ComponentName, boolean);
     method public void setSystemSetting(@NonNull android.content.ComponentName, @NonNull String, String);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, conditional=true) public void setSystemUpdatePolicy(@NonNull android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
-    method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public boolean setTime(@NonNull android.content.ComponentName, long);
-    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public boolean setTimeZone(@NonNull android.content.ComponentName, String);
+    method @RequiresPermission(value=android.Manifest.permission.SET_TIME, conditional=true) public boolean setTime(@Nullable android.content.ComponentName, long);
+    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public boolean setTimeZone(@Nullable android.content.ComponentName, String);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD, conditional=true) public void setTrustAgentConfiguration(@Nullable android.content.ComponentName, @NonNull android.content.ComponentName, android.os.PersistableBundle);
-    method public void setUninstallBlocked(@Nullable android.content.ComponentName, String, boolean);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional=true) public void setUninstallBlocked(@Nullable android.content.ComponentName, String, boolean);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional=true) public void setUsbDataSignalingEnabled(boolean);
-    method public void setUserControlDisabledPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional=true) public void setUserControlDisabledPackages(@Nullable android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
     method public void setUserIcon(@NonNull android.content.ComponentName, android.graphics.Bitmap);
     method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI, conditional=true) public void setWifiSsidPolicy(@Nullable android.app.admin.WifiSsidPolicy);
     method public int startUserInBackground(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
@@ -8003,9 +8005,9 @@
     method public void uninstallAllUserCaCerts(@Nullable android.content.ComponentName);
     method public void uninstallCaCert(@Nullable android.content.ComponentName, byte[]);
     method public boolean updateOverrideApn(@NonNull android.content.ComponentName, int, @NonNull android.telephony.data.ApnSetting);
-    method public void wipeData(int);
-    method public void wipeData(int, @NonNull CharSequence);
-    method public void wipeDevice(int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA, conditional=true) public void wipeData(int);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA, conditional=true) public void wipeData(int, @NonNull CharSequence);
+    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA, conditional=true) public void wipeDevice(int);
     field public static final String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
     field public static final String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE";
     field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
@@ -10243,7 +10245,6 @@
     method @Deprecated public abstract int getWallpaperDesiredMinimumHeight();
     method @Deprecated public abstract int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(String, android.net.Uri, int);
-    method public boolean isDeviceContext();
     method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
     method public boolean isUiContext();
@@ -11355,7 +11356,8 @@
   public class RestrictionsManager {
     method public static android.os.Bundle convertRestrictionsToBundle(java.util.List<android.content.RestrictionEntry>);
     method public android.content.Intent createLocalApprovalIntent();
-    method public android.os.Bundle getApplicationRestrictions();
+    method @Deprecated public android.os.Bundle getApplicationRestrictions();
+    method @NonNull @WorkerThread public java.util.List<android.os.Bundle> getApplicationRestrictionsPerAdmin();
     method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(String);
     method public boolean hasRestrictionsProvider();
     method public void notifyPermissionResponse(String, android.os.PersistableBundle);
@@ -15445,8 +15447,9 @@
     ctor @Deprecated public EmbossMaskFilter(float[], float, float, float);
   }
 
-  public final class Gainmap {
+  public final class Gainmap implements android.os.Parcelable {
     ctor public Gainmap(@NonNull android.graphics.Bitmap);
+    method public int describeContents();
     method @NonNull public float getDisplayRatioForFullHdr();
     method @NonNull public float[] getEpsilonHdr();
     method @NonNull public float[] getEpsilonSdr();
@@ -15463,6 +15466,8 @@
     method @NonNull public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float);
     method @NonNull public void setRatioMax(float, float, float);
     method @NonNull public void setRatioMin(float, float, float);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Gainmap> CREATOR;
   }
 
   public class HardwareBufferRenderer implements java.lang.AutoCloseable {
@@ -33748,7 +33753,7 @@
 
   public class UserManager {
     method public static android.content.Intent createUserCreationIntent(@Nullable String, @Nullable String, @Nullable String, @Nullable android.os.PersistableBundle);
-    method @WorkerThread public android.os.Bundle getApplicationRestrictions(String);
+    method @Deprecated @WorkerThread public android.os.Bundle getApplicationRestrictions(String);
     method public long getSerialNumberForUser(android.os.UserHandle);
     method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS"}) public int getUserCount();
     method public long getUserCreationTime(android.os.UserHandle);
@@ -41388,6 +41393,7 @@
     method public void onEndOfSpeech();
     method public void onError(int);
     method public void onEvent(int, android.os.Bundle);
+    method public default void onLanguageDetection(@NonNull android.os.Bundle);
     method public void onPartialResults(android.os.Bundle);
     method public void onReadyForSpeech(android.os.Bundle);
     method public void onResults(android.os.Bundle);
@@ -41445,6 +41451,7 @@
     method public void error(int) throws android.os.RemoteException;
     method @NonNull public android.content.AttributionSource getCallingAttributionSource();
     method public int getCallingUid();
+    method public void languageDetection(@NonNull android.os.Bundle);
     method public void partialResults(android.os.Bundle) throws android.os.RemoteException;
     method public void readyForSpeech(android.os.Bundle) throws android.os.RemoteException;
     method public void results(android.os.Bundle) throws android.os.RemoteException;
@@ -41502,10 +41509,14 @@
     field public static final String EXTRA_CONFIDENCE_SCORES = "android.speech.extra.CONFIDENCE_SCORES";
     field public static final String EXTRA_ENABLE_BIASING_DEVICE_CONTEXT = "android.speech.extra.ENABLE_BIASING_DEVICE_CONTEXT";
     field public static final String EXTRA_ENABLE_FORMATTING = "android.speech.extra.ENABLE_FORMATTING";
+    field public static final String EXTRA_ENABLE_LANGUAGE_DETECTION = "android.speech.extra.ENABLE_LANGUAGE_DETECTION";
+    field public static final String EXTRA_ENABLE_LANGUAGE_SWITCH = "android.speech.extra.ENABLE_LANGUAGE_SWITCH";
     field public static final String EXTRA_HIDE_PARTIAL_TRAILING_PUNCTUATION = "android.speech.extra.HIDE_PARTIAL_TRAILING_PUNCTUATION";
     field public static final String EXTRA_LANGUAGE = "android.speech.extra.LANGUAGE";
+    field public static final String EXTRA_LANGUAGE_DETECTION_ALLOWED_LANGUAGES = "android.speech.extra.LANGUAGE_DETECTION_ALLOWED_LANGUAGES";
     field public static final String EXTRA_LANGUAGE_MODEL = "android.speech.extra.LANGUAGE_MODEL";
     field public static final String EXTRA_LANGUAGE_PREFERENCE = "android.speech.extra.LANGUAGE_PREFERENCE";
+    field public static final String EXTRA_LANGUAGE_SWITCH_ALLOWED_LANGUAGES = "android.speech.extra.LANGUAGE_SWITCH_ALLOWED_LANGUAGES";
     field public static final String EXTRA_MASK_OFFENSIVE_WORDS = "android.speech.extra.MASK_OFFENSIVE_WORDS";
     field public static final String EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS";
     field public static final String EXTRA_ONLY_RETURN_LANGUAGE_PREFERENCE = "android.speech.extra.ONLY_RETURN_LANGUAGE_PREFERENCE";
@@ -41529,6 +41540,9 @@
     field public static final String FORMATTING_OPTIMIZE_QUALITY = "quality";
     field public static final String LANGUAGE_MODEL_FREE_FORM = "free_form";
     field public static final String LANGUAGE_MODEL_WEB_SEARCH = "web_search";
+    field public static final String LANGUAGE_SWITCH_BALANCED = "balanced";
+    field public static final String LANGUAGE_SWITCH_HIGH_PRECISION = "high_precision";
+    field public static final String LANGUAGE_SWITCH_QUICK_RESPONSE = "quick_response";
     field public static final int RESULT_AUDIO_ERROR = 5; // 0x5
     field public static final int RESULT_CLIENT_ERROR = 2; // 0x2
     field public static final int RESULT_NETWORK_ERROR = 4; // 0x4
@@ -41562,6 +41576,7 @@
     method @MainThread public void stopListening();
     method public void triggerModelDownload(@NonNull android.content.Intent);
     field public static final String CONFIDENCE_SCORES = "confidence_scores";
+    field public static final String DETECTED_LANGUAGE = "detected_language";
     field public static final int ERROR_AUDIO = 3; // 0x3
     field public static final int ERROR_CANNOT_CHECK_SUPPORT = 14; // 0xe
     field public static final int ERROR_CANNOT_LISTEN_TO_DOWNLOAD_EVENTS = 15; // 0xf
@@ -41577,9 +41592,20 @@
     field public static final int ERROR_SERVER_DISCONNECTED = 11; // 0xb
     field public static final int ERROR_SPEECH_TIMEOUT = 6; // 0x6
     field public static final int ERROR_TOO_MANY_REQUESTS = 10; // 0xa
+    field public static final String LANGUAGE_DETECTION_CONFIDENCE_LEVEL = "language_detection_confidence_level";
+    field public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT = 2; // 0x2
+    field public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT = 3; // 0x3
+    field public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT = 1; // 0x1
+    field public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_UNKNOWN = 0; // 0x0
+    field public static final String LANGUAGE_SWITCH_RESULT = "language_switch_result";
+    field public static final int LANGUAGE_SWITCH_RESULT_FAILED = 2; // 0x2
+    field public static final int LANGUAGE_SWITCH_RESULT_NOT_ATTEMPTED = 0; // 0x0
+    field public static final int LANGUAGE_SWITCH_RESULT_SKIPPED_NO_MODEL = 3; // 0x3
+    field public static final int LANGUAGE_SWITCH_RESULT_SUCCEEDED = 1; // 0x1
     field public static final String RECOGNITION_PARTS = "recognition_parts";
     field public static final String RESULTS_ALTERNATIVES = "results_alternatives";
     field public static final String RESULTS_RECOGNITION = "results_recognition";
+    field public static final String TOP_LOCALE_ALTERNATIVES = "top_locale_alternatives";
   }
 
 }
@@ -54143,6 +54169,7 @@
     method public android.view.accessibility.AccessibilityWindowInfo getWindow();
     method public int getWindowId();
     method public boolean hasRequestInitialAccessibilityFocus();
+    method public boolean hasRequestTouchPassthrough();
     method public boolean isAccessibilityFocused();
     method public boolean isCheckable();
     method public boolean isChecked();
@@ -54224,6 +54251,7 @@
     method public void setQueryFromAppProcessEnabled(@NonNull android.view.View, boolean);
     method public void setRangeInfo(android.view.accessibility.AccessibilityNodeInfo.RangeInfo);
     method public void setRequestInitialAccessibilityFocus(boolean);
+    method public void setRequestTouchPassthrough(boolean);
     method public void setScreenReaderFocusable(boolean);
     method public void setScrollable(boolean);
     method public void setSelected(boolean);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2341971..fb544a9 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -71,6 +71,7 @@
     field public static final String BIND_RESUME_ON_REBOOT_SERVICE = "android.permission.BIND_RESUME_ON_REBOOT_SERVICE";
     field public static final String BIND_ROTATION_RESOLVER_SERVICE = "android.permission.BIND_ROTATION_RESOLVER_SERVICE";
     field public static final String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
+    field public static final String BIND_SATELLITE_SERVICE = "android.permission.BIND_SATELLITE_SERVICE";
     field public static final String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
     field public static final String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE";
     field public static final String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
@@ -325,6 +326,7 @@
     field public static final String SET_CLIP_SOURCE = "android.permission.SET_CLIP_SOURCE";
     field public static final String SET_DEFAULT_ACCOUNT_FOR_CONTACTS = "android.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS";
     field public static final String SET_HARMFUL_APP_WARNINGS = "android.permission.SET_HARMFUL_APP_WARNINGS";
+    field public static final String SET_LOW_POWER_STANDBY_PORTS = "android.permission.SET_LOW_POWER_STANDBY_PORTS";
     field public static final String SET_MEDIA_KEY_LISTENER = "android.permission.SET_MEDIA_KEY_LISTENER";
     field public static final String SET_ORIENTATION = "android.permission.SET_ORIENTATION";
     field public static final String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED";
@@ -463,6 +465,7 @@
     field public static final int config_systemAutomotiveCalendarSyncManager = 17039423; // 0x104003f
     field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
     field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
+    field public static final int config_systemCallStreaming;
     field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039
     field public static final int config_systemContacts = 17039403; // 0x104002b
     field public static final int config_systemFinancedDeviceController;
@@ -576,6 +579,7 @@
     field public static final int HISTORY_FLAGS_ALL = 3; // 0x3
     field public static final int HISTORY_FLAG_AGGREGATE = 1; // 0x1
     field public static final int HISTORY_FLAG_DISCRETE = 2; // 0x2
+    field public static final int HISTORY_FLAG_GET_ATTRIBUTION_CHAINS = 4; // 0x4
     field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
     field public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
     field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
@@ -1296,11 +1300,10 @@
     field @Deprecated public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE";
     field @RequiresPermission(android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP) public static final String ACTION_UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER = "android.app.action.UPDATE_DEVICE_POLICY_MANAGEMENT_ROLE_HOLDER";
     field public static final int EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION = 2; // 0x2
-    field public static final int EXEMPT_FROM_APP_STANDBY = 0; // 0x0
     field public static final int EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS = 1; // 0x1
-    field public static final int EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION = 4; // 0x4
     field public static final int EXEMPT_FROM_HIBERNATION = 3; // 0x3
-    field public static final int EXEMPT_FROM_POWER_RESTRICTIONS = 5; // 0x5
+    field public static final int EXEMPT_FROM_POWER_RESTRICTIONS = 4; // 0x4
+    field public static final int EXEMPT_FROM_SUSPENSION = 0; // 0x0
     field public static final String EXTRA_FORCE_UPDATE_ROLE_HOLDER = "android.app.extra.FORCE_UPDATE_ROLE_HOLDER";
     field public static final String EXTRA_LOST_MODE_LOCATION = "android.app.extra.LOST_MODE_LOCATION";
     field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
@@ -6874,7 +6877,7 @@
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE"}) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public java.util.List<java.lang.Integer> getIndependentStreamTypes();
     method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int getLastAudibleStreamVolume(int);
-    method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int getLastAudibleVolumeGroupVolume(int);
+    method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int getLastAudibleVolumeForVolumeGroup(int);
     method @IntRange(from=0) public long getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
@@ -10054,7 +10057,7 @@
   public class SharedConnectivityManager {
     method public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
     method public boolean connectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public boolean disconnectTetherNetwork();
+    method public boolean disconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
     method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
     method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
     method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
@@ -10141,7 +10144,7 @@
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
     method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public abstract void onDisconnectTetherNetwork();
+    method public abstract void onDisconnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
     method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
     method public final void setKnownNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
     method public final void setSettingsState(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
@@ -10660,6 +10663,7 @@
   public final class PowerManager {
     method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
     method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_LOW_POWER_STANDBY, android.Manifest.permission.DEVICE_POWER}) public java.util.List<android.os.PowerManager.LowPowerStandbyPortDescription> getActiveLowPowerStandbyPorts();
     method @NonNull public android.os.BatterySaverPolicyConfig getFullPowerSavePolicy();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_LOW_POWER_STANDBY, android.Manifest.permission.DEVICE_POWER}) public android.os.PowerManager.LowPowerStandbyPolicy getLowPowerStandbyPolicy();
     method public int getPowerSaveModeTrigger();
@@ -10667,6 +10671,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressed();
     method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_LOW_POWER_STANDBY, android.Manifest.permission.DEVICE_POWER}) public boolean isLowPowerStandbySupported();
+    method @NonNull @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS) public android.os.PowerManager.LowPowerStandbyPortsLock newLowPowerStandbyPortsLock(@NonNull java.util.List<android.os.PowerManager.LowPowerStandbyPortDescription>);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
     method @RequiresPermission(anyOf={android.Manifest.permission.BATTERY_PREDICTION, android.Manifest.permission.DEVICE_POWER}) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
@@ -10678,6 +10683,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
+    field @RequiresPermission(android.Manifest.permission.MANAGE_LOW_POWER_STANDBY) public static final String ACTION_LOW_POWER_STANDBY_PORTS_CHANGED = "android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED";
     field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
     field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
     field public static final String REBOOT_USERSPACE = "userspace";
@@ -10700,6 +10706,25 @@
     method @NonNull public String getIdentifier();
   }
 
+  public static final class PowerManager.LowPowerStandbyPortDescription {
+    ctor public PowerManager.LowPowerStandbyPortDescription(int, int, int);
+    ctor public PowerManager.LowPowerStandbyPortDescription(int, int, int, @Nullable android.net.LinkAddress);
+    method @Nullable public android.net.LinkAddress getBindAddress();
+    method public int getPortMatcher();
+    method public int getPortNumber();
+    method public int getProtocol();
+    field public static final int MATCH_PORT_LOCAL = 1; // 0x1
+    field public static final int MATCH_PORT_REMOTE = 2; // 0x2
+    field public static final int PROTOCOL_TCP = 1; // 0x1
+    field public static final int PROTOCOL_UDP = 2; // 0x2
+  }
+
+  public final class PowerManager.LowPowerStandbyPortsLock {
+    method @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS) public void acquire();
+    method protected void finalize();
+    method @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS) public void release();
+  }
+
   @Deprecated public class PowerWhitelistManager {
     method @Deprecated @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
     method @Deprecated @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 4e364a2..d5ced04 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -627,6 +627,13 @@
     method @NonNull public android.app.admin.ResolutionMechanism<V> getResolutionMechanism();
   }
 
+  public abstract class PolicyUpdateReceiver extends android.content.BroadcastReceiver {
+    field public static final String EXTRA_POLICY_BUNDLE_KEY = "android.app.admin.extra.POLICY_BUNDLE_KEY";
+    field public static final String EXTRA_POLICY_KEY = "android.app.admin.extra.POLICY_KEY";
+    field public static final String EXTRA_POLICY_TARGET_USER_ID = "android.app.admin.extra.POLICY_TARGET_USER_ID";
+    field public static final String EXTRA_POLICY_UPDATE_RESULT_KEY = "android.app.admin.extra.POLICY_UPDATE_RESULT_KEY";
+  }
+
   public abstract class ResolutionMechanism<V> implements android.os.Parcelable {
   }
 
@@ -642,6 +649,13 @@
     field @NonNull public static final android.app.admin.StringSetUnion STRING_SET_UNION;
   }
 
+  public final class TargetUser {
+    field public static final int GLOBAL_USER_ID = -3; // 0xfffffffd
+    field public static final int LOCAL_USER_ID = -1; // 0xffffffff
+    field public static final int PARENT_USER_ID = -2; // 0xfffffffe
+    field public static final int UNKNOWN_USER_ID = -3; // 0xfffffffd
+  }
+
   public final class TopPriority<V> extends android.app.admin.ResolutionMechanism<V> {
     method public int describeContents();
     method @NonNull public java.util.List<android.app.admin.Authority> getHighestToLowestPriorityAuthorities();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index c4fd991..52e2024 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2075,7 +2075,9 @@
     public static final String OPSTR_USE_FULL_SCREEN_INTENT = "android:use_full_screen_intent";
 
     /**
-     *  Prevent an app from being placed into hibernation.
+     * Prevent an app from being placed into hibernation.
+     *
+     * Only to be used by the system.
      *
      * @hide
      */
@@ -2084,7 +2086,9 @@
             "android:system_exempt_from_hibernation";
 
     /**
-     *  Prevent an app from being suspended.
+     * Prevent an app from being suspended.
+     *
+     * Only to be used by the system.
      *
      * @hide
      */
@@ -2583,7 +2587,8 @@
                 "SYSTEM_EXEMPT_FROM_APP_STANDBY").build(),
         new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
                 OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
-                "SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS").build(),
+                "SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS")
+                .setDisableReset(true).build(),
         new AppOpInfo.Builder(OP_READ_WRITE_HEALTH_DATA, OPSTR_READ_WRITE_HEALTH_DATA,
                 "READ_WRITE_HEALTH_DATA").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
         new AppOpInfo.Builder(OP_FOREGROUND_SERVICE_SPECIAL_USE,
@@ -2591,7 +2596,8 @@
                 .setPermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE).build(),
         new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
                 OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
-                "SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS").build(),
+                "SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS")
+                .setDisableReset(true).build(),
         new AppOpInfo.Builder(
                 OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
                 OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
@@ -2599,7 +2605,8 @@
                 .build(),
         new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
                 OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
-                "SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION").build(),
+                "SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION")
+                .setDisableReset(true).build(),
         new AppOpInfo.Builder(
                 OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
                 OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
@@ -2616,7 +2623,8 @@
                 .build(),
         new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_HIBERNATION,
                 OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
-                "SYSTEM_EXEMPT_FROM_HIBERNATION").build(),
+                "SYSTEM_EXEMPT_FROM_HIBERNATION")
+                .setDisableReset(true).build(),
         new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_SUSPENSION,
                 OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION,
                 "SYSTEM_EXEMPT_FROM_SUSPENSION")
@@ -4604,10 +4612,9 @@
      * Flag for querying app op history: assemble attribution chains, and attach the last visible
      * node in the chain to the start as a proxy info. This only applies to discrete accesses.
      *
-     * TODO 191512294: Add to @SystemApi
-     *
      * @hide
      */
+    @SystemApi
     public static final int HISTORY_FLAG_GET_ATTRIBUTION_CHAINS = 1 << 2;
 
     /**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bed75db..e45944e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -3068,18 +3068,6 @@
     }
 
     @Override
-    public boolean isDeviceContext() {
-        if (mIsExplicitDeviceId) {
-            if (mDeviceId == VirtualDeviceManager.DEVICE_ID_DEFAULT) {
-                return true;
-            }
-            VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
-            return vdm.isValidVirtualDeviceId(mDeviceId);
-        }
-        return isAssociatedWithDisplay();
-    }
-
-    @Override
     public void registerDeviceIdChangeListener(@NonNull @CallbackExecutor Executor executor,
             @NonNull IntConsumer listener) {
         Objects.requireNonNull(executor, "executor cannot be null");
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index bb91ecd..5cad1ae 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -43,8 +43,10 @@
 import android.os.SystemClock;
 import android.os.TestLooperManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
+import android.view.Display;
 import android.view.IWindowManager;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
@@ -93,6 +95,8 @@
 
     private static final long CONNECT_TIMEOUT_MILLIS = 5000;
 
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
     /**
      * @hide
      */
@@ -1124,10 +1128,44 @@
         newEvent.setTime(downTime, eventTime);
         newEvent.setSource(source);
         newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
+        setDisplayIfNeeded(newEvent);
+
         InputManager.getInstance().injectInputEvent(newEvent,
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
+    private void setDisplayIfNeeded(KeyEvent event) {
+        if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+            return;
+        }
+        // In devices that support visible background users visible, the display id must be set to
+        // reflect the display the user was started visible on, otherwise the event would be sent to
+        // the main display (which would most likely fail the test).
+        int eventDisplayId = event.getDisplayId();
+        if (eventDisplayId != Display.INVALID_DISPLAY) {
+            if (VERBOSE) {
+                Log.v(TAG, "setDisplayIfNeeded(" + event + "): not changing display id as it's "
+                        + "explicitly set to " + eventDisplayId);
+            }
+            return;
+        }
+
+        UserManager userManager = mInstrContext.getSystemService(UserManager.class);
+        int userDisplayId = userManager.getDisplayIdAssignedToUser();
+        if (VERBOSE) {
+            Log.v(TAG, "setDisplayIfNeeded(" + event + "): eventDisplayId=" + eventDisplayId
+                    + ", user=" + mInstrContext.getUser() + ", userDisplayId=" + userDisplayId);
+        }
+        if (userDisplayId == Display.INVALID_DISPLAY) {
+            Log.e(TAG, "setDisplayIfNeeded(" + event + "): UserManager returned INVALID_DISPLAY as "
+                    + "display assigned to user " + mInstrContext.getUser());
+            return;
+
+        }
+
+        event.setDisplayId(userDisplayId);
+    }
+
     /**
      * Sends up and down key events with the given key code to the currently focused window, and
      * waits for it to be processed.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d4151e5..3a3ad8ce 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -712,6 +712,15 @@
      */
     public static final int FLAG_NO_DISMISS = 0x00002000;
 
+    /**
+     * Bit to be bitwise-ORed into the {@link #flags} field that should be
+     * set by the system if the app that sent this notification does not have the permission to send
+     * full screen intents.
+     *
+     * This flag is for internal use only; applications cannot set this flag directly.
+     * @hide
+     */
+    public static final int FLAG_FSI_REQUESTED_BUT_DENIED = 0x00004000;
 
     private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList(
             BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
@@ -5749,7 +5758,10 @@
             List<Notification.Action> nonContextualActions = getNonContextualActions();
 
             int numActions = Math.min(nonContextualActions.size(), MAX_ACTION_BUTTONS);
-            boolean emphazisedMode = mN.fullScreenIntent != null || p.mCallStyleActions;
+            boolean emphazisedMode = mN.fullScreenIntent != null
+                    || p.mCallStyleActions
+                    || ((mN.flags & FLAG_FSI_REQUESTED_BUT_DENIED) != 0);
+
             if (p.mCallStyleActions) {
                 // Clear view padding to allow buttons to start on the left edge.
                 // This must be done before 'setEmphasizedMode' which sets top/bottom margins.
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index e1ee3e0..e0f5fb4 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -428,30 +428,18 @@
                 throw new IllegalArgumentException(msg);
         }
 
-        // Whenever creation or retrieval of a mutable implicit PendingIntent occurs:
-        // - For apps with target SDK >= U, throw an IllegalArgumentException for
-        //   security reasons.
-        // - Otherwise, warn that it will be blocked from target SDK U onwards.
-        if (isNewMutableDisallowedImplicitPendingIntent(flags, intent)) {
-            if (Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) {
-                String msg = packageName + ": Targeting U+ (version "
-                        + Build.VERSION_CODES.UPSIDE_DOWN_CAKE + " and above) disallows"
-                        + " creating or retrieving a PendingIntent with FLAG_MUTABLE,"
-                        + " an implicit Intent within and without FLAG_NO_CREATE and"
-                        + " FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for"
-                        + " security reasons. To retrieve an already existing"
-                        + " PendingIntent, use FLAG_NO_CREATE, however, to create a"
-                        + " new PendingIntent with an implicit Intent use"
-                        + " FLAG_IMMUTABLE.";
-                throw new IllegalArgumentException(msg);
-            } else {
-                String msg = "New mutable implicit PendingIntent: pkg=" + packageName
-                        + ", action=" + intent.getAction()
-                        + ", featureId=" + context.getAttributionTag()
-                        + ". This will be blocked once the app targets U+"
-                        + " for security reasons.";
-                Log.w(TAG, new RuntimeException(msg));
-            }
+        // For apps with target SDK < U, warn that creation or retrieval of a mutable
+        // implicit PendingIntent will be blocked from target SDK U onwards for security
+        // reasons. The block itself happens on the server side, but this warning has to
+        // stay here to preserve the client side stack trace for app developers.
+        if (isNewMutableDisallowedImplicitPendingIntent(flags, intent)
+                && !Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) {
+            String msg = "New mutable implicit PendingIntent: pkg=" + packageName
+                    + ", action=" + intent.getAction()
+                    + ", featureId=" + context.getAttributionTag()
+                    + ". This will be blocked once the app targets U+"
+                    + " for security reasons.";
+            Log.w(TAG, new StackTrace(msg));
         }
     }
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 94a3bbb..b6a8327 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -18,19 +18,29 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
 import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
@@ -3886,18 +3896,17 @@
     public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1;
 
     /**
-     * Prevent an app from being placed into app standby buckets, such that it will not be subject
-     * to device resources restrictions as a result of app standby buckets.
+     * Prevent an app from being suspended.
      *
      * @hide
      */
     @SystemApi
-    public static final int EXEMPT_FROM_APP_STANDBY =  0;
+    public static final int EXEMPT_FROM_SUSPENSION =  0;
 
     /**
      * Prevent an app from dismissible notifications. Starting from Android U, notifications with
      * the ongoing parameter can be dismissed by a user on an unlocked device. An app with
-     * this exemption can create non-dismissable notifications.
+     * this exemption can create non-dismissible notifications.
      *
      * @hide
      */
@@ -3921,15 +3930,6 @@
     public static final int EXEMPT_FROM_HIBERNATION =  3;
 
     /**
-     * Exempt an app from the start foreground service from background with while in user permission
-     * restriction.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION =  4;
-
-    /**
      * Exempt an app from all power-related restrictions, including app standby and doze.
      * In addition, the app will be able to start foreground services from the background,
      * and the user will not be able to stop foreground services run by the app.
@@ -3937,7 +3937,7 @@
      * @hide
      */
     @SystemApi
-    public static final int EXEMPT_FROM_POWER_RESTRICTIONS =  5;
+    public static final int EXEMPT_FROM_POWER_RESTRICTIONS =  4;
 
     /**
      * Exemptions to platform restrictions, given to an application through
@@ -3946,11 +3946,10 @@
      * @hide
      */
     @IntDef(prefix = { "EXEMPT_FROM_"}, value = {
-            EXEMPT_FROM_APP_STANDBY,
+            EXEMPT_FROM_SUSPENSION,
             EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
             EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
             EXEMPT_FROM_HIBERNATION,
-            EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
             EXEMPT_FROM_POWER_RESTRICTIONS
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -5967,9 +5966,11 @@
     }
 
     /**
-     * Called by a profile or device owner to provision a token which can later be used to reset the
-     * device lockscreen password (if called by device owner), or managed profile challenge (if
-     * called by profile owner), via {@link #resetPasswordWithToken}.
+     * Called by a profile owner, device owner or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD} to provision a token
+     * which can later be used to reset the device lockscreen password (if called by on the main or
+     * system user), or managed profile challenge (if called on a managed profile), via
+     * {@link #resetPasswordWithToken}.
      * <p>
      * If the user currently has a lockscreen password, the provisioned token will not be
      * immediately usable; it only becomes active after the user performs a confirm credential
@@ -5992,19 +5993,23 @@
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
      * reset token is not set and this method returns false.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param token a secure token a least 32-byte long, which must be generated by a
      *        cryptographically strong random number generator.
      * @return true if the operation is successful, false otherwise.
-     * @throws SecurityException if admin is not a device or profile owner.
+     * @throws SecurityException if admin is not a device or profile owner and the caller does
+     * not hold the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}.
      * @throws IllegalArgumentException if the supplied token is invalid.
      */
     @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
-    public boolean setResetPasswordToken(ComponentName admin, byte[] token) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional = true)
+    public boolean setResetPasswordToken(@Nullable ComponentName admin, byte[] token) {
         throwIfParentInstance("setResetPasswordToken");
         if (mService != null) {
             try {
-                return mService.setResetPasswordToken(admin, token);
+                return mService.setResetPasswordToken(admin, mContext.getPackageName(), token);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -6013,22 +6018,27 @@
     }
 
     /**
-     * Called by a profile or device owner to revoke the current password reset token.
+     * Called by a profile, device owner or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}
+     * to revoke the current password reset token.
      *
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, this
      * method has no effect - the reset token should not have been set in the first place - and
      * false is returned.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return true if the operation is successful, false otherwise.
-     * @throws SecurityException if admin is not a device or profile owner.
+     * @throws SecurityException if admin is not a device or profile owner and if the caller does
+     * not the permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}.
      */
     @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
-    public boolean clearResetPasswordToken(ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional = true)
+    public boolean clearResetPasswordToken(@Nullable ComponentName admin) {
         throwIfParentInstance("clearResetPasswordToken");
         if (mService != null) {
             try {
-                return mService.clearResetPasswordToken(admin);
+                return mService.clearResetPasswordToken(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -6037,22 +6047,27 @@
     }
 
     /**
-     * Called by a profile or device owner to check if the current reset password token is active.
+     * Called by a profile, device owner or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}
+     * to check if the current reset password token is active.
      *
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
      * false is always returned.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return true if the token is active, false otherwise.
-     * @throws SecurityException if admin is not a device or profile owner.
+     * @throws SecurityException if admin is not a device or profile owner and not a holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}
      * @throws IllegalStateException if no token has been set.
      */
     @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
-    public boolean isResetPasswordTokenActive(ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional = true)
+    public boolean isResetPasswordTokenActive(@Nullable ComponentName admin) {
         throwIfParentInstance("isResetPasswordTokenActive");
         if (mService != null) {
             try {
-                return mService.isResetPasswordTokenActive(admin);
+                return mService.isResetPasswordTokenActive(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -6061,8 +6076,10 @@
     }
 
     /**
-     * Called by device or profile owner to force set a new device unlock password or a managed
-     * profile challenge on current user. This takes effect immediately.
+     * Called by device owner, profile owner or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}to force set a new
+     * device unlock password or a managed profile challenge on current user. This takes effect
+     * immediately.
      * <p>
      * Unlike {@link #resetPassword}, this API can change the password even before the user or
      * device is unlocked or decrypted. The supplied token must have been previously provisioned via
@@ -6080,7 +6097,8 @@
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
      * calling this methods has no effect - the password is always empty - and false is returned.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param password The new password for the user. {@code null} or empty clears the password.
      * @param token the password reset token previously provisioned by
      *        {@link #setResetPasswordToken}.
@@ -6088,16 +6106,19 @@
      *        {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
      * @return Returns true if the password was applied, or false if it is not acceptable for the
      *         current constraints.
-     * @throws SecurityException if admin is not a device or profile owner.
+     * @throws SecurityException if admin is not a device or profile owner and the caller does not
+     * hold the permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RESET_PASSWORD}.
      * @throws IllegalStateException if the provided token is not valid.
      */
     @RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
-    public boolean resetPasswordWithToken(@NonNull ComponentName admin, String password,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RESET_PASSWORD, conditional = true)
+    public boolean resetPasswordWithToken(@Nullable ComponentName admin, String password,
             byte[] token, int flags) {
         throwIfParentInstance("resetPassword");
         if (mService != null) {
             try {
-                return mService.resetPasswordWithToken(admin, password, token, flags);
+                return mService.resetPasswordWithToken(admin, mContext.getPackageName(), password,
+                        token, flags);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -6405,15 +6426,18 @@
      * @param flags Bit mask of additional options: currently supported flags are
      *              {@link #WIPE_EXTERNAL_STORAGE}, {@link #WIPE_RESET_PROTECTION_DATA},
      *              {@link #WIPE_EUICC} and {@link #WIPE_SILENTLY}.
-     * @throws SecurityException     if the calling application does not own an active
-     *                               administrator
-     *                               that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} and is
-     *                               not granted the
-     *                               {@link android.Manifest.permission#MASTER_CLEAR} permission.
+     * @throws SecurityException if the calling application does not own an active
+     *                           administrator
+     *                           that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} and is
+     *                           not granted the
+     *                           {@link android.Manifest.permission#MASTER_CLEAR} or
+     *                           {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIPE_DATA}
+     *                            permissions.
      * @throws IllegalStateException if called on last full-user or system-user
      * @see #wipeDevice(int)
      * @see #wipeData(int, CharSequence)
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIPE_DATA, conditional = true)
     public void wipeData(int flags) {
         wipeDataInternal(flags,
                 /* wipeReasonForUser= */ "",
@@ -6447,13 +6471,15 @@
      *            presented to the user.
      * @throws SecurityException if the calling application does not own an active administrator
      *            that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} and is not granted the
-     *            {@link android.Manifest.permission#MASTER_CLEAR} permission.
+     *            {@link android.Manifest.permission#MASTER_CLEAR} or
+     *            {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIPE_DATA} permissions.
      * @throws IllegalArgumentException if the input reason string is null or empty, or if
      *            {@link #WIPE_SILENTLY} is set.
      * @throws IllegalStateException if called on last full-user or system-user
      * @see #wipeDevice(int)
      * @see #wipeData(int)
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIPE_DATA, conditional = true)
     public void wipeData(int flags, @NonNull CharSequence reason) {
         Objects.requireNonNull(reason, "reason string is null");
         Preconditions.checkStringNotEmpty(reason, "reason string is empty");
@@ -6473,13 +6499,17 @@
      *              {@link #WIPE_EXTERNAL_STORAGE}, {@link #WIPE_RESET_PROTECTION_DATA},
      *              {@link #WIPE_EUICC} and {@link #WIPE_SILENTLY}.
      * @throws SecurityException if the calling application does not own an active administrator
-     *                           that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} and is not
-     *                           granted the {@link android.Manifest.permission#MASTER_CLEAR}
-     *                           permission.
+     *                       that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} and is not
+     *                       granted the {@link android.Manifest.permission#MASTER_CLEAR}
+     *                       or both the
+     *                       {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_WIPE_DATA} and
+     *                       {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS}
+     *                       permissions.
      * @see #wipeData(int)
      * @see #wipeData(int, CharSequence)
      */
     // TODO(b/255323293) Add host-side tests
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_WIPE_DATA, conditional = true)
     public void wipeDevice(int flags) {
         wipeDataInternal(flags,
                 /* wipeReasonForUser= */ "",
@@ -6499,8 +6529,8 @@
             boolean factoryReset) {
         if (mService != null) {
             try {
-                mService.wipeDataWithReason(flags, wipeReasonForUser, mParentInstance,
-                        factoryReset);
+                mService.wipeDataWithReason(mContext.getPackageName(), flags, wipeReasonForUser,
+                        mParentInstance, factoryReset);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -7295,6 +7325,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      * All apps within the profile will be able to access the certificate and use the private key,
      * given direct user approval.
@@ -7317,17 +7349,19 @@
      * revoked.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if calling from a delegated certificate installer.
+     *            {@code null} if the caller is not a device admin.
      * @param privKey The private key to install.
      * @param cert The certificate to install.
      * @param alias The private key alias under which to install the certificate. If a certificate
      * with that alias already exists, it will be overwritten.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
      * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner.
+     *         owner, or {@code admin} is null and the calling application does not have the
+     *         {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @see #setDelegatedScopes
      * @see #DELEGATION_CERT_INSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate cert, @NonNull String alias) {
         return installKeyPair(admin, privKey, new Certificate[] {cert}, alias, false);
@@ -7341,6 +7375,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      * All apps within the profile will be able to access the certificate chain and use the private
      * key, given direct user approval.
@@ -7361,7 +7397,7 @@
      * revoked.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *        {@code null} if calling from a delegated certificate installer.
+     *        {@code null} if the caller is not a device admin.
      * @param privKey The private key to install.
      * @param certs The certificate chain to install. The chain should start with the leaf
      *        certificate and include the chain of trust in order. This will be returned by
@@ -7373,11 +7409,13 @@
      *        approval.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
      * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner.
+     *         owner, or {@code admin} is null and the calling application does not have the
+     *         {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @see android.security.KeyChain#getCertificateChain
      * @see #setDelegatedScopes
      * @see #DELEGATION_CERT_INSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess) {
         int flags = INSTALLKEY_SET_USER_SELECTABLE;
@@ -7395,6 +7433,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      * All apps within the profile will be able to access the certificate chain and use the
      * private key, given direct user approval (if the user is allowed to select the private key).
@@ -7421,7 +7461,7 @@
      * revoked.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *        {@code null} if calling from a delegated certificate installer.
+     *        {@code null} if the caller is not a device admin.
      * @param privKey The private key to install.
      * @param certs The certificate chain to install. The chain should start with the leaf
      *        certificate and include the chain of trust in order. This will be returned by
@@ -7432,13 +7472,15 @@
      *        and set the key to be user-selectable. See {@link #INSTALLKEY_SET_USER_SELECTABLE} and
      *        {@link #INSTALLKEY_REQUEST_CREDENTIALS_ACCESS}.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner, or {@code admin} is null but the calling application is not a delegated
-     *         certificate installer or credential management app.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or
+     *        profile owner, or {@code admin} is null but the calling application is not a
+     *        delegated certificate installer, credential management app and does not have the
+     *        {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @see android.security.KeyChain#getCertificateChain
      * @see #setDelegatedScopes
      * @see #DELEGATION_CERT_INSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate[] certs, @NonNull String alias, int flags) {
         throwIfParentInstance("installKeyPair");
@@ -7474,6 +7516,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      *
      * <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app
@@ -7481,15 +7525,17 @@
      * {@code null}. Note, there can only be a credential management app on an unmanaged device.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *        {@code null} if calling from a delegated certificate installer.
+     *        {@code null} if the caller is not a device admin.
      * @param alias The private key alias under which the certificate is installed.
      * @return {@code true} if the private key alias no longer exists, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner, or {@code admin} is null but the calling application is not a delegated
-     *         certificate installer or credential management app.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+     *        profile owner, or {@code admin} is null but the calling application is not a
+     *        delegated certificate installer, credential management app and does not have the
+     *        {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @see #setDelegatedScopes
      * @see #DELEGATION_CERT_INSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
         throwIfParentInstance("removeKeyPair");
         try {
@@ -7508,6 +7554,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      *
      * If called by the credential management app, the alias must exist in the credential
@@ -7516,10 +7564,12 @@
      * @param alias The alias under which the key pair is installed.
      * @return {@code true} if a key pair with this alias exists, {@code false} otherwise.
      * @throws SecurityException if the caller is not a device or profile owner, a delegated
-     *         certificate installer or the credential management app.
+     *         certificate installer, the credential management app and does not have the
+     *         {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @see #setDelegatedScopes
      * @see #DELEGATION_CERT_INSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean hasKeyPair(@NonNull String alias) {
         throwIfParentInstance("hasKeyPair");
         try {
@@ -7536,6 +7586,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      * If the device supports key generation via secure hardware, this method is useful for
      * creating a key in KeyChain that never left the secure hardware. Access to the key is
@@ -7566,19 +7618,23 @@
      * supports these features, refer to {@link #isDeviceIdAttestationSupported()} and
      * {@link #isUniqueDeviceAttestationSupported()}.
      *
-     * <p>Device owner, profile owner, their delegated certificate installer and the credential
-     * management app can use {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device
-     * information including manufacturer, model, brand, device and product in the attestation
-     * record.
-     * Only device owner, profile owner on an organization-owned device or affiliated user, and
-     * their delegated certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI}
-     * and {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial
-     * number, IMEI and MEID correspondingly), if supported by the device
-     * (see {@link #isDeviceIdAttestationSupported()}).
-     * Additionally, device owner, profile owner on an organization-owned device and their delegated
-     * certificate installers can also request the attestation record to be signed using an
-     * individual attestation certificate by specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION}
-     * flag (if supported by the device, see {@link #isUniqueDeviceAttestationSupported()}).
+     * <p>Device owner, profile owner, their delegated certificate installer, the credential
+     * management app or an app that holds the
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can use
+     * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information including
+     * manufacturer, model, brand, device and product in the attestation record.
+     * Only device owner, profile owner on an organization-owned device or affiliated user, their
+     * delegated certificate installers or an app that holds the
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can use
+     * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request unique
+     * device identifiers to be attested (the serial number, IMEI and MEID correspondingly),
+     * if supported by the device (see {@link #isDeviceIdAttestationSupported()}).
+     * Additionally, device owner, profile owner on an organization-owned device, their delegated
+     * certificate installers and an app that holds the
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission can also
+     * request the attestation record to be signed using an individual attestation certificate by
+     * specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} flag (if supported by the device,
+     * see {@link #isUniqueDeviceAttestationSupported()}).
      * <p>
      * If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID}
      * is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set.
@@ -7587,7 +7643,7 @@
      * key generation is done in StrongBox.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if calling from a delegated certificate installer.
+     *            {@code null} if the caller is not a device admin.
      * @param algorithm The key generation algorithm, see {@link java.security.KeyPairGenerator}.
      * @param keySpec Specification of the key to generate, see
      * {@link java.security.KeyPairGenerator}.
@@ -7603,12 +7659,14 @@
      *        If any flag is specified, then an attestation challenge must be included in the
      *        {@code keySpec}.
      * @return A non-null {@code AttestedKeyPair} if the key generation succeeded, null otherwise.
-     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner, or {@code admin} is null but the calling application is not a delegated
-     *         certificate installer or credential management app. If Device ID attestation is
-     *         requested (using {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} or
-     *         {@link #ID_TYPE_MEID}), the caller must be the Device Owner or the Certificate
-     *         Installer delegate.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+     *         profile owner, or {@code admin} is null but the calling application is not a
+     *         delegated certificate installer, credential management app and does not have the
+     *         {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
+     *         If Device ID attestation is requested (using {@link #ID_TYPE_SERIAL},
+     *         {@link #ID_TYPE_IMEI} or {@link #ID_TYPE_MEID}), the caller must be the Device Owner,
+     *         the Certificate Installer delegate or have the
+     *         {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      * @throws IllegalArgumentException in the following cases:
      *         <p>
      *         <ul>
@@ -7624,6 +7682,7 @@
      *         specified in {@code keySpec} but the device does not have one.
      * @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin,
             @NonNull String algorithm, @NonNull KeyGenParameterSpec keySpec,
             @AttestationIdType int idAttestationFlags) {
@@ -7890,6 +7949,8 @@
      *    <li>Profile owner</li>
      *    <li>Delegated certificate installer</li>
      *    <li>Credential management app</li>
+     *    <li>An app that holds the
+     *    {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission</li>
      * </ul>
      *
      * <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app
@@ -7897,7 +7958,7 @@
      * {@code null}. Note, there can only be a credential management app on an unmanaged device.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if calling from a delegated certificate installer.
+     *            {@code null} if the caller is not a device admin.
      * @param alias The private key alias under which to install the certificate. The {@code alias}
      *        should denote an existing private key. If a certificate with that alias already
      *        exists, it will be overwritten.
@@ -7910,10 +7971,12 @@
      *        {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias}.
      * @return {@code true} if the provided {@code alias} exists and the certificates has been
      *        successfully associated with it, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
-     *         owner, or {@code admin} is null but the calling application is not a delegated
-     *         certificate installer or credential management app.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device owner or
+     *        profile owner, or {@code admin} is null but the calling application is not a
+     *        delegated certificate installer, credential management app and does not have the
+     *        {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CERTIFICATES, conditional = true)
     public boolean setKeyPairCertificate(@Nullable ComponentName admin,
             @NonNull String alias, @NonNull List<Certificate> certs, boolean isUserSelectable) {
         throwIfParentInstance("setKeyPairCertificate");
@@ -7934,7 +7997,6 @@
         return false;
     }
 
-
     /**
      * @return the alias of a given CA certificate in the certificate store, or {@code null} if it
      * doesn't exist.
@@ -8300,14 +8362,15 @@
      * <p>
      * This method can be called on the {@link DevicePolicyManager} instance,
      * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
-     * the profile owner of an organization-owned managed profile.
+     * the profile owner of an organization-owned managed profile
      * <p>
      * If the caller is device owner, then the restriction will be applied to all users. If
      * called on the parent instance, then the restriction will be applied on the personal profile.
      * <p>
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has
-     * not, a security exception will be thrown.
+     * not, a security exception will be thrown, or the caller must hold the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CAMERA}.
      * <p>
      * <b>Note</b>, this policy type is deprecated for legacy device admins since
      * {@link android.os.Build.VERSION_CODES#Q}. On Android
@@ -8323,7 +8386,8 @@
                      the caller is not a device admin
      * @param disabled Whether or not the camera should be disabled.
      * @throws SecurityException if {@code admin} is not an active administrator or does not use
-     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
+     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} and the caller does not hold
+     *             the permisisons {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CAMERA}.
      */
     @RequiresPermission(value = MANAGE_DEVICE_POLICY_CAMERA, conditional = true)
     public void setCameraDisabled(@Nullable ComponentName admin, boolean disabled) {
@@ -8343,11 +8407,14 @@
      * <p>
      * This method can be called on the {@link DevicePolicyManager} instance,
      * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
-     * the profile owner of an organization-owned managed profile.
+     * the profile owner of an organization-owned managed profile or the caller has been granted
+     * the permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CAMERA} and the
+     * cross-user permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS}.
      *
-     * @param admin The name of the admin component to check, or {@code null} to check whether any admins
-     * have disabled the camera
+     * @param admin The name of the admin component to check, or {@code null} to check whether any
+     *              admins have disabled the camera
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CAMERA, conditional = true)
     public boolean getCameraDisabled(@Nullable ComponentName admin) {
         return getCameraDisabled(admin, myUserId());
     }
@@ -8357,7 +8424,8 @@
     public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
         if (mService != null) {
             try {
-                return mService.getCameraDisabled(admin, userHandle, mParentInstance);
+                return mService.getCameraDisabled(admin, mContext.getPackageName(), userHandle,
+                        mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8616,17 +8684,18 @@
      * no user will be able set the date and time. Instead, the network date
      * and time will be used.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param enabled Whether time should be obtained automatically from the network or not.
      * @throws SecurityException if caller is not a device owner, a profile owner for the
      * primary user, or a profile owner of an organization-owned managed profile or a holder of the
      * permission {@link android.Manifest.permission#SET_TIME}.
      */
     @RequiresPermission(value = SET_TIME, conditional = true)
-    public void setAutoTimeEnabled(@NonNull ComponentName admin, boolean enabled) {
+    public void setAutoTimeEnabled(@Nullable ComponentName admin, boolean enabled) {
         if (mService != null) {
             try {
-                mService.setAutoTimeEnabled(admin, enabled);
+                mService.setAutoTimeEnabled(admin, mContext.getPackageName(), enabled);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8640,16 +8709,18 @@
      * are also able to call this method if they hold the permission
      *{@link android.Manifest.permission#SET_TIME}.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return true if auto time is enabled on the device.
      * @throws SecurityException if the caller is not a device owner, a profile
      * owner for the primary user, or a profile owner of an organization-owned managed profile or a
      * holder of the permission {@link android.Manifest.permission#SET_TIME}.
      */
     @RequiresPermission(anyOf = {SET_TIME, QUERY_ADMIN_POLICY}, conditional = true)
-    public boolean getAutoTimeEnabled(@NonNull ComponentName admin) {
+    public boolean getAutoTimeEnabled(@Nullable ComponentName admin) {
         if (mService != null) {
             try {
-                return mService.getAutoTimeEnabled(admin);
+                return mService.getAutoTimeEnabled(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8669,7 +8740,8 @@
      * no user will be able set the date and time zone. Instead, the network date
      * and time zone will be used.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or Null if the
+     *              caller is not a device admin.
      * @param enabled Whether time zone should be obtained automatically from the network or not.
      * @throws SecurityException if caller is not a device owner, a profile owner for the
      * primary user, or a profile owner of an organization-owned managed profile or a holder of the
@@ -8677,11 +8749,11 @@
      */
     @SupportsCoexistence
     @RequiresPermission(value = SET_TIME_ZONE, conditional = true)
-    public void setAutoTimeZoneEnabled(@NonNull ComponentName admin, boolean enabled) {
+    public void setAutoTimeZoneEnabled(@Nullable ComponentName admin, boolean enabled) {
         throwIfParentInstance("setAutoTimeZone");
         if (mService != null) {
             try {
-                mService.setAutoTimeZoneEnabled(admin, enabled);
+                mService.setAutoTimeZoneEnabled(admin, mContext.getPackageName(), enabled);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -8695,17 +8767,19 @@
      * are also able to call this method if they hold the permission
      *{@link android.Manifest.permission#SET_TIME}.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return true if auto time zone is enabled on the device.
      * @throws SecurityException if the caller is not a device owner, a profile
      * owner for the primary user, or a profile owner of an organization-owned managed profile or a
      * holder of the permission {@link android.Manifest.permission#SET_TIME_ZONE}.
      */
     @RequiresPermission(anyOf = {SET_TIME_ZONE, QUERY_ADMIN_POLICY}, conditional = true)
-    public boolean getAutoTimeZoneEnabled(@NonNull ComponentName admin) {
+    public boolean getAutoTimeZoneEnabled(@Nullable ComponentName admin) {
         throwIfParentInstance("getAutoTimeZone");
         if (mService != null) {
             try {
-                return mService.getAutoTimeZoneEnabled(admin);
+                return mService.getAutoTimeZoneEnabled(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -9426,9 +9500,12 @@
     }
 
     /**
-     * Called by device or profile owners to suspend packages for this user. This function can be
-     * called by a device owner, profile owner, or by a delegate given the
-     * {@link #DELEGATION_PACKAGE_ACCESS} scope via {@link #setDelegatedScopes}.
+     * Called by device or profile owners or holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE}.
+     * to suspend packages for this user. This function can be
+     * called by a device owner, profile owner, by a delegate given the
+     * {@link #DELEGATION_PACKAGE_ACCESS} scope via {@link #setDelegatedScopes} or by holders of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE}.
      * <p>
      * A suspended package will not be able to start activities. Its notifications will be hidden,
      * it will not show up in recents, will not be able to show toasts or dialogs or ring the
@@ -9442,18 +9519,22 @@
      * package installer, the required package uninstaller, the required package verifier, the
      * default dialer, and the permission controller.
      *
-     * @param admin The name of the admin component to check, or {@code null} if the caller is a
-     *            package access delegate.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageNames The package names to suspend or unsuspend.
      * @param suspended If set to {@code true} than the packages will be suspended, if set to
      *            {@code false} the packages will be unsuspended.
      * @return an array of package names for which the suspended status is not set as requested in
      *         this method.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or has not been
+     * granted the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE}.
      * @see #setDelegatedScopes
      * @see #DELEGATION_PACKAGE_ACCESS
      */
-    public @NonNull String[] setPackagesSuspended(@NonNull ComponentName admin,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true)
+    @NonNull
+    public String[] setPackagesSuspended(@Nullable ComponentName admin,
             @NonNull String[] packageNames, boolean suspended) {
         throwIfParentInstance("setPackagesSuspended");
         if (mService != null) {
@@ -9470,19 +9551,23 @@
     /**
      * Determine if a package is suspended. This function can be called by a device owner, profile
      * owner, or by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via
-     * {@link #setDelegatedScopes}.
+     * {@link #setDelegatedScopes} or by holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE}.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *            {@code null} if the caller is a package access delegate.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageName The name of the package to retrieve the suspended status of.
      * @return {@code true} if the package is suspended or {@code false} if the package is not
      *         suspended, could not be found or an error occurred.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or has not been
+     * granted the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PACKAGE_STATE}.
      * @throws NameNotFoundException if the package could not be found.
      * @see #setDelegatedScopes
      * @see #DELEGATION_PACKAGE_ACCESS
      */
-    public boolean isPackageSuspended(@NonNull ComponentName admin, String packageName)
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true)
+    public boolean isPackageSuspended(@Nullable ComponentName admin, String packageName)
             throws NameNotFoundException {
         throwIfParentInstance("isPackageSuspended");
         if (mService != null) {
@@ -9728,10 +9813,11 @@
     }
 
     /**
-     * Called by a profile owner or device owner to set a default activity that the system selects
-     * to handle intents that match the given {@link IntentFilter}. This activity will remain the
-     * default intent handler even if the set of potential event handlers for the intent filter
-     * changes and if the intent preferences are reset.
+     * Called by a profile owner or device owner or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}. to set a default activity
+     * that the system selects to handle intents that match the given {@link IntentFilter}.
+     * This activity will remain the default intent handler even if the set of potential event
+     * handlers for the intent filter changes and if the intent preferences are reset.
      * <p>
      * Note that the caller should still declare the activity in the manifest, the API just sets
      * the activity to be the default one to handle the given intent filter.
@@ -9745,18 +9831,22 @@
      *
      * <p>NOTE: Performs disk I/O and shouldn't be called on the main thread.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *        caller is not a device admin.
      * @param filter The IntentFilter for which a default handler is added.
      * @param activity The Activity that is added as default intent handler.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
     @SupportsCoexistence
-    public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
+    public void addPersistentPreferredActivity(@Nullable ComponentName admin, IntentFilter filter,
             @NonNull ComponentName activity) {
         throwIfParentInstance("addPersistentPreferredActivity");
         if (mService != null) {
             try {
-                mService.addPersistentPreferredActivity(admin, filter, activity);
+                mService.addPersistentPreferredActivity(admin, mContext.getPackageName(), filter,
+                        activity);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -9764,22 +9854,30 @@
     }
 
     /**
-     * Called by a profile owner or device owner to remove all persistent intent handler preferences
-     * associated with the given package that were set by {@link #addPersistentPreferredActivity}.
+     * Called by a profile owner or device owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK} to remove all
+     * persistent intent handler preferences associated with the given package that were set by
+     * {@link #addPersistentPreferredActivity}.
      * <p>
      * The calling device admin must be a profile owner. If it is not, a security exception will be
      * thrown.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageName The name of the package for which preferences are removed.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      */
-    public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
+    public void clearPackagePersistentPreferredActivities(@Nullable ComponentName admin,
             String packageName) {
         throwIfParentInstance("clearPackagePersistentPreferredActivities");
         if (mService != null) {
             try {
-                mService.clearPackagePersistentPreferredActivities(admin, packageName);
+                mService.clearPackagePersistentPreferredActivities(
+                        admin,
+                        mContext.getPackageName(),
+                        packageName);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -9788,27 +9886,69 @@
 
     /**
      * Must be called by a device owner or a profile owner of an organization-owned managed profile
-     * to set the default SMS application.
+     * or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_DEFAULT_SMS} to set the default SMS
+     * application.
      * <p>
      * This method can be called on the {@link DevicePolicyManager} instance, returned by
      * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner
      * of an organization-owned managed profile and the package must be a pre-installed system
      * package. If called on the parent instance, then the default SMS application is set on the
      * personal profile.
+     * <p>
+     * Starting from Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, the profile
+     * owner of an organization-owned managed profile can also call this method directly (not on the
+     * parent profile instance) to set the default SMS application in the work profile. This is only
+     * meaningful when work profile telephony is enabled by {@link #setManagedSubscriptionsPolicy}.
      *
-     * @param admin       Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageName The name of the package to set as the default SMS application.
-     * @throws SecurityException        if {@code admin} is not a device or profile owner or if
-     *                                  called on the parent profile and the {@code admin} is not a
-     *                                  profile owner of an organization-owned managed profile.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or if
+     *                        called on the parent profile and the {@code admin} is not a
+     *                        profile owner of an organization-owned managed profile and
+     *                        if the caller has not been granted the permission
+     *                        {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_DEFAULT_SMS}.
      * @throws IllegalArgumentException if called on the parent profile and the package
      *                                  provided is not a pre-installed system package.
      */
-    public void setDefaultSmsApplication(@NonNull ComponentName admin,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_DEFAULT_SMS, conditional = true)
+    public void setDefaultSmsApplication(@Nullable ComponentName admin,
             @NonNull String packageName) {
         if (mService != null) {
             try {
-                mService.setDefaultSmsApplication(admin, packageName, mParentInstance);
+                mService.setDefaultSmsApplication(admin, mContext.getPackageName(), packageName,
+                        mParentInstance);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Must be called by a device owner or a profile owner of an organization-owned managed profile
+     * to set the default dialer application for the calling user.
+     * <p>
+     * When the profile owner of an organization-owned managed profile calls this method, it sets
+     * the default dialer application in the work profile. This is only meaningful when work profile
+     * telephony is enabled by {@link #setManagedSubscriptionsPolicy}.
+     * <p>
+     * If the device does not support telephony ({@link PackageManager#FEATURE_TELEPHONY}), calling
+     * this method will do nothing.
+     *
+     * @param packageName The name of the package to set as the default dialer application.
+     * @throws SecurityException        if {@code admin} is not a device or profile owner or a
+     *                                  profile owner of an organization-owned managed profile.
+     * @throws IllegalArgumentException if the package cannot be set as the default dialer, for
+     *                                  example if the package is not installed or does not expose
+     *                                  the expected activities or services that a dialer app is
+     *                                  required to have.
+     */
+    public void setDefaultDialerApplication(@NonNull String packageName) {
+        throwIfParentInstance("setDefaultDialerApplication");
+        if (mService != null) {
+            try {
+                mService.setDefaultDialerApplication(packageName);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -9927,6 +10067,11 @@
      * owner, and the application restrictions managing package via
      * {@link #getApplicationRestrictions}.
      *
+     * <p>Starting from Android Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * multiple admins can set app restrictions for the same application, the target application can
+     * get the list of app restrictions set by each admin via
+     * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin}.
+     *
      * <p>NOTE: The method performs disk I/O and shouldn't be called on the main thread
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
@@ -10522,22 +10667,29 @@
     }
 
     /**
-     * Called by the profile owner of a managed profile so that some intents sent in the managed
-     * profile can also be resolved in the parent, or vice versa. Only activity intents are
-     * supported.
+     * Called by the profile owner of a managed profile or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}. so that some
+     * intents sent in the managed profile can also be resolved in the parent, or vice versa.
+     * Only activity intents are supported.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param filter The {@link IntentFilter} the intent has to match to be also resolved in the
      *            other profile
      * @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and
      *            {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner and is not a
+     * holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}.
      */
-    public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional = true)
+    public void addCrossProfileIntentFilter(@Nullable ComponentName admin, IntentFilter filter,
+            int flags) {
         throwIfParentInstance("addCrossProfileIntentFilter");
         if (mService != null) {
             try {
-                mService.addCrossProfileIntentFilter(admin, filter, flags);
+                mService.addCrossProfileIntentFilter(admin, mContext.getPackageName(), filter,
+                        flags);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -10545,9 +10697,10 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to remove the cross-profile intent filters
-     * that go from the managed profile to the parent, or from the parent to the managed profile.
-     * Only removes those that have been set by the profile owner.
+     * Called by a profile owner of a managed profile or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION} to remove the
+     * cross-profile intent filters that go from the managed profile to the parent, or from the
+     * parent to the managed profile. Only removes those that have been set by the profile owner.
      * <p>
      * <em>Note</em>: A list of default cross profile intent filters are set up by the system when
      * the profile is created, some of them ensure the proper functioning of the profile, while
@@ -10556,14 +10709,18 @@
      * profile data sharing is not desired, they can be disabled with
      * {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE}.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
+     * @throws SecurityException if {@code admin} is not a profile owner and is not a
+     * holder of the permission
+     * @link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}.
      */
-    public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional = true)
+    public void clearCrossProfileIntentFilters(@Nullable ComponentName admin) {
         throwIfParentInstance("clearCrossProfileIntentFilters");
         if (mService != null) {
             try {
-                mService.clearCrossProfileIntentFilters(admin);
+                mService.clearCrossProfileIntentFilters(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11352,9 +11509,11 @@
     }
 
     /**
-     * Called by a profile or device owner to set a user restriction specified by the key.
+     * Called by a profile owner, device owner or a holder of any permission that is associated with
+     * a user restriction to set a user restriction specified by the key.
      * <p>
-     * The calling device admin must be a profile or device owner; if it is not, a security
+     * The calling device admin must be a profile owner, device owner or holder of any permission
+     * that is associated with a user restriction; if it is not, a security
      * exception will be thrown.
      * <p>
      * The profile owner of an organization-owned managed profile may invoke this method on
@@ -11362,7 +11521,8 @@
      * {@link #getParentProfileInstance(ComponentName)}, for enforcing device-wide restrictions.
      * <p>
      * See the constants in {@link android.os.UserManager} for the list of restrictions that can
-     * be enforced device-wide.
+     * be enforced device-wide. These constants will also state in their documentation which
+     * permission is required to manage the restriction using this API.
      *
      * <p>For callers targeting Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or
      * above, calling this API will result in applying the restriction locally on the calling user,
@@ -11373,7 +11533,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param key   The key of the restriction.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner and if the caller
+     * has not been granted the permission to set the given user restriction.
      */
     public void addUserRestriction(@NonNull ComponentName admin,
             @UserManager.UserRestrictionKey String key) {
@@ -11388,21 +11549,24 @@
     }
 
     /**
-     * Called by a profile or device owner to set a user restriction specified by the provided
-     * {@code key} globally on all users. To clear the restriction use
-     * {@link #clearUserRestriction}.
+     * Called by a profile owner, device owner or a holder of any permission that is associated with
+     *  a user restriction to set a user restriction specified by the provided {@code key} globally
+     *  on all users. To clear the restriction use {@link #clearUserRestriction}.
      *
      * <p>For a given user, a restriction will be set if it was applied globally or locally by any
      * admin.
      *
-     * <p> The calling device admin must be a profile or device owner; if it is not, a security
+     * <p> The calling device admin must be a profile owner, device owner or or a holder of any
+     * permission that is associated with a user restriction; if it is not, a security
      * exception will be thrown.
      *
      * <p> See the constants in {@link android.os.UserManager} for the list of restrictions that can
-     * be enforced device-wide.
+     * be enforced device-wide. These constants will also state in their documentation which
+     * permission is required to manage the restriction using this API.
      *
      * @param key The key of the restriction.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner and if the
+     * caller has not been granted the permission to set the given user restriction.
      * @throws IllegalStateException if caller is not targeting Android
      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or above.
      */
@@ -11418,7 +11582,8 @@
     }
 
     /**
-     * Called by a profile or device owner to clear a user restriction specified by the key.
+     * Called by a profile owner, device owner or a holder of any permission that is associated with
+     * a user restriction to clear a user restriction specified by the key.
      * <p>
      * The calling device admin must be a profile or device owner; if it is not, a security
      * exception will be thrown.
@@ -11427,7 +11592,9 @@
      * the {@link DevicePolicyManager} instance it obtained from
      * {@link #getParentProfileInstance(ComponentName)}, for clearing device-wide restrictions.
      * <p>
-     * See the constants in {@link android.os.UserManager} for the list of restrictions.
+     * See the constants in {@link android.os.UserManager} for the list of restrictions. These
+     * constants state in their documentation which permission is required to manage the restriction
+     * using this API.
      *
      * <p>For callers targeting Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or
      * above, calling this API will result in clearing any local and global restriction with the
@@ -11435,7 +11602,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param key   The key of the restriction.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner  and if the
+     *  caller has not been granted the permission to set the given user restriction.
      */
     public void clearUserRestriction(@NonNull ComponentName admin,
             @UserManager.UserRestrictionKey String key) {
@@ -11450,11 +11618,11 @@
     }
 
     /**
-     * Called by a profile or device owner to get user restrictions set with
+     * Called by an admin to get user restrictions set by themselves with
      * {@link #addUserRestriction(ComponentName, String)}.
      * <p>
-     * The target user may have more restrictions set by the system or other device owner / profile
-     * owner. To get all the user restrictions currently set, use
+     * The target user may have more restrictions set by the system or other admin.
+     * To get all the user restrictions currently set, use
      * {@link UserManager#getUserRestrictions()}.
      * <p>
      * The profile owner of an organization-owned managed profile may invoke this method on
@@ -11728,8 +11896,9 @@
     }
 
     /**
-     * Called by a device owner or profile owner to disable account management for a specific type
-     * of account.
+     * Called by a device owner, profile owner or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT}
+     * to disable account management for a specific type of account.
      * <p>
      * The calling device admin must be a device owner or profile owner. If it is not, a security
      * exception will be thrown.
@@ -11746,18 +11915,22 @@
      * organization-owned device, to restrict accounts that may not be managed on the primary
      * profile.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param accountType For which account management is disabled or enabled.
      * @param disabled The boolean indicating that account management will be disabled (true) or
      *            enabled (false).
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or has not been
+     * granted the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT}.
      */
-    public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, conditional = true)
+    public void setAccountManagementDisabled(@Nullable ComponentName admin, String accountType,
             boolean disabled) {
         if (mService != null) {
             try {
-                mService.setAccountManagementDisabled(admin, accountType, disabled,
-                        mParentInstance);
+                mService.setAccountManagementDisabled(admin, mContext.getPackageName(), accountType,
+                        disabled, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11787,8 +11960,13 @@
      * @see #getAccountTypesWithManagementDisabled()
      * Note that calling this method on the parent profile instance will return the same
      * value as calling it on the main {@code DevicePolicyManager} instance.
+     *
+     * @throws SecurityException if the userId is different to the caller's and the caller has not
+     * been granted {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT} and
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS}.
      * @hide
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, conditional = true)
     public @Nullable String[] getAccountTypesWithManagementDisabledAsUser(int userId) {
         return getAccountTypesWithManagementDisabledAsUser(userId, false);
     }
@@ -11801,7 +11979,8 @@
             int userId, boolean parentInstance) {
         if (mService != null) {
             try {
-                return mService.getAccountTypesWithManagementDisabledAsUser(userId, parentInstance);
+                return mService.getAccountTypesWithManagementDisabledAsUser(userId,
+                        mContext.getPackageName(), parentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11869,26 +12048,31 @@
      * package list results in locked tasks belonging to those packages to be finished.
      * <p>
      * This function can only be called by the device owner, a profile owner of an affiliated user
-     * or profile, or the profile owner when no device owner is set. See {@link #isAffiliatedUser}.
+     * or profile, or the profile owner when no device owner is set or holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}. See
+     * {@link #isAffiliatedUser}.
      * Any package set via this method will be cleared if the user becomes unaffiliated.
      *
      * @param packages The list of packages allowed to enter lock task mode
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @throws SecurityException if {@code admin} is not the device owner, the profile owner of an
-     * affiliated user or profile, or the profile owner when no device owner is set.
+     * affiliated user or profile, or the profile owner when no device owner is set or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      * @see #isAffiliatedUser
      * @see Activity#startLockTask()
      * @see DeviceAdminReceiver#onLockTaskModeEntering(Context, Intent, String)
      * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
      * @see UserManager#DISALLOW_CREATE_WINDOWS
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
     @SupportsCoexistence
-    public void setLockTaskPackages(@NonNull ComponentName admin, @NonNull String[] packages)
+    public void setLockTaskPackages(@Nullable ComponentName admin, @NonNull String[] packages)
             throws SecurityException {
         throwIfParentInstance("setLockTaskPackages");
         if (mService != null) {
             try {
-                mService.setLockTaskPackages(admin, packages);
+                mService.setLockTaskPackages(admin, mContext.getPackageName(),  packages);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11898,16 +12082,20 @@
     /**
      * Returns the list of packages allowed to start the lock task mode.
      *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @throws SecurityException if {@code admin} is not the device owner, the profile owner of an
-     * affiliated user or profile, or the profile owner when no device owner is set.
+     * affiliated user or profile, or the profile owner when no device owner is set or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      * @see #isAffiliatedUser
      * @see #setLockTaskPackages
      */
-    public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
+    public @NonNull String[] getLockTaskPackages(@Nullable ComponentName admin) {
         throwIfParentInstance("getLockTaskPackages");
         if (mService != null) {
             try {
-                return mService.getLockTaskPackages(admin);
+                return mService.getLockTaskPackages(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11941,22 +12129,26 @@
      * {@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}.
      *
      * <p>This method can only be called by the device owner, a profile owner of an affiliated
-     * user or profile, or the profile owner when no device owner is set. See
+     * user or profile, or the profile owner when no device owner is set or holders of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}. See
      * {@link #isAffiliatedUser}.
      * Any features set using this method are cleared if the user becomes unaffiliated.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param flags The system features enabled during lock task mode.
      * @throws SecurityException if {@code admin} is not the device owner, the profile owner of an
-     * affiliated user or profile, or the profile owner when no device owner is set.
+     * affiliated user or profile, or the profile owner when no device owner is set or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      * @see #isAffiliatedUser
      **/
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
     @SupportsCoexistence
-    public void setLockTaskFeatures(@NonNull ComponentName admin, @LockTaskFeature int flags) {
+    public void setLockTaskFeatures(@Nullable ComponentName admin, @LockTaskFeature int flags) {
         throwIfParentInstance("setLockTaskFeatures");
         if (mService != null) {
             try {
-                mService.setLockTaskFeatures(admin, flags);
+                mService.setLockTaskFeatures(admin, mContext.getPackageName(), flags);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -11966,18 +12158,21 @@
     /**
      * Gets which system features are enabled for LockTask mode.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @return bitfield of flags. See {@link #setLockTaskFeatures(ComponentName, int)} for a list.
      * @throws SecurityException if {@code admin} is not the device owner, the profile owner of an
-     * affiliated user or profile, or the profile owner when no device owner is set.
+     * affiliated user or profile, or the profile owner when no device owner is set or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
      * @see #isAffiliatedUser
      * @see #setLockTaskFeatures
      */
-    public @LockTaskFeature int getLockTaskFeatures(@NonNull ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
+    public @LockTaskFeature int getLockTaskFeatures(@Nullable ComponentName admin) {
         throwIfParentInstance("getLockTaskFeatures");
         if (mService != null) {
             try {
-                return mService.getLockTaskFeatures(admin);
+                return mService.getLockTaskFeatures(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -12259,7 +12454,8 @@
      * {@link android.provider.Settings.Global#AUTO_TIME} is 0, otherwise {@code false} will be
      * returned.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param millis time in milliseconds since the Epoch
      * @return {@code true} if set time succeeded, {@code false} otherwise.
      * @throws SecurityException if {@code admin} is not a device owner or a profile owner
@@ -12267,11 +12463,11 @@
      * {@link android.Manifest.permission#SET_TIME}.
      */
     @RequiresPermission(value = SET_TIME, conditional = true)
-    public boolean setTime(@NonNull ComponentName admin, long millis) {
+    public boolean setTime(@Nullable ComponentName admin, long millis) {
         throwIfParentInstance("setTime");
         if (mService != null) {
             try {
-                return mService.setTime(admin, millis);
+                return mService.setTime(admin, mContext.getPackageName(), millis);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -12288,7 +12484,8 @@
      * returned.
      *
      * @see android.app.AlarmManager#setTimeZone(String)
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param timeZone one of the Olson ids from the list returned by
      *     {@link java.util.TimeZone#getAvailableIDs}
      * @return {@code true} if set timezone succeeded, {@code false} otherwise.
@@ -12297,11 +12494,11 @@
      * {@link android.Manifest.permission#SET_TIME_ZONE}.
      */
     @RequiresPermission(value = SET_TIME_ZONE, conditional = true)
-    public boolean setTimeZone(@NonNull ComponentName admin, String timeZone) {
+    public boolean setTimeZone(@Nullable ComponentName admin, String timeZone) {
         throwIfParentInstance("setTimeZone");
         if (mService != null) {
             try {
-                return mService.setTimeZone(admin, timeZone);
+                return mService.setTimeZone(admin, mContext.getPackageName(), timeZone);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -12452,16 +12649,19 @@
     /**
      * Change whether a user can uninstall a package. This function can be called by a device owner,
      * profile owner, or by a delegate given the {@link #DELEGATION_BLOCK_UNINSTALL} scope via
-     * {@link #setDelegatedScopes}.
+     * {@link #setDelegatedScopes} or holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL}.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     *             {@code null} if the caller is a block uninstall delegate.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param packageName package to change.
      * @param uninstallBlocked true if the user shouldn't be able to uninstall the package.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL}.
      * @see #setDelegatedScopes
      * @see #DELEGATION_BLOCK_UNINSTALL
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional = true)
     @SupportsCoexistence
     public void setUninstallBlocked(@Nullable ComponentName admin, String packageName,
             boolean uninstallBlocked) {
@@ -12490,17 +12690,21 @@
      * <a href="/training/basics/intents/package-visibility">manage package visibility</a>.
      *
      * @param admin The name of the admin component whose blocking policy will be checked, or
-     *            {@code null} to check whether any admin has blocked the uninstallation.
+     *            {@code null} to check whether any admin has blocked the uninstallation. Starting
+     *              from {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} admin will be
+     *              ignored and assumed {@code null}.
      * @param packageName package to check.
      * @return true if uninstallation is blocked and the given package is visible to you, false
      *         otherwise if uninstallation isn't blocked or the given package isn't visible to you.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner. Starting
+     *  from {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} there will not be a security
+     *  check at all.
      */
     public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
         throwIfParentInstance("isUninstallBlocked");
         if (mService != null) {
             try {
-                return mService.isUninstallBlocked(admin, packageName);
+                return mService.isUninstallBlocked(packageName);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -12509,26 +12713,33 @@
     }
 
     /**
-     * Called by the profile owner of a managed profile to enable widget providers from a given
-     * package to be available in the parent profile. As a result the user will be able to add
-     * widgets from the allowlisted package running under the profile to a widget host which runs
-     * under the parent profile, for example the home screen. Note that a package may have zero or
-     * more provider components, where each component provides a different widget type.
+     * Called by the profile owner of a managed profile or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION} to enable
+     * widget providers from a given package to be available in the parent profile. As a result the
+     * user will be able to add widgets from the allowlisted package running under the profile to a
+     * widget host which runs under the parent profile, for example the home screen. Note that a
+     * package may have zero or more provider components, where each component provides a different
+     * widget type.
      * <p>
      * <strong>Note:</strong> By default no widget provider package is allowlisted.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageName The package from which widget providers are allowlisted.
      * @return Whether the package was added.
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * @throws SecurityException if {@code admin} is not a profile owner and not a holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}.
      * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
-    public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional = true)
+    public boolean addCrossProfileWidgetProvider(@Nullable ComponentName admin,
+            String packageName) {
         throwIfParentInstance("addCrossProfileWidgetProvider");
         if (mService != null) {
             try {
-                return mService.addCrossProfileWidgetProvider(admin, packageName);
+                return mService.addCrossProfileWidgetProvider(admin,
+                        mContext.getPackageName(), packageName);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -12537,26 +12748,31 @@
     }
 
     /**
-     * Called by the profile owner of a managed profile to disable widget providers from a given
-     * package to be available in the parent profile. For this method to take effect the package
-     * should have been added via
+     * Called by the profile owner of a managed profile or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION} to disable
+     * widget providers from a given package to be available in the parent profile. For this method
+     * to take effect the package should have been added via
      * {@link #addCrossProfileWidgetProvider( android.content.ComponentName, String)}.
      * <p>
      * <strong>Note:</strong> By default no widget provider package is allowlisted.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param packageName The package from which widget providers are no longer allowlisted.
      * @return Whether the package was removed.
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * @throws SecurityException if {@code admin} is not a profile owner and not a holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}.
      * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
-    public boolean removeCrossProfileWidgetProvider(
-            @NonNull ComponentName admin, String packageName) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional = true)
+    public boolean removeCrossProfileWidgetProvider(@Nullable ComponentName admin,
+            String packageName) {
         throwIfParentInstance("removeCrossProfileWidgetProvider");
         if (mService != null) {
             try {
-                return mService.removeCrossProfileWidgetProvider(admin, packageName);
+                return mService.removeCrossProfileWidgetProvider(admin, mContext.getPackageName(),
+                        packageName);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -12565,20 +12781,25 @@
     }
 
     /**
-     * Called by the profile owner of a managed profile to query providers from which packages are
-     * available in the parent profile.
+     * Called by the profile owner of a managed profile or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION} to query
+     * providers from which packages are available in the parent profile.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return The allowlisted package list.
      * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * @throws SecurityException if {@code admin} is not a profile owner and not a holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_PROFILE_INTERACTION}.
      */
-    public @NonNull List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_PROFILE_INTERACTION, conditional = true)
+    public @NonNull List<String> getCrossProfileWidgetProviders(@Nullable ComponentName admin) {
         throwIfParentInstance("getCrossProfileWidgetProviders");
         if (mService != null) {
             try {
-                List<String> providers = mService.getCrossProfileWidgetProviders(admin);
+                List<String> providers = mService.getCrossProfileWidgetProviders(admin,
+                        mContext.getPackageName());
                 if (providers != null) {
                     return providers;
                 }
@@ -12714,9 +12935,10 @@
     }
 
     /**
-     * Called by device owner or profile owner of secondary users that is affiliated with the
-     * device to disable the status bar. Disabling the status bar blocks notifications and quick
-     * settings.
+     * Called by device owner, profile owner of secondary users that is affiliated with the
+     * device or a holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_STATUS_BAR} to disable the status
+     * bar. Disabling the status bar blocks notifications and quick settings.
      * <p>
      * <strong>Note:</strong> This method has no effect for LockTask mode. The behavior of the
      * status bar in LockTask mode can be configured with
@@ -12727,18 +12949,21 @@
      * <p>This policy does not have any effect while on the lock screen, where the status bar will
      * not be disabled. Using LockTask instead of this method is recommended.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param disabled {@code true} disables the status bar, {@code false} reenables it.
      * @return {@code false} if attempting to disable the status bar failed. {@code true} otherwise.
-     * @throws SecurityException if {@code admin} is not the device owner, or a profile owner of
-     * secondary user that is affiliated with the device.
+     * @throws SecurityException if {@code admin} is not the device owner, a profile owner of
+     * secondary user that is affiliated with the device or if the caller is not a holder of
+     * the permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_STATUS_BAR}.
      * @see #isAffiliatedUser
      * @see #getSecondaryUsers
      */
-    public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_STATUS_BAR, conditional = true)
+    public boolean setStatusBarDisabled(@Nullable ComponentName admin, boolean disabled) {
         throwIfParentInstance("setStatusBarDisabled");
         try {
-            return mService.setStatusBarDisabled(admin, disabled);
+            return mService.setStatusBarDisabled(admin, mContext.getPackageName(), disabled);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -12904,7 +13129,8 @@
      * cannot manage it through the UI, and {@link #PERMISSION_GRANT_STATE_GRANTED granted} in which
      * the permission is granted and the user cannot manage it through the UI. This method can only
      * be called by a profile owner, device owner, or a delegate given the
-     * {@link #DELEGATION_PERMISSION_GRANT} scope via {@link #setDelegatedScopes}.
+     * {@link #DELEGATION_PERMISSION_GRANT} scope via {@link #setDelegatedScopes} or holders of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS} .
      * <p/>
      * Note that user cannot manage other permissions in the affected group through the UI
      * either and their granted state will be kept as the current value. Thus, it's recommended that
@@ -12967,22 +13193,25 @@
      * the permissions listed above and {@code grantState} of
      * {@code #PERMISSION_GRANT_STATE_GRANTED}), but may deny them.
      *
-     * @param admin Which profile or device owner this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param packageName The application to grant or revoke a permission to.
      * @param permission The permission to grant or revoke.
      * @param grantState The permission grant state which is one of
      *            {@link #PERMISSION_GRANT_STATE_DENIED}, {@link #PERMISSION_GRANT_STATE_DEFAULT},
      *            {@link #PERMISSION_GRANT_STATE_GRANTED},
      * @return whether the permission was successfully granted or revoked.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS}.
      * @see #PERMISSION_GRANT_STATE_DENIED
      * @see #PERMISSION_GRANT_STATE_DEFAULT
      * @see #PERMISSION_GRANT_STATE_GRANTED
      * @see #setDelegatedScopes
      * @see #DELEGATION_PERMISSION_GRANT
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, conditional = true)
     @SupportsCoexistence
-    public boolean setPermissionGrantState(@NonNull ComponentName admin,
+    public boolean setPermissionGrantState(@Nullable ComponentName admin,
             @NonNull String packageName, @NonNull String permission,
             @PermissionGrantState int grantState) {
         throwIfParentInstance("setPermissionGrantState");
@@ -13010,11 +13239,11 @@
      * function can be called by a device owner, profile owner, or by a delegate given the
      * {@link #DELEGATION_PERMISSION_GRANT} scope via {@link #setDelegatedScopes}.
      *
-     * @param admin Which profile or device owner this request is associated with, or {@code null}
-     *            if the caller is a permission grant delegate.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param packageName The application to check the grant state for.
      * @param permission The permission to check for.
-     * @return the current grant state specified by device policy. If the profile or device owner
+     * @return the current grant state specified by device policy. If admins have not set a grant
      *         has not set a grant state, the return value is
      *         {@link #PERMISSION_GRANT_STATE_DEFAULT}. This does not indicate whether or not the
      *         permission is currently granted for the package.
@@ -13023,12 +13252,14 @@
      *         be one of {@link #PERMISSION_GRANT_STATE_DENIED} or
      *         {@link #PERMISSION_GRANT_STATE_GRANTED}, which indicates if the permission is
      *         currently denied or granted.
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS}.
      * @see #setPermissionGrantState(ComponentName, String, String, int)
      * @see PackageManager#checkPermission(String, String)
      * @see #setDelegatedScopes
      * @see #DELEGATION_PERMISSION_GRANT
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, conditional = true)
     public @PermissionGrantState int getPermissionGrantState(@Nullable ComponentName admin,
             @NonNull String packageName, @NonNull String permission) {
         throwIfParentInstance("getPermissionGrantState");
@@ -13143,7 +13374,9 @@
     }
 
     /**
-     * Called by a device admin to set the short support message. This will be displayed to the user
+     * Called by a device admin or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE} to set the short
+     * support message. This will be displayed to the user
      * in settings screens where funtionality has been disabled by the admin. The message should be
      * limited to a short statement such as "This setting is disabled by your administrator. Contact
      * someone@example.com for support." If the message is longer than 200 characters it may be
@@ -13154,17 +13387,21 @@
      * and set a new version of this string accordingly.
      *
      * @see #setLongSupportMessage
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param message Short message to be displayed to the user in settings or null to clear the
      *            existing message.
-     * @throws SecurityException if {@code admin} is not an active administrator.
+     * @throws SecurityException if {@code admin} is not an active administrator and is not a
+     * holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE}.
      */
-    public void setShortSupportMessage(@NonNull ComponentName admin,
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE, conditional = true)
+    public void setShortSupportMessage(@Nullable ComponentName admin,
             @Nullable CharSequence message) {
         throwIfParentInstance("setShortSupportMessage");
         if (mService != null) {
             try {
-                mService.setShortSupportMessage(admin, message);
+                mService.setShortSupportMessage(admin, mContext.getPackageName(), message);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -13172,18 +13409,23 @@
     }
 
     /**
-     * Called by a device admin to get the short support message.
+     * Called by a device admin or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE} to get the short
+     * support message.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @return The message set by {@link #setShortSupportMessage(ComponentName, CharSequence)} or
      *         null if no message has been set.
-     * @throws SecurityException if {@code admin} is not an active administrator.
+     * @throws SecurityException if {@code admin} is not an active administrator and not a holder of
+     * the permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE}..
      */
-    public CharSequence getShortSupportMessage(@NonNull ComponentName admin) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE, conditional = true)
+    public CharSequence getShortSupportMessage(@Nullable ComponentName admin) {
         throwIfParentInstance("getShortSupportMessage");
         if (mService != null) {
             try {
-                return mService.getShortSupportMessage(admin);
+                return mService.getShortSupportMessage(admin, mContext.getPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -13709,51 +13951,47 @@
     }
 
     /**
-     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
-     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
-     * holders of the permission
-     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY} to set the
-     * name of the organization under management.
+     * Called by the device owner (since API 26) or profile owner (since API 24) or holders of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY} to
+     * set the name of the organization under management.
      *
      * <p>If the organization name needs to be localized, it is the responsibility of the caller
      * to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast and set a new version of this
      * string accordingly.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
-     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param title The organization name or {@code null} to clear a previously set name.
      * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
      * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
      */
-    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, conditional = true)
     public void setOrganizationName(@Nullable ComponentName admin, @Nullable CharSequence title) {
         throwIfParentInstance("setOrganizationName");
         try {
-            mService.setOrganizationName(admin, title);
+            mService.setOrganizationName(admin, mContext.getPackageName(), title);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
-     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
-     * holders of the permission
-     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY
+     * Called by the device owner (since API 26) or profile owner (since API 24) or holders of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY
      * to retrieve the name of the organization under management.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
-     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @return The organization name or {@code null} if none is set.
      * @throws SecurityException if {@code admin} if {@code admin} is not a device or profile
      * owner or holder of the
      * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
      */
-    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY, conditional = true)
     public @Nullable CharSequence getOrganizationName(@Nullable ComponentName admin) {
         throwIfParentInstance("getOrganizationName");
         try {
-            return mService.getOrganizationName(admin);
+            return mService.getOrganizationName(admin, mContext.getPackageName());
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -15552,22 +15790,28 @@
     }
 
     /**
-     * Called by a device owner or a profile owner to disable user control over apps. User will not
-     * be able to clear app data or force-stop packages. When called by a device owner, applies to
-     * all users on the device. Starting from Android 13, packages with user control disabled are
-     * exempted from being put in the "restricted" App Standby Bucket.
+     * Called by a device owner or a profile owner or holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL} to disable user
+     * control over apps. User will not be able to clear app data or force-stop packages. When
+     * called by a device owner, applies to all users on the device. Starting from Android 13,
+     * packages with user control disabled are exempted from being put in the "restricted" App
+     * Standby Bucket.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
      * @param packages The package names for the apps.
-     * @throws SecurityException if {@code admin} is not a device owner or a profile owner.
+     * @throws SecurityException if {@code admin} is not a device owner or a profile owner or
+     * holder of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL}.
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional = true)
     @SupportsCoexistence
-    public void setUserControlDisabledPackages(@NonNull ComponentName admin,
+    public void setUserControlDisabledPackages(@Nullable ComponentName admin,
             @NonNull List<String> packages) {
         throwIfParentInstance("setUserControlDisabledPackages");
         if (mService != null) {
             try {
-                mService.setUserControlDisabledPackages(admin, packages);
+                mService.setUserControlDisabledPackages(admin, mContext.getPackageName(), packages);
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -15576,17 +15820,21 @@
 
     /**
      * Returns the list of packages over which user control is disabled by a device or profile
-     * owner.
+     * owner or holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL}.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with
-     * @throws SecurityException if {@code admin} is not a device or profile owner.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *               caller is not a device admin.
+     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
+     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL}.
      */
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_APPS_CONTROL, conditional = true)
     @NonNull
-    public List<String> getUserControlDisabledPackages(@NonNull ComponentName admin) {
+    public List<String> getUserControlDisabledPackages(@Nullable ComponentName admin) {
         throwIfParentInstance("getUserControlDisabledPackages");
         if (mService != null) {
             try {
-                return mService.getUserControlDisabledPackages(admin);
+                return mService.getUserControlDisabledPackages(admin, mContext.getPackageName());
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
@@ -15595,7 +15843,9 @@
     }
 
     /**
-     * Called by device owner or profile owner of an organization-owned managed profile to toggle
+     * Called by device owner or profile owner of an organization-owned managed profile or
+     * holders of the permission
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE} to toggle
      * Common Criteria mode for the device. When the device is in Common Criteria mode,
      * certain device functionalities are tuned to meet the higher
      * security level required by Common Criteria certification. For example:
@@ -15608,14 +15858,16 @@
      * <p><em>Note:</em> if Common Critera mode is turned off after being enabled previously,
      * all existing WiFi configurations will be lost.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @param enabled whether Common Criteria mode should be enabled or not.
      */
-    public void setCommonCriteriaModeEnabled(@NonNull ComponentName admin, boolean enabled) {
+    @RequiresPermission(value = MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE, conditional = true)
+    public void setCommonCriteriaModeEnabled(@Nullable ComponentName admin, boolean enabled) {
         throwIfParentInstance("setCommonCriteriaModeEnabled");
         if (mService != null) {
             try {
-                mService.setCommonCriteriaModeEnabled(admin, enabled);
+                mService.setCommonCriteriaModeEnabled(admin, mContext.getPackageName(), enabled);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -15629,8 +15881,8 @@
      * aggregated device-wide Common Criteria mode state by passing {@code null} as the
      * {@code admin} argument.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with, or
-     *     {@code null} if the caller is not a device admin.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+     *              caller is not a device admin.
      * @return {@code true} if Common Criteria mode is enabled, {@code false} otherwise.
      */
     public boolean isCommonCriteriaModeEnabled(@Nullable ComponentName admin) {
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index eefadea..5345947 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -25,7 +25,6 @@
 import android.os.UserHandle;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -279,11 +278,13 @@
      * The given permission will be checked along with its associated cross-user permission, if it
      * exists and the target user is different to the calling user.
      *
+     * @param callerPackage the package of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      * @throws SecurityException If the calling process has not been granted the permission.
      */
-    public abstract void enforcePermission(String permission, int targetUserId);
+    public abstract void enforcePermission(String callerPackage, String permission,
+            int targetUserId);
 
     /**
      * Return whether the calling process has been granted permission to apply a device policy on
@@ -292,10 +293,12 @@
      * The given permission will be checked along with its associated cross-user
      * permission, if it exists and the target user is different to the calling user.
      *
+     * @param callerPackage the package of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      */
-    public abstract boolean hasPermission(String permission, int targetUserId);
+    public abstract boolean hasPermission(String callerPackage, String permission,
+            int targetUserId);
 
     /**
      * Returns whether new "turn off work" behavior is enabled via feature flag.
@@ -318,8 +321,9 @@
     public abstract boolean isApplicationExemptionsFlagEnabled();
 
     /**
-    * Returns the application restrictions set by each admin for the given {@code packageName}.
+     * Returns a map of admin to {@link Bundle} map of restrictions set by the admins for the
+     * provided {@code packageName} in the provided {@code userId}
      */
-    public abstract Map<String, Bundle> getApplicationRestrictionsPerAdmin(
-            String packageName, int userId);
+    public abstract List<Bundle> getApplicationRestrictionsPerAdminForUser(
+            String packageName, @UserIdInt int userId);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 14c6ecd..a4dedea 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,7 +124,7 @@
     /**
     * @param factoryReset only applicable when `targetSdk >= U`, either tries to factoryReset/fail or removeUser/fail otherwise
     **/
-    void wipeDataWithReason(int flags, String wipeReasonForUser, boolean parent, boolean factoryReset);
+    void wipeDataWithReason(String callerPackageName, int flags, String wipeReasonForUser, boolean parent, boolean factoryReset);
 
     void setFactoryResetProtectionPolicy(in ComponentName who, String callerPackageName, in FactoryResetProtectionPolicy policy);
     FactoryResetProtectionPolicy getFactoryResetProtectionPolicy(in ComponentName who);
@@ -143,7 +143,7 @@
     boolean requestBugreport(in ComponentName who);
 
     void setCameraDisabled(in ComponentName who, String callerPackageName, boolean disabled, boolean parent);
-    boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent);
+    boolean getCameraDisabled(in ComponentName who, String callerPackageName, int userHandle, boolean parent);
 
     void setScreenCaptureDisabled(
         in ComponentName who, String callerPackageName, boolean disabled, boolean parent);
@@ -235,10 +235,11 @@
     boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle);
     List<String> getAlwaysOnVpnLockdownAllowlist(in ComponentName who);
 
-    void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
-    void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
+    void addPersistentPreferredActivity(in ComponentName admin, String callerPackageName, in IntentFilter filter, in ComponentName activity);
+    void clearPackagePersistentPreferredActivities(in ComponentName admin, String callerPackageName, String packageName);
 
-    void setDefaultSmsApplication(in ComponentName admin, String packageName, boolean parent);
+    void setDefaultSmsApplication(in ComponentName admin, String callerPackageName, String packageName, boolean parent);
+    void setDefaultDialerApplication(String packageName);
 
     void setApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in Bundle settings);
     Bundle getApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName);
@@ -254,8 +255,8 @@
     Bundle getUserRestrictions(in ComponentName who, in String callerPackage, boolean parent);
     Bundle getUserRestrictionsGlobally(in String callerPackage);
 
-    void addCrossProfileIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
-    void clearCrossProfileIntentFilters(in ComponentName admin);
+    void addCrossProfileIntentFilter(in ComponentName admin, String callerPackageName, in IntentFilter filter, int flags);
+    void clearCrossProfileIntentFilters(in ComponentName admin, String callerPackageName);
 
     boolean setPermittedAccessibilityServices(in ComponentName admin,in List<String> packageList);
     List<String> getPermittedAccessibilityServices(in ComponentName admin);
@@ -292,9 +293,9 @@
     int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent);
     boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName);
 
-    void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled, in boolean parent);
-    String[] getAccountTypesWithManagementDisabled();
-    String[] getAccountTypesWithManagementDisabledAsUser(int userId, in boolean parent);
+    void setAccountManagementDisabled(in ComponentName who, String callerPackageName, in String accountType, in boolean disabled, in boolean parent);
+    String[] getAccountTypesWithManagementDisabled(String callerPackageName);
+    String[] getAccountTypesWithManagementDisabledAsUser(int userId, String callerPackageName, in boolean parent);
 
     void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled);
     boolean isSecondaryLockscreenEnabled(in UserHandle userHandle);
@@ -303,12 +304,12 @@
             in List<PreferentialNetworkServiceConfig> preferentialNetworkServiceConfigs);
     List<PreferentialNetworkServiceConfig> getPreferentialNetworkServiceConfigs();
 
-    void setLockTaskPackages(in ComponentName who, in String[] packages);
-    String[] getLockTaskPackages(in ComponentName who);
+    void setLockTaskPackages(in ComponentName who, String callerPackageName, in String[] packages);
+    String[] getLockTaskPackages(in ComponentName who, String callerPackageName);
     boolean isLockTaskPermitted(in String pkg);
 
-    void setLockTaskFeatures(in ComponentName who, int flags);
-    int getLockTaskFeatures(in ComponentName who);
+    void setLockTaskFeatures(in ComponentName who, String callerPackageName, int flags);
+    int getLockTaskFeatures(in ComponentName who, String callerPackageName);
 
     void setGlobalSetting(in ComponentName who, in String setting, in String value);
     void setSystemSetting(in ComponentName who, in String setting, in String value);
@@ -319,8 +320,8 @@
 
     void setLocationEnabled(in ComponentName who, boolean locationEnabled);
 
-    boolean setTime(in ComponentName who, long millis);
-    boolean setTimeZone(in ComponentName who, String timeZone);
+    boolean setTime(in ComponentName who, String callerPackageName, long millis);
+    boolean setTimeZone(in ComponentName who, String callerPackageName, String timeZone);
 
     void setMasterVolumeMuted(in ComponentName admin, boolean on);
     boolean isMasterVolumeMuted(in ComponentName admin);
@@ -328,7 +329,7 @@
     void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userId);
 
     void setUninstallBlocked(in ComponentName admin, in String callerPackage, in String packageName, boolean uninstallBlocked);
-    boolean isUninstallBlocked(in ComponentName admin, in String packageName);
+    boolean isUninstallBlocked(in String packageName);
 
     void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
     boolean getCrossProfileCallerIdDisabled(in ComponentName who);
@@ -358,18 +359,18 @@
     List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
             in ComponentName agent, int userId, boolean parent);
 
-    boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName);
-    boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName);
-    List<String> getCrossProfileWidgetProviders(in ComponentName admin);
+    boolean addCrossProfileWidgetProvider(in ComponentName admin, String callerPackageName, String packageName);
+    boolean removeCrossProfileWidgetProvider(in ComponentName admin, String callerPackageName, String packageName);
+    List<String> getCrossProfileWidgetProviders(in ComponentName admin, String callerPackageName);
 
     void setAutoTimeRequired(in ComponentName who, boolean required);
     boolean getAutoTimeRequired();
 
-    void setAutoTimeEnabled(in ComponentName who, boolean enabled);
-    boolean getAutoTimeEnabled(in ComponentName who);
+    void setAutoTimeEnabled(in ComponentName who, String callerPackageName, boolean enabled);
+    boolean getAutoTimeEnabled(in ComponentName who, String callerPackageName);
 
-    void setAutoTimeZoneEnabled(in ComponentName who, boolean enabled);
-    boolean getAutoTimeZoneEnabled(in ComponentName who);
+    void setAutoTimeZoneEnabled(in ComponentName who, String callerPackageName, boolean enabled);
+    boolean getAutoTimeZoneEnabled(in ComponentName who, String callerPackageName);
 
     void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
     boolean getForceEphemeralUsers(in ComponentName who);
@@ -383,7 +384,7 @@
     void clearSystemUpdatePolicyFreezePeriodRecord();
 
     boolean setKeyguardDisabled(in ComponentName admin, boolean disabled);
-    boolean setStatusBarDisabled(in ComponentName who, boolean disabled);
+    boolean setStatusBarDisabled(in ComponentName who, String callerPackageName, boolean disabled);
     boolean isStatusBarDisabled(in String callerPackage);
     boolean getDoNotAskCredentialsOnBoot();
 
@@ -403,8 +404,8 @@
     String getWifiMacAddress(in ComponentName admin, String callerPackageName);
     void reboot(in ComponentName admin);
 
-    void setShortSupportMessage(in ComponentName admin, in CharSequence message);
-    CharSequence getShortSupportMessage(in ComponentName admin);
+    void setShortSupportMessage(in ComponentName admin, String callerPackageName, in CharSequence message);
+    CharSequence getShortSupportMessage(in ComponentName admin, String callerPackageName);
     void setLongSupportMessage(in ComponentName admin, in CharSequence message);
     CharSequence getLongSupportMessage(in ComponentName admin);
 
@@ -417,8 +418,8 @@
     int getOrganizationColor(in ComponentName admin);
     int getOrganizationColorForUser(int userHandle);
 
-    void setOrganizationName(in ComponentName admin, in CharSequence title);
-    CharSequence getOrganizationName(in ComponentName admin);
+    void setOrganizationName(in ComponentName admin, String callerPackageName, in CharSequence title);
+    CharSequence getOrganizationName(in ComponentName admin, String callerPackageName);
     CharSequence getDeviceOwnerOrganizationName();
     CharSequence getOrganizationNameForUser(int userHandle);
 
@@ -463,10 +464,10 @@
     long getLastBugReportRequestTime();
     long getLastNetworkLogRetrievalTime();
 
-    boolean setResetPasswordToken(in ComponentName admin, in byte[] token);
-    boolean clearResetPasswordToken(in ComponentName admin);
-    boolean isResetPasswordTokenActive(in ComponentName admin);
-    boolean resetPasswordWithToken(in ComponentName admin, String password, in byte[] token, int flags);
+    boolean setResetPasswordToken(in ComponentName admin, String callerPackageName, in byte[] token);
+    boolean clearResetPasswordToken(in ComponentName admin, String callerPackageName);
+    boolean isResetPasswordTokenActive(in ComponentName admin, String callerPackageName);
+    boolean resetPasswordWithToken(in ComponentName admin, String callerPackageName, String password, in byte[] token, int flags);
 
     boolean isCurrentInputMethodSetByOwner();
     StringParceledListSlice getOwnerInstalledCaCerts(in UserHandle user);
@@ -527,11 +528,11 @@
     boolean setKeyGrantToWifiAuth(String callerPackage, String alias, boolean hasGrant);
     boolean isKeyPairGrantedToWifiAuth(String callerPackage, String alias);
 
-    void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages);
+    void setUserControlDisabledPackages(in ComponentName admin, String callerPackageName, in List<String> packages);
 
-    List<String> getUserControlDisabledPackages(in ComponentName admin);
+    List<String> getUserControlDisabledPackages(in ComponentName admin, String callerPackageName);
 
-    void setCommonCriteriaModeEnabled(in ComponentName admin, boolean enabled);
+    void setCommonCriteriaModeEnabled(in ComponentName admin, String callerPackageName, boolean enabled);
     boolean isCommonCriteriaModeEnabled(in ComponentName admin);
 
     int getPersonalAppsSuspendedReasons(in ComponentName admin);
diff --git a/core/java/android/app/admin/PolicyUpdateReceiver.java b/core/java/android/app/admin/PolicyUpdateReceiver.java
index 58f4f1b..b5d9286 100644
--- a/core/java/android/app/admin/PolicyUpdateReceiver.java
+++ b/core/java/android/app/admin/PolicyUpdateReceiver.java
@@ -19,6 +19,7 @@
 import android.annotation.BroadcastBehavior;
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
+import android.annotation.TestApi;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -112,31 +113,37 @@
             "android.app.admin.extra.ACCOUNT_TYPE";
 
     /**
+     * String extra containing the policy identifier.
+     *
      * @hide
      */
-    public static final String EXTRA_POLICY_CHANGED_KEY =
-            "android.app.admin.extra.POLICY_CHANGED_KEY";
-
-    /**
-     * @hide
-     */
+    @TestApi
     public static final String EXTRA_POLICY_KEY = "android.app.admin.extra.POLICY_KEY";
 
     /**
+     * Bundle extra containing additional information related to a policy.
+     *
      * @hide
      */
+    @TestApi
     public static final String EXTRA_POLICY_BUNDLE_KEY =
             "android.app.admin.extra.POLICY_BUNDLE_KEY";
 
     /**
+     * Int extra containing the {@link PolicyUpdateResult} code.
+     *
      * @hide
      */
+    @TestApi
     public static final String EXTRA_POLICY_UPDATE_RESULT_KEY =
             "android.app.admin.extra.POLICY_UPDATE_RESULT_KEY";
 
     /**
+     * Int extra containing the target user this policy update applies to.
+     *
      * @hide
      */
+    @TestApi
     public static final String EXTRA_POLICY_TARGET_USER_ID =
             "android.app.admin.extra.POLICY_TARGET_USER_ID";
 
diff --git a/core/java/android/app/admin/TargetUser.java b/core/java/android/app/admin/TargetUser.java
index ed4fae0..ce6f32b 100644
--- a/core/java/android/app/admin/TargetUser.java
+++ b/core/java/android/app/admin/TargetUser.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 
 import java.util.Objects;
 
@@ -29,23 +30,35 @@
  */
 public final class TargetUser {
     /**
+     * Indicates that the policy relates to the user the admin is installed on.
+     *
      * @hide
      */
+    @TestApi
     public static final int LOCAL_USER_ID = -1;
 
     /**
+     * For admins of profiles, this indicates that the policy relates to the parent profile.
+     *
      * @hide
      */
+    @TestApi
     public static final int PARENT_USER_ID = -2;
 
     /**
+     * This indicates the policy is a global policy.
+     *
      * @hide
      */
+    @TestApi
     public static final int GLOBAL_USER_ID = -3;
 
     /**
+     * Indicates that the policy relates to some unknown user on the device.
+     *
      * @hide
      */
+    @TestApi
     public static final int UNKNOWN_USER_ID = -3;
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0d330ce..fcffc6f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -7384,7 +7384,6 @@
      * @throws IllegalArgumentException if the given device ID is not a valid ID of the default
      *         device or a virtual device.
      *
-     * @see #isDeviceContext()
      * @see #createDeviceContext(int)
      * @hide
      */
@@ -7408,26 +7407,8 @@
      * </p>
      *
      * <p>
-     * This method will only return a reliable value for this instance if
-     * {@link Context#isDeviceContext()} is {@code true}. The system can assign an arbitrary device
-     * id value for Contexts not logically associated with a device.
-     * </p>
-     *
-     * @return the ID of the device this context is associated with.
-     * @see #isDeviceContext()
-     * @see #createDeviceContext(int)
-     * @see #registerDeviceIdChangeListener(Executor, IntConsumer)
-     */
-    public int getDeviceId() {
-        throw new RuntimeException("Not implemented. Must override in a subclass.");
-    }
-
-    /**
-     * Indicates whether the value of {@link Context#getDeviceId()} can be relied upon for
-     * this instance. It will return {@code true} for Contexts created by
-     * {@link Context#createDeviceContext(int)} which reference a valid device ID, as well as for
-     * UI and Display Contexts.
-     * <p>
+     * This method will only return a reliable value for this instance if it was created with
+     * {@link Context#createDeviceContext(int)}, or if this instance is a UI or Display Context.
      * Contexts created with {@link Context#createDeviceContext(int)} will have an explicit
      * device association, which will never change, even if the underlying device is closed or is
      * removed. UI Contexts and Display Contexts are
@@ -7437,15 +7418,12 @@
      * logically associated with a device.
      * </p>
      *
-     * @return {@code true} if {@link Context#getDeviceId()} is reliable, {@code false} otherwise.
-     *
+     * @return the ID of the device this context is associated with.
      * @see #createDeviceContext(int)
-     * @see #getDeviceId()}
-     * @see #createDisplayContext(Display)
+     * @see #registerDeviceIdChangeListener(Executor, IntConsumer)
      * @see #isUiContext()
      */
-
-    public boolean isDeviceContext() {
+    public int getDeviceId() {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
 
@@ -7464,7 +7442,6 @@
      * @param listener The listener {@code IntConsumer} to call which will receive the updated
      *                 device ID.
      *
-     * @see Context#isDeviceContext()
      * @see Context#getDeviceId()
      * @see Context#createDeviceContext(int)
      */
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index a103128..91be664 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1201,11 +1201,6 @@
     }
 
     @Override
-    public boolean isDeviceContext() {
-        return mBase.isDeviceContext();
-    }
-
-    @Override
     public void registerDeviceIdChangeListener(@NonNull @CallbackExecutor Executor executor,
             @NonNull IntConsumer listener) {
         mBase.registerDeviceIdChangeListener(executor, listener);
diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl
index db9146f..0fcd63f 100644
--- a/core/java/android/content/IRestrictionsManager.aidl
+++ b/core/java/android/content/IRestrictionsManager.aidl
@@ -26,6 +26,7 @@
  */
 interface IRestrictionsManager {
     Bundle getApplicationRestrictions(in String packageName);
+    List<Bundle> getApplicationRestrictionsPerAdminForUser(int userId, in String packageName);
     boolean hasRestrictionsProvider();
     void requestPermission(in String packageName, in String requestType, in String requestId,
             in PersistableBundle requestData);
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index ffd80ea..8115292 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -18,7 +18,10 @@
 
 import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
 
+import android.annotation.NonNull;
 import android.annotation.SystemService;
+import android.annotation.UserHandleAware;
+import android.annotation.WorkerThread;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -31,6 +34,7 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.os.UserManager;
 import android.service.restrictions.RestrictionsReceiver;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -422,6 +426,14 @@
      * to this application.
      * @return the application restrictions as a Bundle. Returns null if there
      * are no restrictions.
+     *
+     * @deprecated Use {@link #getApplicationRestrictionsPerAdmin} instead.
+     * Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it is
+     * possible for there to be multiple managing agents on the device with the ability to set
+     * restrictions. This API will only to return the restrictions set by device policy controllers
+     * (DPCs)
+     *
+     * @see DevicePolicyManager
      */
     public Bundle getApplicationRestrictions() {
         try {
@@ -435,6 +447,46 @@
     }
 
     /**
+     * Returns a {@link List} containing a {@link Bundle} for each managing agent that has set
+     * restrictions for the current application, the bundle contains any application restrictions
+     * set for the current package. The order of the items in the list is not guaranteed to remain
+     * stable between multiple calls.
+     *
+     * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+     * it is possible for there to be multiple managing agents on the device with the ability to set
+     * restrictions, e.g. an Enterprise DPC and a Supervision admin.
+     *
+     * <p>Each {@link Bundle} consists of key-value pairs, as defined by the application,
+     * where the types of values may be:
+     * <ul>
+     * <li>{@code boolean}
+     * <li>{@code int}
+     * <li>{@code String} or {@code String[]}
+     * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
+     * </ul>
+     *
+     * <p>NOTE: The method performs disk I/O and shouldn't be called on the main thread
+     *
+     * @return a {@link List} of {@link Bundle} containing the restrictions set by admins for that
+     * package. Returns an empty {@link List} if there are no saved restrictions.
+     *
+     * @see UserManager#KEY_RESTRICTIONS_PENDING
+     */
+    @WorkerThread
+    @UserHandleAware
+    public @NonNull List<Bundle> getApplicationRestrictionsPerAdmin() {
+        try {
+            if (mService != null) {
+                return mService.getApplicationRestrictionsPerAdminForUser(
+                        mContext.getUserId(), mContext.getPackageName());
+            }
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+        return null;
+    }
+
+    /**
      * Called by an application to check if there is an active Restrictions Provider. If
      * there isn't, {@link #requestPermission(String, String, PersistableBundle)} is not available.
      *
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index cfd291f..2b4ea70 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2914,10 +2914,10 @@
          *     <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li>
          *     <li>The app being installed targets:
          *          <ul>
-         *              <li>{@link android.os.Build.VERSION_CODES#Q API 29} or higher on
-         *              Android S ({@link android.os.Build.VERSION_CODES#S API 31})</li>
-         *              <li>{@link android.os.Build.VERSION_CODES#R API 30} or higher after
-         *              Android S ({@link android.os.Build.VERSION_CODES#S API 31})</li>
+         *              <li>{@link android.os.Build.VERSION_CODES#R API 30} or higher on
+         *              Android T ({@link android.os.Build.VERSION_CODES#TIRAMISU API 33})</li>
+         *              <li>{@link android.os.Build.VERSION_CODES#S API 31} or higher <b>after</b>
+         *              Android T ({@link android.os.Build.VERSION_CODES#TIRAMISU API 33})</li>
          *          </ul>
          *     </li>
          *     <li>The installer is:
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index 07473d2..ff7fc36 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -332,6 +332,7 @@
             @Nullable CancellationSignal cancellationSignal,
             @CallbackExecutor @NonNull Executor executor,
             @NonNull OutcomeReceiver<Void, ClearCredentialStateException> callback) {
+        requireNonNull(request, "request must not be null");
         requireNonNull(executor, "executor must not be null");
         requireNonNull(callback, "callback must not be null");
 
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 3b62881..80ae8a8 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -86,6 +86,12 @@
     boolean isExemptFromLowPowerStandby();
     boolean isReasonAllowedInLowPowerStandby(int reason);
     boolean isFeatureAllowedInLowPowerStandby(String feature);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)")
+    void acquireLowPowerStandbyPorts(in IBinder token, in List<LowPowerStandbyPortDescription> ports);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)")
+    void releaseLowPowerStandbyPorts(in IBinder token);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_LOW_POWER_STANDBY, android.Manifest.permission.DEVICE_POWER })")
+    List<LowPowerStandbyPortDescription> getActiveLowPowerStandbyPorts();
 
     parcelable LowPowerStandbyPolicy {
         String identifier;
@@ -94,6 +100,13 @@
         List<String> allowedFeatures;
     }
 
+    parcelable LowPowerStandbyPortDescription {
+        int protocol;
+        int portMatcher;
+        int portNumber;
+        @nullable String bindAddress;
+    }
+
     @UnsupportedAppUsage
     void reboot(boolean confirm, String reason, boolean wait);
     void rebootSafeMode(boolean confirm, boolean wait);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 797730b..3cf3ea2 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -133,6 +133,7 @@
     boolean isUserForeground(int userId);
     boolean isUserVisible(int userId);
     int[] getVisibleUsers();
+    int getDisplayIdAssignedToUser();
     boolean isUserNameSet(int userId);
     boolean hasRestrictedProfiles(int userId);
     boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userId, in IntentSender target, int flags);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 03c32d70..ed1afa2 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -32,6 +32,7 @@
 import android.app.PropertyInvalidatedCache;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.net.LinkAddress;
 import android.service.dreams.Sandman;
 import android.sysprop.InitProperties;
 import android.util.ArrayMap;
@@ -47,6 +48,7 @@
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Executor;
@@ -2472,6 +2474,49 @@
     }
 
     /**
+     * Creates a new Low Power Standby ports lock.
+     *
+     * <p>A Low Power Standby ports lock requests that the given ports remain open during
+     * Low Power Standby.
+     * Call {@link LowPowerStandbyPortsLock#acquire} to acquire the lock.
+     * This request is only respected if the calling package is exempt
+     * (see {@link #isExemptFromLowPowerStandby()}), and until the returned
+     * {@code LowPowerStandbyPorts} object is destroyed or has
+     * {@link LowPowerStandbyPortsLock#release} called on it.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
+    @NonNull
+    public LowPowerStandbyPortsLock newLowPowerStandbyPortsLock(
+            @NonNull List<LowPowerStandbyPortDescription> ports) {
+        LowPowerStandbyPortsLock standbyPorts = new LowPowerStandbyPortsLock(ports);
+        return standbyPorts;
+    }
+
+    /**
+     * Gets all ports that should remain open in standby.
+     * Only includes ports requested by exempt packages (see {@link #getLowPowerStandbyPolicy()}).
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
+            android.Manifest.permission.DEVICE_POWER
+    })
+    @NonNull
+    public List<LowPowerStandbyPortDescription> getActiveLowPowerStandbyPorts() {
+        try {
+            return LowPowerStandbyPortDescription.fromParcelable(
+                    mService.getActiveLowPowerStandbyPorts());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return whether the given application package name is on the device's power allowlist.
      * Apps can be placed on the allowlist through the settings UI invoked by
      * {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
@@ -2980,6 +3025,19 @@
             "android.os.action.LOW_POWER_STANDBY_POLICY_CHANGED";
 
     /**
+     * Intent that is broadcast when Low Power Standby exempt ports change.
+     * This broadcast is only sent to registered receivers.
+     *
+     * @see #getActiveLowPowerStandbyPorts
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_LOW_POWER_STANDBY)
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LOW_POWER_STANDBY_PORTS_CHANGED =
+            "android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED";
+
+    /**
      * Signals that wake-on-lan/wake-on-wlan is allowed in Low Power Standby.
      *
      * <p>If Low Power Standby is enabled ({@link #isLowPowerStandbyEnabled()}),
@@ -3154,6 +3212,322 @@
     }
 
     /**
+     * Describes ports that may be requested to remain open during Low Power Standby.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class LowPowerStandbyPortDescription {
+        /** @hide */
+        @IntDef(prefix = { "PROTOCOL_" }, value = {
+                PROTOCOL_TCP,
+                PROTOCOL_UDP,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Protocol {
+        }
+
+        /**
+         * Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a TCP port.
+         */
+        public static final int PROTOCOL_TCP = 1;
+        /**
+         * Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a UDP port.
+         */
+        public static final int PROTOCOL_UDP = 2;
+
+        /** @hide */
+        @IntDef(prefix = { "MATCH_PORT_" }, value = {
+                MATCH_PORT_LOCAL,
+                MATCH_PORT_REMOTE,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface PortMatcher {
+        }
+        /**
+         * Constant to indicate the {@link LowPowerStandbyPortDescription}'s port number is to be
+         * matched against the socket's local port number (the destination port number of an
+         * incoming packet).
+         */
+        public static final int MATCH_PORT_LOCAL = 1;
+        /**
+         * Constant to indicate the {@link LowPowerStandbyPortDescription}'s port number is to be
+         * matched against the socket's remote port number (the source port number of an
+         * incoming packet).
+         */
+        public static final int MATCH_PORT_REMOTE = 2;
+
+        @Protocol
+        private final int mProtocol;
+        @PortMatcher
+        private final int mPortMatcher;
+        private final int mPortNumber;
+        @Nullable
+        private final LinkAddress mBindAddress;
+
+        /**
+         * Describes a port.
+         *
+         * @param protocol The protocol of the port to match, {@link #PROTOCOL_TCP} or
+         *                 {@link #PROTOCOL_UDP}.
+         * @param portMatcher Whether to match the source port number of an incoming packet
+         *                    ({@link #MATCH_PORT_REMOTE}), or the destination port
+         *                    ({@link #MATCH_PORT_LOCAL}).
+         * @param portNumber The port number to match.
+         *
+         * @see #newLowPowerStandbyPortsLock(List)
+         */
+        public LowPowerStandbyPortDescription(@Protocol int protocol, @PortMatcher int portMatcher,
+                int portNumber) {
+            this.mProtocol = protocol;
+            this.mPortMatcher = portMatcher;
+            this.mPortNumber = portNumber;
+            this.mBindAddress = null;
+        }
+
+        /**
+         * Describes a port.
+         *
+         * @param protocol The protocol of the port to match, {@link #PROTOCOL_TCP} or
+         *                 {@link #PROTOCOL_UDP}.
+         * @param portMatcher Whether to match the source port number of an incoming packet
+         *                    ({@link #MATCH_PORT_REMOTE}), or the destination port
+         *                    ({@link #MATCH_PORT_LOCAL}).
+         * @param portNumber The port number to match.
+         * @param bindAddress The bind address to match.
+         *
+         * @see #newLowPowerStandbyPortsLock(List)
+         */
+        public LowPowerStandbyPortDescription(@Protocol int protocol, @PortMatcher int portMatcher,
+                int portNumber, @Nullable LinkAddress bindAddress) {
+            this.mProtocol = protocol;
+            this.mPortMatcher = portMatcher;
+            this.mPortNumber = portNumber;
+            this.mBindAddress = bindAddress;
+        }
+
+        private String protocolToString(int protocol) {
+            switch (protocol) {
+                case PROTOCOL_TCP: return "TCP";
+                case PROTOCOL_UDP: return "UDP";
+            }
+            return String.valueOf(protocol);
+        }
+
+        private String portMatcherToString(int portMatcher) {
+            switch (portMatcher) {
+                case MATCH_PORT_LOCAL: return "MATCH_PORT_LOCAL";
+                case MATCH_PORT_REMOTE: return "MATCH_PORT_REMOTE";
+            }
+            return String.valueOf(portMatcher);
+        }
+
+        /**
+         * Returns the described port's protocol,
+         * either {@link #PROTOCOL_TCP} or {@link #PROTOCOL_UDP}.
+         *
+         * @see #PROTOCOL_TCP
+         * @see #PROTOCOL_UDP
+         * @see #getPortNumber()
+         * @see #getPortMatcher()
+         */
+        @Protocol
+        public int getProtocol() {
+            return mProtocol;
+        }
+
+        /**
+         * Returns how the port number ({@link #getPortNumber()}) should be matched against
+         * incoming packets.
+         * Either {@link #PROTOCOL_TCP} or {@link #PROTOCOL_UDP}.
+         *
+         * @see #PROTOCOL_TCP
+         * @see #PROTOCOL_UDP
+         * @see #getPortNumber()
+         * @see #getProtocol()
+         */
+        @PortMatcher
+        public int getPortMatcher() {
+            return mPortMatcher;
+        }
+
+        /**
+         * Returns how the port number that incoming packets should be matched against.
+         *
+         * @see #getPortMatcher()
+         * @see #getProtocol()
+         */
+        public int getPortNumber() {
+            return mPortNumber;
+        }
+
+        /**
+         * Returns the bind address to match against, or {@code null} if matching against any
+         * bind address.
+         *
+         * @see #getPortMatcher()
+         * @see #getProtocol()
+         */
+        @Nullable
+        public LinkAddress getBindAddress() {
+            return mBindAddress;
+        }
+
+        @Override
+        public String toString() {
+            return "PortDescription{"
+                    + "mProtocol=" + protocolToString(mProtocol)
+                    + ", mPortMatcher=" + portMatcherToString(mPortMatcher)
+                    + ", mPortNumber=" + mPortNumber
+                    + ", mBindAddress=" + mBindAddress
+                    + '}';
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof LowPowerStandbyPortDescription)) return false;
+            LowPowerStandbyPortDescription that = (LowPowerStandbyPortDescription) o;
+            return mProtocol == that.mProtocol && mPortMatcher == that.mPortMatcher
+                    && mPortNumber == that.mPortNumber && Objects.equals(mBindAddress,
+                    that.mBindAddress);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mProtocol, mPortMatcher, mPortNumber, mBindAddress);
+        }
+
+        /** @hide */
+        public static IPowerManager.LowPowerStandbyPortDescription toParcelable(
+                LowPowerStandbyPortDescription portDescription) {
+            if (portDescription == null) {
+                return null;
+            }
+
+            IPowerManager.LowPowerStandbyPortDescription parcelablePortDescription =
+                    new IPowerManager.LowPowerStandbyPortDescription();
+            parcelablePortDescription.protocol = portDescription.mProtocol;
+            parcelablePortDescription.portMatcher = portDescription.mPortMatcher;
+            parcelablePortDescription.portNumber = portDescription.mPortNumber;
+            if (portDescription.mBindAddress != null) {
+                parcelablePortDescription.bindAddress = portDescription.mBindAddress.toString();
+            }
+            return parcelablePortDescription;
+        }
+
+        /** @hide */
+        public static List<IPowerManager.LowPowerStandbyPortDescription> toParcelable(
+                List<LowPowerStandbyPortDescription> portDescriptions) {
+            if (portDescriptions == null) {
+                return null;
+            }
+
+            ArrayList<IPowerManager.LowPowerStandbyPortDescription> result = new ArrayList<>();
+            for (LowPowerStandbyPortDescription port : portDescriptions) {
+                result.add(toParcelable(port));
+            }
+            return result;
+        }
+
+        /** @hide */
+        public static LowPowerStandbyPortDescription fromParcelable(
+                IPowerManager.LowPowerStandbyPortDescription parcelablePortDescription) {
+            if (parcelablePortDescription == null) {
+                return null;
+            }
+
+            LinkAddress bindAddress = null;
+            if (parcelablePortDescription.bindAddress != null) {
+                bindAddress = new LinkAddress(parcelablePortDescription.bindAddress);
+            }
+            return new LowPowerStandbyPortDescription(
+                    parcelablePortDescription.protocol,
+                    parcelablePortDescription.portMatcher,
+                    parcelablePortDescription.portNumber,
+                    bindAddress);
+        }
+
+        /** @hide */
+        public static List<LowPowerStandbyPortDescription> fromParcelable(
+                List<IPowerManager.LowPowerStandbyPortDescription> portDescriptions) {
+            if (portDescriptions == null) {
+                return null;
+            }
+
+            ArrayList<LowPowerStandbyPortDescription> result = new ArrayList<>();
+            for (IPowerManager.LowPowerStandbyPortDescription port : portDescriptions) {
+                result.add(fromParcelable(port));
+            }
+            return result;
+        }
+    }
+
+    /**
+     * An object that can be used to request network ports to remain open during Low Power Standby.
+     *
+     * <p>Use {@link #newLowPowerStandbyPortsLock} to create a ports lock, and {@link #acquire()}
+     * to request the ports to remain open. The request is only respected if the app requesting the
+     * lock is exempt from Low Power Standby ({@link #isExemptFromLowPowerStandby()}).
+     *
+     * @hide
+     */
+    @SystemApi
+    @SuppressLint("NotCloseable")
+    public final class LowPowerStandbyPortsLock {
+        private final IBinder mToken;
+        private final List<LowPowerStandbyPortDescription> mPorts;
+        private boolean mHeld;
+
+        LowPowerStandbyPortsLock(List<LowPowerStandbyPortDescription> ports) {
+            mPorts = ports;
+            mToken = new Binder();
+        }
+
+        /** Request the ports to remain open during standby. */
+        @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
+        public void acquire() {
+            synchronized (mToken) {
+                try {
+                    mService.acquireLowPowerStandbyPorts(mToken,
+                            LowPowerStandbyPortDescription.toParcelable(mPorts));
+                    mHeld = true;
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+
+        /**
+         * Release the request, allowing these ports to be blocked during standby.
+         *
+         * <p>Note: This lock is not reference counted, so calling this method will release the lock
+         * regardless of how many times {@link #acquire()} has been called before.
+         */
+        @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
+        public void release() {
+            synchronized (mToken) {
+                try {
+                    mService.releaseLowPowerStandbyPorts(mToken);
+                    mHeld = false;
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+
+        @Override
+        protected void finalize() {
+            synchronized (mToken) {
+                if (mHeld) {
+                    Log.wtf(TAG, "LowPowerStandbyPorts finalized while still held");
+                    release();
+                }
+            }
+        }
+    }
+
+    /**
      * Constant for PreIdleTimeout normal mode (default mode, not short nor extend timeout) .
      * @hide
      */
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c60f558..9c55ad6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3052,6 +3052,19 @@
     }
 
     /**
+     * See {@link com.android.server.pm.UserManagerInternal#getDisplayAssignedToUser(int)}.
+     *
+     * @hide
+     */
+    public int getDisplayIdAssignedToUser() {
+        try {
+            return mService.getDisplayIdAssignedToUser();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Return whether the context user is running in an "unlocked" state.
      * <p>
      * On devices with direct boot, a user is unlocked only after they've
@@ -5574,7 +5587,17 @@
      * if there are no saved restrictions.
      *
      * @see #KEY_RESTRICTIONS_PENDING
+     *
+     * @deprecated Use
+     * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+     * Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it is
+     * possible for there to be multiple managing agents on the device with the ability to set
+     * restrictions. This API will only to return the restrictions set by device policy controllers
+     * (DPCs)
+     *
+     * @see DevicePolicyManager
      */
+    @Deprecated
     @WorkerThread
     @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
     public Bundle getApplicationRestrictions(String packageName) {
@@ -5587,8 +5610,12 @@
     }
 
     /**
+     * @deprecated Use
+     * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+     *
      * @hide
      */
+    @Deprecated
     @WorkerThread
     public Bundle getApplicationRestrictions(String packageName, UserHandle user) {
         try {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 19e759ca..947248a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10323,7 +10323,7 @@
 
         /**
          * If active unlock triggers on unlock intents, then also request active unlock on
-         * these wake-up reasons. See PowerManager.WakeReason for value mappings.
+         * these wake-up reasons. See {@link PowerManager.WakeReason} for value mappings.
          * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this
          * setting should be disabled, then this should be set to an empty string. A null value
          * will use the system default value (WAKE_REASON_UNFOLD_DEVICE).
@@ -10333,6 +10333,17 @@
                 "active_unlock_wakeups_considered_unlock_intents";
 
         /**
+         * If active unlock triggers and succeeds on these wakeups, force dismiss keyguard on
+         * these wake reasons. See {@link PowerManager#WakeReason} for value mappings.
+         * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this
+         * setting should be disabled, then this should be set to an empty string. A null value
+         * will use the system default value (WAKE_REASON_UNFOLD_DEVICE).
+         * @hide
+         */
+        public static final String ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD =
+                "active_unlock_wakeups_to_force_dismiss_keyguard";
+
+        /**
          * Whether the assist gesture should be enabled.
          *
          * @hide
@@ -18592,6 +18603,40 @@
              * @hide
              */
             public static final int ACCESSIBILITY_VIBRATION_WATCH_SPEED_VERY_FAST = 4;
+
+            /**
+             * The key to indicate the data migration status on device upgrade in Wear Services.
+             * @hide
+             */
+            public static final String UPGRADE_DATA_MIGRATION_STATUS =
+                    "upgrade_data_migration_status";
+
+            /**
+             * Constant indicating that the data migration is not needed.
+             *
+             * The value should be provided with setting name {@link
+             * #UPGRADE_DATA_MIGRATION_STATUS}.
+             * @hide
+             */
+            public static final int UPGRADE_DATA_MIGRATION_NOT_NEEDED = 0;
+
+            /**
+             * Constant indicating that the data migration is not yet finished.
+             *
+             * The value should be provided with setting name {@link
+             * #UPGRADE_DATA_MIGRATION_STATUS}.
+             * @hide
+             */
+            public static final int UPGRADE_DATA_MIGRATION_PENDING = 1;
+
+            /**
+             * Constant indicating that the data migration is finished.
+             *
+             * The value should be provided with setting name {@link
+             * #UPGRADE_DATA_MIGRATION_STATUS}.
+             * @hide
+             */
+            public static final int UPGRADE_DATA_MIGRATION_DONE = 2;
         }
     }
 
diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java
index b6c13c4..7e98bc7 100644
--- a/core/java/android/service/credentials/CredentialEntry.java
+++ b/core/java/android/service/credentials/CredentialEntry.java
@@ -107,6 +107,7 @@
     }
 
     private CredentialEntry(@NonNull Parcel in) {
+        requireNonNull(in, "parcel must not be null");
         mType = in.readString8();
         mSlice = in.readTypedObject(Slice.CREATOR);
         mBeginGetCredentialOption = in.readTypedObject(BeginGetCredentialOption.CREATOR);
diff --git a/core/java/android/service/credentials/CredentialProviderInfo.java b/core/java/android/service/credentials/CredentialProviderInfo.java
index 75ba525..b5464db 100644
--- a/core/java/android/service/credentials/CredentialProviderInfo.java
+++ b/core/java/android/service/credentials/CredentialProviderInfo.java
@@ -16,6 +16,8 @@
 
 package android.service.credentials;
 
+import static java.util.Objects.requireNonNull;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -112,10 +114,9 @@
                         "Provider is not a valid system provider: " + serviceInfo);
             }
         }
-
         mIsSystemProvider = isSystemProvider;
-        mContext = context;
-        mServiceInfo = serviceInfo;
+        mContext =  requireNonNull(context, "context must not be null");
+        mServiceInfo = requireNonNull(serviceInfo, "serviceInfo must not be null");
         mCapabilities = new ArrayList<>();
         mIcon = mServiceInfo.loadIcon(mContext.getPackageManager());
         mLabel =
@@ -300,6 +301,7 @@
             @NonNull Context context,
             @UserIdInt int userId,
             boolean disableSystemAppVerificationForTests) {
+        requireNonNull(context, "context must not be null");
         final List<CredentialProviderInfo> providerInfos = new ArrayList<>();
         for (ServiceInfo si :
                 getAvailableSystemServiceInfos(
@@ -381,6 +383,8 @@
             int userId,
             boolean disableSystemAppVerificationForTests,
             int providerFilter) {
+        requireNonNull(context, "context must not be null");
+
         // Get the device policy.
         PackagePolicy pp = getDeviceManagerPolicy(context);
 
diff --git a/core/java/android/service/credentials/GetCredentialRequest.java b/core/java/android/service/credentials/GetCredentialRequest.java
index 7cdccc6..4f13922 100644
--- a/core/java/android/service/credentials/GetCredentialRequest.java
+++ b/core/java/android/service/credentials/GetCredentialRequest.java
@@ -23,6 +23,8 @@
 
 import com.android.internal.util.AnnotationValidations;
 
+import java.util.Objects;
+
 /**
  * Request for getting user's credential from a given credential provider.
  *
@@ -43,8 +45,10 @@
 
     public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
             @NonNull CredentialOption credentialOption) {
-        this.mCallingAppInfo = callingAppInfo;
-        this.mCredentialOption = credentialOption;
+        this.mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
+                "callingAppInfo must not be null");
+        this.mCredentialOption = Objects.requireNonNull(credentialOption,
+                "credentialOption must not be null");
     }
 
     private GetCredentialRequest(@NonNull Parcel in) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 00161c0..d21e5df 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -60,7 +60,6 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
@@ -180,8 +179,6 @@
 
     private final ArrayList<Engine> mActiveEngines
             = new ArrayList<Engine>();
-    private Handler mBackgroundHandler;
-    private HandlerThread mBackgroundThread;
 
     static final class WallpaperCommand {
         String action;
@@ -201,6 +198,14 @@
      */
     public class Engine {
         IWallpaperEngineWrapper mIWallpaperEngine;
+        final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
+        final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
+
+        // 2D matrix [x][y] to represent a page of a portion of a window
+        EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
+        Bitmap mLastScreenshot;
+        int mLastWindowPage = -1;
+        private boolean mResetWindowPages;
 
         // Copies from mIWallpaperEngine.
         HandlerCaller mCaller;
@@ -261,27 +266,11 @@
 
         final Object mLock = new Object();
         boolean mOffsetMessageEnqueued;
-
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         float mPendingXOffset;
         float mPendingYOffset;
         float mPendingXOffsetStep;
         float mPendingYOffsetStep;
-
-        /**
-         * local color extraction related fields
-         * to be used by the background thread only (except the atomic boolean)
-         */
-        final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
-        final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
-        private long mLastProcessLocalColorsTimestamp;
-        private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
-        private int mPixelCopyCount = 0;
-        // 2D matrix [x][y] to represent a page of a portion of a window
-        EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
-        Bitmap mLastScreenshot;
-        private boolean mResetWindowPages;
-
         boolean mPendingSync;
         MotionEvent mPendingMove;
         boolean mIsInAmbientMode;
@@ -290,8 +279,12 @@
         private long mLastColorInvalidation;
         private final Runnable mNotifyColorsChanged = this::notifyColorsChanged;
 
+        // used to throttle processLocalColors
+        private long mLastProcessLocalColorsTimestamp;
+        private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
         private final Supplier<Long> mClockFunction;
         private final Handler mHandler;
+
         private Display mDisplay;
         private Context mDisplayContext;
         private int mDisplayState;
@@ -861,7 +854,7 @@
                             + "was not established.");
                 }
                 mResetWindowPages = true;
-                processLocalColors();
+                processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             } catch (RemoteException e) {
                 Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
             }
@@ -1399,7 +1392,7 @@
                             resetWindowPages();
                             mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
                                                    Integer.MAX_VALUE);
-                            processLocalColors();
+                            processLocalColors(mPendingXOffset, mPendingXOffsetStep);
                         }
                         reposition();
                         reportEngineShown(shouldWaitForEngineShown());
@@ -1543,7 +1536,7 @@
             if (!mDestroyed) {
                 mVisible = visible;
                 reportVisibility();
-                if (mReportedVisible) processLocalColors();
+                if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep);
             } else {
                 AnimationHandler.requestAnimatorsEnabled(visible, this);
             }
@@ -1627,44 +1620,31 @@
             }
 
             // setup local color extraction data
-            processLocalColors();
+            processLocalColors(xOffset, xOffsetStep);
         }
 
         /**
          * Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of
          * {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls.
          */
-        private void processLocalColors() {
+        private void processLocalColors(float xOffset, float xOffsetStep) {
             if (mProcessLocalColorsPending.compareAndSet(false, true)) {
                 final long now = mClockFunction.get();
                 final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp;
                 final long timeToWait = Math.max(0,
                         PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess);
 
-                mBackgroundHandler.postDelayed(() -> {
+                mHandler.postDelayed(() -> {
                     mLastProcessLocalColorsTimestamp = now + timeToWait;
                     mProcessLocalColorsPending.set(false);
-                    processLocalColorsInternal();
+                    processLocalColorsInternal(xOffset, xOffsetStep);
                 }, timeToWait);
             }
         }
 
-        private void processLocalColorsInternal() {
+        private void processLocalColorsInternal(float xOffset, float xOffsetStep) {
             // implemented by the wallpaper
             if (supportsLocalColorExtraction()) return;
-            if (!mBackgroundHandler.getLooper().isCurrentThread()) {
-                throw new IllegalStateException(
-                        "ProcessLocalColors should be called from the background thread");
-            }
-            float xOffset;
-            float xOffsetStep;
-            float wallpaperDimAmount;
-            synchronized (mLock) {
-                xOffset = mPendingXOffset;
-                xOffsetStep = mPendingXOffsetStep;
-                wallpaperDimAmount = mWallpaperDimAmount;
-            }
-
             if (DEBUG) {
                 Log.d(TAG, "processLocalColors " + xOffset + " of step "
                         + xOffsetStep);
@@ -1727,7 +1707,7 @@
                 xPage = mWindowPages.length - 1;
             }
             current = mWindowPages[xPage];
-            updatePage(current, xPage, xPages, wallpaperDimAmount);
+            updatePage(current, xPage, xPages, finalXOffsetStep);
             Trace.endSection();
         }
 
@@ -1747,21 +1727,16 @@
             }
         }
 
-        /**
-         * Must be called with the surface lock held.
-         * Must not be called if the surface is not valid.
-         * Will unlock the surface when done using it.
-         */
         void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages,
-                float wallpaperDimAmount) {
-
+                float xOffsetStep) {
             // in case the clock is zero, we start with negative time
             long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION;
             long lapsed = current - currentPage.getLastUpdateTime();
             // Always update the page when the last update time is <= 0
             // This is important especially when the device first boots
-            if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return;
-
+            if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) {
+                return;
+            }
             Surface surface = mSurfaceHolder.getSurface();
             if (!surface.isValid()) return;
             boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y;
@@ -1777,41 +1752,32 @@
             Bitmap screenShot = Bitmap.createBitmap(width, height,
                     Bitmap.Config.ARGB_8888);
             final Bitmap finalScreenShot = screenShot;
-            final String pixelCopySectionName = "WallpaperService#pixelCopy";
-            final int pixelCopyCount = mPixelCopyCount++;
-            Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount);
-            try {
-                PixelCopy.request(surface, screenShot, (res) -> {
-                    mSurfaceHolder.mSurfaceLock.unlock();
-                    Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount);
-                    if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
-                    if (res != PixelCopy.SUCCESS) {
-                        Bitmap lastBitmap = currentPage.getBitmap();
-                        // assign the last bitmap taken for now
-                        currentPage.setBitmap(mLastScreenshot);
-                        Bitmap lastScreenshot = mLastScreenshot;
-                        if (lastScreenshot != null && !lastScreenshot.isRecycled()
-                                && !Objects.equals(lastBitmap, lastScreenshot)) {
-                            updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
-                        }
-                    } else {
-                        mLastScreenshot = finalScreenShot;
-                        // going to hold this lock for a while
-                        currentPage.setBitmap(finalScreenShot);
-                        currentPage.setLastUpdateTime(current);
-                        updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
+            Trace.beginSection("WallpaperService#pixelCopy");
+            PixelCopy.request(surface, screenShot, (res) -> {
+                Trace.endSection();
+                if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
+                if (res != PixelCopy.SUCCESS) {
+                    Bitmap lastBitmap = currentPage.getBitmap();
+                    // assign the last bitmap taken for now
+                    currentPage.setBitmap(mLastScreenshot);
+                    Bitmap lastScreenshot = mLastScreenshot;
+                    if (lastScreenshot != null && !lastScreenshot.isRecycled()
+                            && !Objects.equals(lastBitmap, lastScreenshot)) {
+                        updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
                     }
-                }, mBackgroundHandler);
-            } catch (IllegalArgumentException e) {
-                // this can potentially happen if the surface is invalidated right between the
-                // surface.isValid() check and the PixelCopy operation.
-                // in this case, stop: we'll compute colors on the next processLocalColors call.
-                Log.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy");
-            }
+                } else {
+                    mLastScreenshot = finalScreenShot;
+                    // going to hold this lock for a while
+                    currentPage.setBitmap(finalScreenShot);
+                    currentPage.setLastUpdateTime(current);
+                    updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
+                }
+            }, mHandler);
+
         }
         // locked by the passed page
-        private void updatePageColors(
-                EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) {
+        private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages,
+                float xOffsetStep) {
             if (page.getBitmap() == null) return;
             Trace.beginSection("WallpaperService#updatePageColors");
             if (DEBUG) {
@@ -1834,7 +1800,7 @@
                     Log.e(TAG, "Error creating page local color bitmap", e);
                     continue;
                 }
-                WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount);
+                WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount);
                 target.recycle();
                 WallpaperColors currentColor = page.getColors(area);
 
@@ -1851,14 +1817,12 @@
                                 + " local color callback for area" + area + " for page " + pageIndx
                                 + " of " + numPages);
                     }
-                    mHandler.post(() -> {
-                        try {
-                            mConnection.onLocalWallpaperColorsChanged(area, color,
-                                    mDisplayContext.getDisplayId());
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
-                        }
-                    });
+                    try {
+                        mConnection.onLocalWallpaperColorsChanged(area, color,
+                                mDisplayContext.getDisplayId());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+                    }
                 }
             }
             Trace.endSection();
@@ -1888,6 +1852,7 @@
             if (supportsLocalColorExtraction()) return;
             if (!mResetWindowPages) return;
             mResetWindowPages = false;
+            mLastWindowPage = -1;
             for (int i = 0; i < mWindowPages.length; i++) {
                 mWindowPages[i].setLastUpdateTime(0L);
             }
@@ -1913,10 +1878,12 @@
             if (DEBUG) {
                 Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
             }
-            mBackgroundHandler.post(() -> {
+            mHandler.post(() -> {
                 mLocalColorsToAdd.addAll(regions);
-                processLocalColors();
+                processLocalColors(mPendingXOffset, mPendingYOffset);
             });
+
+
         }
 
         /**
@@ -1926,7 +1893,7 @@
          */
         public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
             if (supportsLocalColorExtraction()) return;
-            mBackgroundHandler.post(() -> {
+            mHandler.post(() -> {
                 float step = mPendingXOffsetStep;
                 mLocalColorsToAdd.removeAll(regions);
                 mLocalColorAreas.removeAll(regions);
@@ -2583,10 +2550,6 @@
     @Override
     public void onCreate() {
         Trace.beginSection("WPMS.onCreate");
-        final String localColorExtractorThreadName = "DefaultWallpaperLocalColorExtractor";
-        mBackgroundThread = new HandlerThread(localColorExtractorThreadName);
-        mBackgroundThread.start();
-        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
         super.onCreate();
         Trace.endSection();
     }
@@ -2599,7 +2562,6 @@
             mActiveEngines.get(i).detach();
         }
         mActiveEngines.clear();
-        mBackgroundThread.quitSafely();
         Trace.endSection();
     }
 
diff --git a/core/java/android/speech/IRecognitionListener.aidl b/core/java/android/speech/IRecognitionListener.aidl
index f7e459e..b924f35 100644
--- a/core/java/android/speech/IRecognitionListener.aidl
+++ b/core/java/android/speech/IRecognitionListener.aidl
@@ -96,6 +96,16 @@
     void onEndOfSegmentedSession();
 
     /**
+     * Called when the language detection (and switching) results are available.
+     *
+     * @param results a Bundle containing the identifiers of the most confidently detected language,
+     * the confidence level of the detection,
+     * the alternative locales for the most confidently detected language,
+     * and the results of the language switching.
+     */
+    void onLanguageDetection(in Bundle results);
+
+    /**
      * Reserved for adding future events.
      *
      * @param eventType the type of the occurred event
diff --git a/core/java/android/speech/RecognitionListener.java b/core/java/android/speech/RecognitionListener.java
index ee4a7d0..609f54e 100644
--- a/core/java/android/speech/RecognitionListener.java
+++ b/core/java/android/speech/RecognitionListener.java
@@ -117,6 +117,36 @@
     default void onEndOfSegmentedSession() {}
 
     /**
+     * Called when the language detection (and switching) results are available. This callback
+     * can be invoked on any number of occasions at any time between {@link #onBeginningOfSpeech()}
+     * and {@link #onEndOfSpeech()}, depending on the speech recognition service implementation.
+     *
+     * <p> To request language detection,
+     * use {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION}.
+     * <p> To request automatic language switching,
+     * use {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_SWITCH}.
+     *
+     * @param results the returned language detection (and switching) results.
+     *        <p> To retrieve the most confidently detected language IETF tag
+     *        (as defined by BCP 47, e.g., "en-US", "de-DE"),
+     *        use {@link Bundle#getString(String)}
+     *        with {@link SpeechRecognizer#DETECTED_LANGUAGE} as the parameter.
+     *        <p> To retrieve the language detection confidence level represented by a value
+     *        prefixed by {@code LANGUAGE_DETECTION_CONFIDENCE_LEVEL_} and
+     *        defined in {@link SpeechRecognizer}, use {@link Bundle#getInt(String)}
+     *        with {@link SpeechRecognizer#LANGUAGE_DETECTION_CONFIDENCE_LEVEL} as the parameter.
+     *        <p> To retrieve the alternative locales for the same language
+     *        retrieved by the key {@link SpeechRecognizer#DETECTED_LANGUAGE},
+     *        use {@link Bundle#getStringArrayList(String)}
+     *        with {@link SpeechRecognizer#TOP_LOCALE_ALTERNATIVES} as the parameter.
+     *        <p> To retrieve the language switching results represented by a value
+     *        prefixed by {@code LANGUAGE_SWITCH_RESULT_} and defined in {@link SpeechRecognizer},
+     *        use {@link Bundle#getInt(String)}
+     *        with {@link SpeechRecognizer#LANGUAGE_SWITCH_RESULT} as the parameter.
+     */
+    default void onLanguageDetection(@NonNull Bundle results) {}
+
+    /**
      * Reserved for adding future events.
      * 
      * @param eventType the type of the occurred event
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index d1d80a4..4ecec8f 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -651,6 +651,39 @@
         }
 
         /**
+         * The service should call this method when the language detection (and switching)
+         * results are available. This method can be called on any number of occasions
+         * at any time between {@link #beginningOfSpeech()} and {@link #endOfSpeech()},
+         * depending on the speech recognition service implementation.
+         *
+         * @param results the returned language detection (and switching) results.
+         *        <p> To retrieve the most confidently detected language IETF tag
+         *        (as defined by BCP 47, e.g., "en-US", "de-DE"),
+         *        use {@link Bundle#getString(String)}
+         *        with {@link SpeechRecognizer#DETECTED_LANGUAGE} as the parameter.
+         *        <p> To retrieve the language detection confidence level represented by a value
+         *        prefixed by {@code LANGUAGE_DETECTION_CONFIDENCE_LEVEL_} defined in
+         *        {@link SpeechRecognizer}, use {@link Bundle#getInt(String)} with
+         *        {@link SpeechRecognizer#LANGUAGE_DETECTION_CONFIDENCE_LEVEL} as the parameter.
+         *        <p> To retrieve the alternative locales for the same language
+         *        retrieved by the key {@link SpeechRecognizer#DETECTED_LANGUAGE},
+         *        use {@link Bundle#getStringArrayList(String)}
+         *        with {@link SpeechRecognizer#TOP_LOCALE_ALTERNATIVES} as the parameter.
+         *        <p> To retrieve the language switching results represented by a value
+         *        prefixed by {@code LANGUAGE_SWITCH_RESULT_}
+         *        and defined in {@link SpeechRecognizer}, use {@link Bundle#getInt(String)}
+         *        with {@link SpeechRecognizer#LANGUAGE_SWITCH_RESULT} as the parameter.
+         */
+        @SuppressLint("CallbackMethodName") // For consistency with existing methods.
+        public void languageDetection(@NonNull Bundle results) {
+            try {
+                mListener.onLanguageDetection(results);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Return the Linux uid assigned to the process that sent you the current transaction that
          * is being processed. This is obtained from {@link Binder#getCallingUid()}.
          */
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 7127fa1..118d028 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -572,4 +572,85 @@
      */
     public static final String EXTRA_REQUEST_WORD_CONFIDENCE =
             "android.speech.extra.REQUEST_WORD_CONFIDENCE";
+
+    /**
+     * Optional boolean indicating whether to enable language detection. When enabled, the
+     * recognizer will consistently identify the language of the current spoken utterance and
+     * provide that info via {@link RecognitionListener#onLanguageDetection(Bundle)}.
+     *
+     * <p> Depending on the recognizer implementation, this flag may have no effect.
+     */
+    public static final String EXTRA_ENABLE_LANGUAGE_DETECTION =
+            "android.speech.extra.ENABLE_LANGUAGE_DETECTION";
+
+    /**
+     * Optional list of IETF language tags (as defined by BCP 47, e.g. "en-US", "de-DE").
+     * This extra is to be used with {@link #EXTRA_ENABLE_LANGUAGE_DETECTION}.
+     * If set, the recognizer will constrain the language detection output
+     * to this list of languages, potentially improving detection accuracy.
+     */
+    public static final String EXTRA_LANGUAGE_DETECTION_ALLOWED_LANGUAGES =
+            "android.speech.extra.LANGUAGE_DETECTION_ALLOWED_LANGUAGES";
+
+    /**
+     * Optional string to enable automatic switching to the language being spoken with
+     * the desired sensitivity level, instead of being restricted to a single language.
+     * The corresponding language models must be downloaded to support the switch.
+     * Otherwise, the recognizer will report an error on a switch failure. The recognizer
+     * provides the switch results via {@link RecognitionListener#onLanguageDetection(Bundle)}.
+     *
+     * <p> Since detection is a necessary requirement for the language switching,
+     * setting this value implicitly enables {@link #EXTRA_ENABLE_LANGUAGE_DETECTION}.
+     *
+     * <p> Depending on the recognizer implementation, this value may have no effect.
+     *
+     * @see #LANGUAGE_SWITCH_HIGH_PRECISION
+     * @see #LANGUAGE_SWITCH_BALANCED
+     * @see #LANGUAGE_SWITCH_QUICK_RESPONSE
+     */
+    public static final String EXTRA_ENABLE_LANGUAGE_SWITCH =
+            "android.speech.extra.ENABLE_LANGUAGE_SWITCH";
+
+    /**
+     * A value to use for {@link #EXTRA_ENABLE_LANGUAGE_SWITCH}.
+     *
+     * <p> Enables language switch only when a new language is detected as
+     * {@link SpeechRecognizer#LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT},
+     * which means the service may wait for longer before switching.
+     *
+     * @see #EXTRA_ENABLE_LANGUAGE_SWITCH
+     */
+    public static final String LANGUAGE_SWITCH_HIGH_PRECISION = "high_precision";
+
+    /**
+     * A value to use for {@link #EXTRA_ENABLE_LANGUAGE_SWITCH}.
+     *
+     * <p> Enables language switch only when a new language is detected as at least
+     * {@link SpeechRecognizer#LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT}, which means
+     * the service is balancing between detecting a new language confidently and switching early.
+     *
+     * @see #EXTRA_ENABLE_LANGUAGE_SWITCH
+     */
+    public static final String LANGUAGE_SWITCH_BALANCED = "balanced";
+
+    /**
+     * A value to use for {@link #EXTRA_ENABLE_LANGUAGE_SWITCH}.
+     *
+     * <p> Enables language switch only when a new language is detected as at least
+     * {@link SpeechRecognizer#LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT},
+     * which means the service should switch at the earliest moment possible.
+     *
+     * @see #EXTRA_ENABLE_LANGUAGE_SWITCH
+     */
+    public static final String LANGUAGE_SWITCH_QUICK_RESPONSE = "quick_response";
+
+    /**
+     * Optional list of IETF language tags (as defined by BCP 47, e.g. "en-US", "de-DE"). This extra
+     * is to be used with {@link #EXTRA_ENABLE_LANGUAGE_SWITCH}. If set, the recognizer will apply
+     * the auto switch only to these languages, even if the speech models of other languages also
+     * exist. The corresponding language models must be downloaded to support the switch.
+     * Otherwise, the recognizer will report an error on a switch failure.
+     */
+    public static final String EXTRA_LANGUAGE_SWITCH_ALLOWED_LANGUAGES =
+            "android.speech.extra.LANGUAGE_SWITCH_ALLOWED_LANGUAGES";
 }
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index dce72f5..76eb09e 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -80,7 +80,7 @@
      * recognition results, where the first element is the most likely candidate.
      */
     public static final String RESULTS_RECOGNITION = "results_recognition";
-    
+
     /**
      * Key used to retrieve a float array from the {@link Bundle} passed to the
      * {@link RecognitionListener#onResults(Bundle)} and
@@ -124,6 +124,101 @@
     public static final String RECOGNITION_PARTS = "recognition_parts";
 
     /**
+     * Key used to retrieve a {@link String} representation of the IETF language tag (as defined by
+     * BCP 47, e.g., "en-US", "de-DE") of the detected language of the most recent audio chunk.
+     *
+     * <p> This info is returned to the client in the {@link Bundle} passed to
+     * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
+     * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set. Additionally, if
+     * {@link RecognizerIntent#EXTRA_LANGUAGE_DETECTION_ALLOWED_LANGUAGES} are listed,
+     * the detected language is constrained to be one from the list.
+     */
+    public static final String DETECTED_LANGUAGE = "detected_language";
+
+    /**
+     * Key used to retrieve the level of confidence of the detected language
+     * of the most recent audio chunk,
+     * represented by an {@code int} value prefixed by {@code LANGUAGE_DETECTION_CONFIDENCE_LEVEL_}.
+     *
+     * <p> This info is returned to the client in the {@link Bundle} passed to
+     * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
+     * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set.
+     */
+    public static final String LANGUAGE_DETECTION_CONFIDENCE_LEVEL =
+            "language_detection_confidence_level";
+
+    /**
+     * The level of language detection confidence.
+     *
+     * @hide
+     */
+    @Documented
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"LANGUAGE_DETECTION_CONFIDENCE_LEVEL_"}, value = {
+            LANGUAGE_DETECTION_CONFIDENCE_LEVEL_UNKNOWN,
+            LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT,
+            LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT,
+            LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT
+    })
+    public @interface LanguageDetectionConfidenceLevel {}
+
+    public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_UNKNOWN = 0;
+    public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_NOT_CONFIDENT = 1;
+    public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_CONFIDENT = 2;
+    public static final int LANGUAGE_DETECTION_CONFIDENCE_LEVEL_HIGHLY_CONFIDENT = 3;
+
+    /**
+     * Key used to retrieve an ArrayList&lt;{@link String}&gt; containing representations of the
+     * IETF language tags (as defined by BCP 47, e.g., "en-US", "en-UK") denoting the alternative
+     * locales for the same language retrieved by the key {@link #DETECTED_LANGUAGE}.
+     *
+     * This info is returned to the client in the {@link Bundle} passed to
+     * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
+     * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_DETECTION} is set.
+     */
+    public static final String TOP_LOCALE_ALTERNATIVES = "top_locale_alternatives";
+
+    /**
+     * Key used to retrieve the result of the language switch of the most recent audio chunk,
+     * represented by an {@code int} value prefixed by {@code LANGUAGE_SWITCH_}.
+     *
+     * <p> This info is returned to the client in the {@link Bundle} passed to the
+     * {@link RecognitionListener#onLanguageDetection(Bundle)} only if
+     * {@link RecognizerIntent#EXTRA_ENABLE_LANGUAGE_SWITCH} is set.
+     */
+    public static final String LANGUAGE_SWITCH_RESULT = "language_switch_result";
+
+    /**
+     * The result of the language switch.
+     *
+     * @hide
+     */
+    @Documented
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"LANGUAGE_SWITCH_RESULT_"}, value = {
+            LANGUAGE_SWITCH_RESULT_NOT_ATTEMPTED,
+            LANGUAGE_SWITCH_RESULT_SUCCEEDED,
+            LANGUAGE_SWITCH_RESULT_FAILED,
+            LANGUAGE_SWITCH_RESULT_SKIPPED_NO_MODEL
+    })
+    public @interface LanguageSwitchResult {}
+
+    /** Switch not attempted. */
+    public static final int LANGUAGE_SWITCH_RESULT_NOT_ATTEMPTED = 0;
+
+    /** Switch attempted and succeeded. */
+    public static final int LANGUAGE_SWITCH_RESULT_SUCCEEDED = 1;
+
+    /** Switch attempted and failed. */
+    public static final int LANGUAGE_SWITCH_RESULT_FAILED = 2;
+
+    /**
+     * Switch skipped because the language model is missing
+     * or the language is not allowlisted for auto switch.
+     */
+    public static final int LANGUAGE_SWITCH_RESULT_SKIPPED_NO_MODEL = 3;
+
+    /**
      * The reason speech recognition failed.
      *
      * @hide
@@ -963,6 +1058,7 @@
         private static final int MSG_ON_EVENT = 9;
         private static final int MSG_SEGMENT_RESULTS = 10;
         private static final int MSG_SEGMENT_END_SESSION = 11;
+        private static final int MSG_LANGUAGE_DETECTION = 12;
 
         private final Handler mInternalHandler = new Handler(Looper.getMainLooper()) {
             @Override
@@ -1004,6 +1100,9 @@
                     case MSG_SEGMENT_END_SESSION:
                         mInternalListener.onEndOfSegmentedSession();
                         break;
+                    case MSG_LANGUAGE_DETECTION:
+                        mInternalListener.onLanguageDetection((Bundle) msg.obj);
+                        break;
                 }
             }
         };
@@ -1048,6 +1147,10 @@
             Message.obtain(mInternalHandler, MSG_SEGMENT_END_SESSION).sendToTarget();
         }
 
+        public void onLanguageDetection(final Bundle results) {
+            Message.obtain(mInternalHandler, MSG_LANGUAGE_DETECTION, results).sendToTarget();
+        }
+
         public void onEvent(final int eventType, final Bundle params) {
             Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
                     .sendToTarget();
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 18fdb83..f6309f2 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -32,6 +32,8 @@
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
 import android.telephony.TelephonyManager.DataEnabledReason;
+import android.telephony.TelephonyManager.EmergencyCallbackModeStopReason;
+import android.telephony.TelephonyManager.EmergencyCallbackModeType;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.MediaQualityStatus;
@@ -1304,8 +1306,6 @@
         // default implementation empty
     }
 
-
-
     /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
@@ -1669,6 +1669,18 @@
         public final void onMediaQualityStatusChanged(MediaQualityStatus mediaQualityStatus) {
             // not support. Can't override. Use TelephonyCallback.
         }
+
+        /** @hide */
+        public final void onCallBackModeStarted(
+                @TelephonyManager.EmergencyCallbackModeType int type) {
+            // not support. Can't override. Use TelephonyCallback.
+        }
+
+        /** @hide */
+        public final void onCallBackModeStopped(@EmergencyCallbackModeType int type,
+                @EmergencyCallbackModeStopReason int reason) {
+            // not support. Can't override. Use TelephonyCallback.
+        }
     }
 
     private void log(String s) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index f8df668..7ada058 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -612,6 +612,20 @@
     @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int EVENT_MEDIA_QUALITY_STATUS_CHANGED = 39;
 
+
+    /**
+     * Event for changes to the Emergency callback mode
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
+     *
+     * @see EmergencyCallbackModeListener#onCallbackModeStarted(int)
+     * @see EmergencyCallbackModeListener#onCallbackModeStopped(int, int)
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int EVENT_EMERGENCY_CALLBACK_MODE_CHANGED = 40;
+
     /**
      * @hide
      */
@@ -654,7 +668,8 @@
             EVENT_LEGACY_CALL_STATE_CHANGED,
             EVENT_LINK_CAPACITY_ESTIMATE_CHANGED,
             EVENT_TRIGGER_NOTIFY_ANBR,
-            EVENT_MEDIA_QUALITY_STATUS_CHANGED
+            EVENT_MEDIA_QUALITY_STATUS_CHANGED,
+            EVENT_EMERGENCY_CALLBACK_MODE_CHANGED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TelephonyEvent {
@@ -1568,6 +1583,53 @@
     }
 
     /**
+     * Interface for emergency callback mode listener.
+     *
+     * @hide
+     */
+    public interface EmergencyCallbackModeListener {
+        /**
+         * Indicates that Callback Mode has been started.
+         * <p>
+         * This method will be called when an emergency sms/emergency call is sent
+         * and the callback mode is supported by the carrier.
+         * If an emergency SMS is transmitted during callback mode for SMS, this API will be called
+         * once again with TelephonyManager#EMERGENCY_CALLBACK_MODE_SMS.
+         *
+         * @param type for callback mode entry
+         *             See {@link TelephonyManager.EmergencyCallbackModeType}.
+         * @see TelephonyManager#EMERGENCY_CALLBACK_MODE_CALL
+         * @see TelephonyManager#EMERGENCY_CALLBACK_MODE_SMS
+         */
+        @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+        void onCallBackModeStarted(@TelephonyManager.EmergencyCallbackModeType int type);
+
+        /**
+         * Indicates that Callback Mode has been stopped.
+         * <p>
+         * This method will be called when the callback mode timer expires or when
+         * a normal call/SMS is sent
+         *
+         * @param type for callback mode entry
+         * @see TelephonyManager#EMERGENCY_CALLBACK_MODE_CALL
+         * @see TelephonyManager#EMERGENCY_CALLBACK_MODE_SMS
+         *
+         * @param reason for changing callback mode
+         *
+         * @see TelephonyManager#STOP_REASON_UNKNOWN
+         * @see TelephonyManager#STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED
+         * @see TelephonyManager#STOP_REASON_NORMAL_SMS_SENT
+         * @see TelephonyManager#STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED
+         * @see TelephonyManager#STOP_REASON_EMERGENCY_SMS_SENT
+         * @see TelephonyManager#STOP_REASON_TIMER_EXPIRED
+         * @see TelephonyManager#STOP_REASON_USER_ACTION
+         */
+        @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+        void onCallBackModeStopped(@TelephonyManager.EmergencyCallbackModeType int type,
+                @TelephonyManager.EmergencyCallbackModeStopReason int reason);
+    }
+
+    /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
      * <p>
@@ -1935,5 +1997,27 @@
                     () -> mExecutor.execute(() -> listener.onMediaQualityStatusChanged(
                             mediaQualityStatus)));
         }
+
+        public void onCallBackModeStarted(@TelephonyManager.EmergencyCallbackModeType int type) {
+            EmergencyCallbackModeListener listener =
+                    (EmergencyCallbackModeListener) mTelephonyCallbackWeakRef.get();
+            Log.d(LOG_TAG, "onCallBackModeStarted:type=" + type + ", listener=" + listener);
+            if (listener == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> listener.onCallBackModeStarted(type)));
+        }
+
+        public void onCallBackModeStopped(@TelephonyManager.EmergencyCallbackModeType int type,
+                @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
+            EmergencyCallbackModeListener listener =
+                    (EmergencyCallbackModeListener) mTelephonyCallbackWeakRef.get();
+            Log.d(LOG_TAG, "onCallBackModeStopped:type=" + type
+                    + ", reason=" + reason + ", listener=" + listener);
+            if (listener == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> listener.onCallBackModeStopped(type, reason)));
+        }
     }
 }
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 8b24e07..f648ad4 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1113,6 +1113,11 @@
             eventList.add(TelephonyCallback.EVENT_MEDIA_QUALITY_STATUS_CHANGED);
         }
 
+        if (telephonyCallback instanceof TelephonyCallback.EmergencyCallbackModeListener) {
+            eventList.add(TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
+        }
+
+
         return eventList;
     }
 
@@ -1539,4 +1544,43 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Notify Callback Mode has been started.
+     * @param phoneId Sender phone ID.
+     * @param subId Sender subscription ID.
+     * @param type for callback mode entry.
+     *             See {@link TelephonyManager.EmergencyCallbackModeType}.
+     */
+    public void notifyCallBackModeStarted(int phoneId, int subId,
+            @TelephonyManager.EmergencyCallbackModeType int type) {
+        try {
+            Log.d(TAG, "notifyCallBackModeStarted:type=" + type);
+            sRegistry.notifyCallbackModeStarted(phoneId, subId, type);
+        } catch (RemoteException ex) {
+            // system process is dead
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Notify Callback Mode has been stopped.
+     * @param phoneId Sender phone ID.
+     * @param subId Sender subscription ID.
+     * @param type for callback mode entry.
+     *             See {@link TelephonyManager.EmergencyCallbackModeType}.
+     * @param reason for changing callback mode.
+     *             See {@link TelephonyManager.EmergencyCallbackModeStopReason}.
+     */
+    public void notifyCallbackModeStopped(int phoneId, int subId,
+            @TelephonyManager.EmergencyCallbackModeType int type,
+            @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
+        try {
+            Log.d(TAG, "notifyCallbackModeStopped:type=" + type + ", reason=" + reason);
+            sRegistry.notifyCallbackModeStopped(phoneId, subId, type, reason);
+        } catch (RemoteException ex) {
+            // system process is dead
+            throw ex.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c2afd20..7d18bf0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10199,6 +10199,7 @@
             setNotifiedContentCaptureAppeared();
 
             if (ai != null) {
+                makeParentImportantAndNotifyAppearedEventIfNeed();
                 ai.delayNotifyContentCaptureEvent(session, this, appeared);
             } else {
                 if (DEBUG_CONTENT_CAPTURE) {
@@ -10226,6 +10227,22 @@
         }
     }
 
+    private void makeParentImportantAndNotifyAppearedEventIfNeed() {
+        // If view sent the appeared event to Content Capture, Content Capture also
+        // would like to receive its parents' appeared events. So checks its parents
+        // whether the appeared event is sent or not. If not, send the appeared event.
+        final ViewParent parent = getParent();
+        if (parent instanceof View) {
+            View p = ((View) parent);
+            if (p.getNotifiedContentCaptureAppeared()) {
+                return;
+            }
+            // Set important for content capture in the cache.
+            p.mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
+            p.notifyAppearedOrDisappearedForContentCaptureIfNeeded(/* appeared */ true);
+        }
+    }
+
     private void setNotifiedContentCaptureAppeared() {
         mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
         mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 4576d62..247e026 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -832,6 +832,8 @@
 
     private static final int BOOLEAN_PROPERTY_REQUEST_INITIAL_ACCESSIBILITY_FOCUS = 1 << 24;
 
+    private static final int BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH = 1 << 25;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2595,6 +2597,53 @@
     }
 
     /**
+     * Gets whether this node is one of the candidates that wants touch interaction within its
+     * screen bounds to bypass the touch exploration and go straight to the underlying view
+     * hierarchy.
+     *
+     * <p>
+     * {@link android.accessibilityservice.AccessibilityService} could aggregate the {@link
+     * #getBoundsInScreen()} that has request touch passthrough, and/or doing complex calculation
+     * with other views that doesn't request touch passthrough, and call {@link
+     * AccessibilityService#setTouchExplorationPassthroughRegion(int, Region)} to bypass the touch
+     * interactions to the underlying views within the region.
+     * </p>
+     *
+     * @return True if the node wants touch interaction within its screen bounds to bypass touch
+     * exploration and go straight to the underlying view hierarchy; false otherwise.
+     */
+    public boolean hasRequestTouchPassthrough() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH);
+    }
+
+    /**
+     * Sets whether this node wants touch interaction within its screen bounds to bypass touch
+     * exploration and go straight to the underlying view hierarchy.
+     * <p>
+     *   <strong>Note:</strong> This property allows the
+     *   {@link android.accessibilityservice.AccessibilityService} to calculate the
+     *   aggregated touch passthrough region. App developers need to ensure that the
+     *   {@link #getBoundsInScreen()} of
+     *   the node align with the region they want touchable, and that child nodes overlapping these
+     *   bounds may cause that region to be reduced.
+     * </p>
+     *
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param touchPassthrough True if the node wants touch interaction within its screen bounds
+     *                         to bypass touch exploration and go straight to the underlying view
+     *                         hierarchy.
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setRequestTouchPassthrough(boolean touchPassthrough) {
+        setBooleanProperty(BOOLEAN_PROPERTY_REQUEST_TOUCH_PASSTHROUGH, touchPassthrough);
+    }
+
+    /**
      * If this node represents a visually distinct region of the screen that may update separately
      * from the rest of the window, it is considered a pane. Set the pane title to indicate that
      * the node is a pane, and to provide a title for it.
diff --git a/core/java/com/android/internal/expresslog/Counter.java b/core/java/com/android/internal/expresslog/Counter.java
index cc37c69..afdbdc8 100644
--- a/core/java/com/android/internal/expresslog/Counter.java
+++ b/core/java/com/android/internal/expresslog/Counter.java
@@ -28,6 +28,7 @@
 
     /**
      * Increments Telemetry Express Counter metric by 1
+     * @param metricId to log, no-op if metricId is not defined in the TeX catalog
      * @hide
      */
     public static void logIncrement(@NonNull String metricId) {
@@ -36,6 +37,8 @@
 
     /**
      * Increments Telemetry Express Counter metric by arbitrary value
+     * @param metricId to log, no-op if metricId is not defined in the TeX catalog
+     * @param amount to increment counter
      * @hide
      */
     public static void logIncrement(@NonNull String metricId, long amount) {
diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java
index db70cac..2f3b662 100644
--- a/core/java/com/android/internal/expresslog/Histogram.java
+++ b/core/java/com/android/internal/expresslog/Histogram.java
@@ -26,6 +26,12 @@
     private final long mMetricIdHash;
     private final BinOptions mBinOptions;
 
+    /**
+     * Creates Histogram metric logging wrapper
+     * @param metricId to log, logging will be no-op if metricId is not defined in the TeX catalog
+     * @param binOptions to calculate bin index for samples
+     * @hide
+     */
     public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) {
         mMetricIdHash = Utils.hashString(metricId);
         mBinOptions = binOptions;
@@ -33,7 +39,7 @@
 
     /**
      * Logs increment sample count for automatically calculated bin
-     *
+     * @param sample value
      * @hide
      */
     public void logSample(float sample) {
@@ -46,17 +52,16 @@
     public interface BinOptions {
         /**
          * Returns bins count to be used by a histogram
-         *
          * @return bins count used to initialize Options, including overflow & underflow bins
          * @hide
          */
         int getBinsCount();
 
         /**
-         * @return zero based index
-         * Calculates bin index for the input sample value
+         * Returns bin index for the input sample value
          * index == 0 stands for underflow
          * index == getBinsCount() - 1 stands for overflow
+         * @return zero based index
          * @hide
          */
         int getBinForSample(float sample);
@@ -70,6 +75,17 @@
         private final float mExclusiveMaxValue;
         private final float mBinSize;
 
+        /**
+         * Creates otpions for uniform (linear) sized bins
+         * @param binCount amount of histogram bins. 2 bin indexes will be calculated
+         *                 automatically to represent undeflow & overflow bins
+         * @param minValue is included in the first bin, values less than minValue
+         *                 go to underflow bin
+         * @param exclusiveMaxValue is included in the overflow bucket. For accurate
+                                    measure up to kMax, then exclusiveMaxValue
+         *                          should be set to kMax + 1
+         * @hide
+         */
         public UniformOptions(int binCount, float minValue, float exclusiveMaxValue) {
             if (binCount < 1) {
                 throw new IllegalArgumentException("Bin count should be positive number");
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 63785f2..134a917 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -139,15 +139,6 @@
     }
 
     @Override
-    public boolean isDeviceContext() {
-        Context context = mContext.get();
-        if (context != null) {
-            return context.isDeviceContext();
-        }
-        return false;
-    }
-
-    @Override
     public boolean isConfigurationContext() {
         Context context = mContext.get();
         if (context != null) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 1875ecf..a14e9a7 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2507,12 +2507,23 @@
         final boolean targetPreQ = targetSdk < Build.VERSION_CODES.Q;
 
         if (!mForcedStatusBarColor) {
-            mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
+            mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, Color.BLACK);
         }
         if (!mForcedNavigationBarColor) {
-            mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
+            final int navBarCompatibleColor = context.getColor(R.color.navigation_bar_compatible);
+            final int navBarDefaultColor = context.getColor(R.color.navigation_bar_default);
+            final int navBarColor = a.getColor(R.styleable.Window_navigationBarColor,
+                    navBarDefaultColor);
+
+            mNavigationBarColor =
+                    navBarColor == navBarDefaultColor
+                            && !context.getResources().getBoolean(
+                                    R.bool.config_navBarDefaultTransparent)
+                    ? navBarCompatibleColor
+                    : navBarColor;
+
             mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
-                    0x00000000);
+                    Color.TRANSPARENT);
         }
         if (!targetPreQ) {
             mEnsureStatusBarContrastWhenTransparent = a.getBoolean(
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 3e9f1cb..03cfd4f 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -78,4 +78,6 @@
     void onAllowedNetworkTypesChanged(in int reason, in long allowedNetworkType);
     void onLinkCapacityEstimateChanged(in List<LinkCapacityEstimate> linkCapacityEstimateList);
     void onMediaQualityStatusChanged(in MediaQualityStatus mediaQualityStatus);
+    void onCallBackModeStarted(int type);
+    void onCallBackModeStopped(int type, int reason);
 }
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index fd9239d..8a02dd6 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -117,4 +117,7 @@
             String pkg, String featureId);
     void removeCarrierConfigChangeListener(ICarrierConfigChangeListener listener, String pkg);
     void notifyCarrierConfigChanged(int phoneId, int subId, int carrierId, int specificCarrierId);
+
+    void notifyCallbackModeStarted(int phoneId, int subId, int type);
+    void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason);
 }
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 1910331..b1dab85 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -18,29 +18,25 @@
 
 #define LOG_TAG "AudioRecord-JNI"
 
-#include <inttypes.h>
-#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include "core_jni_helpers.h"
-
-#include <utils/Log.h>
-#include <media/AudioRecord.h>
-#include <media/MicrophoneInfo.h>
-#include <vector>
-
 #include <android/content/AttributionSourceState.h>
 #include <android_os_Parcel.h>
-
+#include <inttypes.h>
+#include <jni.h>
+#include <media/AudioRecord.h>
+#include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
+
+#include <vector>
 
 #include "android_media_AudioAttributes.h"
-#include "android_media_AudioFormat.h"
 #include "android_media_AudioErrors.h"
+#include "android_media_AudioFormat.h"
 #include "android_media_DeviceCallback.h"
 #include "android_media_JNIUtils.h"
 #include "android_media_MediaMetricsJNI.h"
 #include "android_media_MicrophoneInfo.h"
-
+#include "core_jni_helpers.h"
 
 // ----------------------------------------------------------------------------
 
@@ -719,7 +715,7 @@
     }
 
     jint jStatus = AUDIO_JAVA_SUCCESS;
-    std::vector<media::MicrophoneInfo> activeMicrophones;
+    std::vector<media::MicrophoneInfoFw> activeMicrophones;
     status_t status = lpRecorder->getActiveMicrophones(&activeMicrophones);
     if (status != NO_ERROR) {
         ALOGE_IF(status != NO_ERROR, "AudioRecord::getActiveMicrophones error %d", status);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 75f8402..8ba4eed 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -28,7 +28,6 @@
 #include <media/AudioContainers.h>
 #include <media/AudioPolicy.h>
 #include <media/AudioSystem.h>
-#include <media/MicrophoneInfo.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <system/audio.h>
@@ -2424,7 +2423,7 @@
     }
 
     jint jStatus;
-    std::vector<media::MicrophoneInfo> microphones;
+    std::vector<media::MicrophoneInfoFw> microphones;
     status_t status = AudioSystem::getMicrophones(&microphones);
     if (status != NO_ERROR) {
         ALOGE("AudioSystem::getMicrophones error %d", status);
diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp
index b70190f..65e30d8 100644
--- a/core/jni/android_media_MicrophoneInfo.cpp
+++ b/core/jni/android_media_MicrophoneInfo.cpp
@@ -15,6 +15,9 @@
  */
 
 #include "android_media_MicrophoneInfo.h"
+
+#include <media/AidlConversion.h>
+
 #include "android_media_AudioErrors.h"
 #include "core_jni_helpers.h"
 
@@ -46,8 +49,17 @@
 namespace android {
 
 jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
-        const media::MicrophoneInfo *microphoneInfo)
-{
+                                     const media::MicrophoneInfoFw *microphoneInfo) {
+    // The Java object uses the same enum values as the C enum values, which are
+    // generated from HIDL. Thus, we can use the legacy structure as the source for
+    // creating the Java object. Once we start removing legacy types, we can add
+    // direct converters between Java and AIDL, this will eliminate the need
+    // to have JNI code like this one.
+    auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(*microphoneInfo);
+    if (!conv.ok()) {
+        return nativeToJavaStatus(conv.error());
+    }
+
     jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
     jstring jDeviceId = NULL;
     jstring jAddress = NULL;
@@ -56,36 +68,23 @@
     jobject jFrequencyResponses = NULL;
     jobject jChannelMappings = NULL;
 
-    jDeviceId = env->NewStringUTF(microphoneInfo->getDeviceId().c_str());
-    jAddress = env->NewStringUTF(microphoneInfo->getAddress().c_str());
-    if (microphoneInfo->getGeometricLocation().size() != 3 ||
-            microphoneInfo->getOrientation().size() != 3) {
-        jStatus = nativeToJavaStatus(BAD_VALUE);
-        goto exit;
-    }
-    jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass,
-                                        gMicrophoneInfoCoordinateCstor,
-                                        microphoneInfo->getGeometricLocation()[0],
-                                        microphoneInfo->getGeometricLocation()[1],
-                                        microphoneInfo->getGeometricLocation()[2]);
-    jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass,
-                                  gMicrophoneInfoCoordinateCstor,
-                                  microphoneInfo->getOrientation()[0],
-                                  microphoneInfo->getOrientation()[1],
-                                  microphoneInfo->getOrientation()[2]);
+    const auto &micInfo = conv.value();
+    jDeviceId = env->NewStringUTF(micInfo.device_id);
+    jAddress = env->NewStringUTF(micInfo.address);
+    jGeometricLocation =
+            env->NewObject(gMicrophoneInfoCoordinateClass, gMicrophoneInfoCoordinateCstor,
+                           micInfo.geometric_location.x, micInfo.geometric_location.y,
+                           micInfo.geometric_location.z);
+    jOrientation =
+            env->NewObject(gMicrophoneInfoCoordinateClass, gMicrophoneInfoCoordinateCstor,
+                           micInfo.orientation.x, micInfo.orientation.y, micInfo.orientation.z);
     // Create a list of Pair for frequency response.
-    if (microphoneInfo->getFrequencyResponses().size() != 2 ||
-            microphoneInfo->getFrequencyResponses()[0].size() !=
-                    microphoneInfo->getFrequencyResponses()[1].size()) {
-        jStatus = nativeToJavaStatus(BAD_VALUE);
-        goto exit;
-    }
     jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor);
-    for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) {
-        jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor,
-                                            microphoneInfo->getFrequencyResponses()[0][i]);
-        jobject jResponse = env->NewObject(gFloatClass, gFloatCstor,
-                                          microphoneInfo->getFrequencyResponses()[1][i]);
+    for (size_t i = 0; i < micInfo.num_frequency_responses; i++) {
+        jobject jFrequency =
+                env->NewObject(gFloatClass, gFloatCstor, micInfo.frequency_responses[0][i]);
+        jobject jResponse =
+                env->NewObject(gFloatClass, gFloatCstor, micInfo.frequency_responses[1][i]);
         jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse);
         env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse);
         env->DeleteLocalRef(jFrequency);
@@ -93,13 +92,9 @@
         env->DeleteLocalRef(jFrequencyResponse);
     }
     // Create a list of Pair for channel mapping.
-    if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) {
-        jStatus = nativeToJavaStatus(BAD_VALUE);
-        goto exit;
-    }
-    jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
-    for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) {
-        int channelMappingType = microphoneInfo->getChannelMapping()[i];
+    const auto &channelMapping = micInfo.channel_mapping;
+    for (size_t i = 0; i < std::size(channelMapping); i++) {
+        int channelMappingType = channelMapping[i];
         if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
             jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i);
             jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor,
@@ -113,18 +108,11 @@
         }
     }
     *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId,
-                                      microphoneInfo->getType(), jAddress,
-                                      microphoneInfo->getDeviceLocation(),
-                                      microphoneInfo->getDeviceGroup(),
-                                      microphoneInfo->getIndexInTheGroup(),
-                                      jGeometricLocation, jOrientation,
-                                      jFrequencyResponses, jChannelMappings,
-                                      microphoneInfo->getSensitivity(),
-                                      microphoneInfo->getMaxSpl(),
-                                      microphoneInfo->getMinSpl(),
-                                      microphoneInfo->getDirectionality());
+                                      micInfo.device, jAddress, micInfo.location, micInfo.group,
+                                      micInfo.index_in_the_group, jGeometricLocation, jOrientation,
+                                      jFrequencyResponses, jChannelMappings, micInfo.sensitivity,
+                                      micInfo.max_spl, micInfo.min_spl, micInfo.directionality);
 
-exit:
     if (jDeviceId != NULL) {
         env->DeleteLocalRef(jDeviceId);
     }
@@ -145,7 +133,6 @@
     }
     return jStatus;
 }
-
 }
 
 int register_android_media_MicrophoneInfo(JNIEnv *env)
diff --git a/core/jni/android_media_MicrophoneInfo.h b/core/jni/android_media_MicrophoneInfo.h
index 241b6d0..dc531c6 100644
--- a/core/jni/android_media_MicrophoneInfo.h
+++ b/core/jni/android_media_MicrophoneInfo.h
@@ -17,8 +17,8 @@
 #ifndef ANDROID_MEDIA_MICROPHONEINFO_H
 #define ANDROID_MEDIA_MICROPHONEINFO_H
 
+#include <android/media/MicrophoneInfoFw.h>
 #include <system/audio.h>
-#include <media/MicrophoneInfo.h>
 
 #include "jni.h"
 
@@ -27,7 +27,7 @@
 // Conversion from C++ MicrophoneInfo object to Java MicrophoneInfo object
 
 extern jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
-        const media::MicrophoneInfo *microphoneInfo);
+                                            const media::MicrophoneInfoFw *microphoneInfo);
 } // namespace android
 
-#endif
\ No newline at end of file
+#endif
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a4818c7..830ef46 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -109,6 +109,7 @@
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
     <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_ENABLED_CHANGED" />
     <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_POLICY_CHANGED" />
+    <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED" />
     <protected-broadcast android:name="android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED" />
 
     <!-- @deprecated This is rarely used and will be phased out soon. -->
@@ -2930,6 +2931,15 @@
     <permission android:name="android.permission.BIND_IMS_SERVICE"
         android:protectionLevel="signature|privileged|vendorPrivileged" />
 
+    <!-- Must be required by a SatelliteService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature|privileged|vendorPrivileged
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_SATELLITE_SERVICE"
+        android:protectionLevel="signature|privileged|vendorPrivileged" />
+
     <!-- Must be required by a telephony data service to ensure that only the
          system can bind to it.
          <p>Protection level: signature
@@ -3667,6 +3677,10 @@
     <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MTE"
                 android:protectionLevel="internal|role" />
 
+    <!-- Allows an application to manage policy related to device identifiers. -->
+    <permission android:name="android.permission.MANAGE_DEVICE_POLICY_DEVICE_IDENTIFIERS"
+                android:protectionLevel="internal|role" />
+
     <!-- Allows an application to set device policies outside the current user
         that are critical for securing data within the current user.
         <p>Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_*
@@ -4459,6 +4473,11 @@
     <permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"
         android:protectionLevel="normal" />
 
+    <!-- Allows permission to use Credential Manager UI for providing and saving credentials
+         @hide -->
+    <permission android:name="android.permission.LAUNCH_CREDENTIAL_SELECTOR"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to be able to store and retrieve credentials from a remote
          device.
          @hide @SystemApi -->
@@ -5838,7 +5857,7 @@
          <p>Not for use by third-party applications.</p>
          @hide -->
     <permission android:name="android.permission.CALL_AUDIO_INTERCEPTION"
-                android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|privileged|role" />
 
     <!-- @TestApi Allows an application to query audio related state.
          @hide -->
@@ -5940,6 +5959,12 @@
     <permission android:name="android.permission.MANAGE_LOW_POWER_STANDBY"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @hide @SystemApi Allows an application to request ports to remain open during
+         Low Power Standby.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.SET_LOW_POWER_STANDBY_PORTS"
+        android:protectionLevel="signature|privileged" />
+
    <!-- @hide Allows low-level access to tun tap driver -->
     <permission android:name="android.permission.NET_TUNNELING"
         android:protectionLevel="signature|role" />
diff --git a/core/res/res/drawable/accessibility_magnification_thumbnail_background_bg.xml b/core/res/res/drawable/accessibility_magnification_thumbnail_background_bg.xml
new file mode 100644
index 0000000..7b82b4d
--- /dev/null
+++ b/core/res/res/drawable/accessibility_magnification_thumbnail_background_bg.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+<item>
+    <shape android:shape="rectangle">
+        <stroke
+            android:width="1dp"
+            android:color="@color/accessibility_magnification_thumbnail_stroke_color" />
+        <corners android:radius="4dp"/>
+        <solid android:color="@color/accessibility_magnification_thumbnail_background_color" />
+    </shape>
+</item>
+</layer-list>
diff --git a/core/res/res/drawable/accessibility_magnification_thumbnail_bg.xml b/core/res/res/drawable/accessibility_magnification_thumbnail_bg.xml
new file mode 100644
index 0000000..77ba94e
--- /dev/null
+++ b/core/res/res/drawable/accessibility_magnification_thumbnail_bg.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+<item>
+    <shape android:shape="rectangle">
+        <corners android:radius="2dp"/>
+        <solid android:color="@color/accessibility_magnification_thumbnail_color" />
+    </shape>
+</item>
+</layer-list>
diff --git a/core/res/res/layout/thumbnail_background_view.xml b/core/res/res/layout/thumbnail_background_view.xml
new file mode 100644
index 0000000..0ba01e9
--- /dev/null
+++ b/core/res/res/layout/thumbnail_background_view.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@drawable/accessibility_magnification_thumbnail_background_bg">
+    <View
+        android:id="@+id/accessibility_magnification_thumbnail_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/accessibility_magnification_thumbnail_bg">
+    </View>
+</FrameLayout>
\ No newline at end of file
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 0c2fc1d..6b3c155 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -470,15 +470,15 @@
     <color name="system_error_container_light">#FFDAD5</color>
     <color name="system_on_error_container_light">#410000</color>
     <color name="system_primary_fixed_light">#D8E2FF</color>
-    <color name="system_primary_fixed_darker_light">#ADC6FF</color>
+    <color name="system_primary_fixed_dim_light">#ADC6FF</color>
     <color name="system_on_primary_fixed_light">#001A41</color>
     <color name="system_on_primary_fixed_variant_light">#2B4678</color>
     <color name="system_secondary_fixed_light">#DBE2F9</color>
-    <color name="system_secondary_fixed_darker_light">#BFC6DC</color>
+    <color name="system_secondary_fixed_dim_light">#BFC6DC</color>
     <color name="system_on_secondary_fixed_light">#141B2C</color>
     <color name="system_on_secondary_fixed_variant_light">#3F4759</color>
     <color name="system_tertiary_fixed_light">#FBD7FC</color>
-    <color name="system_tertiary_fixed_darker_light">#DEBCDF</color>
+    <color name="system_tertiary_fixed_dim_light">#DEBCDF</color>
     <color name="system_on_tertiary_fixed_light">#29132D</color>
     <color name="system_on_tertiary_fixed_variant_light">#583E5B</color>
     <color name="system_control_activated_light">#D8E2FF</color>
@@ -525,15 +525,15 @@
     <color name="system_error_container_dark">#930001</color>
     <color name="system_on_error_container_dark">#FFDAD5</color>
     <color name="system_primary_fixed_dark">#D8E2FF</color>
-    <color name="system_primary_fixed_darker_dark">#ADC6FF</color>
+    <color name="system_primary_fixed_dim_dark">#ADC6FF</color>
     <color name="system_on_primary_fixed_dark">#001A41</color>
     <color name="system_on_primary_fixed_variant_dark">#2B4678</color>
     <color name="system_secondary_fixed_dark">#DBE2F9</color>
-    <color name="system_secondary_fixed_darker_dark">#BFC6DC</color>
+    <color name="system_secondary_fixed_dim_dark">#BFC6DC</color>
     <color name="system_on_secondary_fixed_dark">#141B2C</color>
     <color name="system_on_secondary_fixed_variant_dark">#3F4759</color>
     <color name="system_tertiary_fixed_dark">#FBD7FC</color>
-    <color name="system_tertiary_fixed_darker_dark">#DEBCDF</color>
+    <color name="system_tertiary_fixed_dim_dark">#DEBCDF</color>
     <color name="system_on_tertiary_fixed_dark">#29132D</color>
     <color name="system_on_tertiary_fixed_variant_dark">#583E5B</color>
     <color name="system_control_activated_dark">#2B4678</color>
@@ -556,6 +556,11 @@
     <color name="accessibility_daltonizer_background">#00BCD4</color>
     <color name="accessibility_color_inversion_background">#546E7A</color>
 
+    <!-- Fullscreen magnification thumbnail color -->
+    <color name="accessibility_magnification_thumbnail_stroke_color">#E0E0E0</color>
+    <color name="accessibility_magnification_thumbnail_background_color">#FCFCFC</color>
+    <color name="accessibility_magnification_thumbnail_color">#252525</color>
+
     <!-- Color of camera light when camera is in use -->
     <color name="camera_privacy_light_day">#FFFFFF</color>
     <color name="camera_privacy_light_night">#FFFFFF</color>
@@ -573,4 +578,10 @@
     <color name="side_fps_toast_background">#F7F9FA</color>
     <color name="side_fps_text_color">#191C1D</color>
     <color name="side_fps_button_color">#00677E</color>
+
+    <!-- Color for system bars -->
+    <color name="navigation_bar_compatible">@android:color/black</color>
+    <!-- This uses non-regular transparent intentionally. It is used to tell if the transparent
+         color is set by the framework or not. -->
+    <color name="navigation_bar_default">#00808080</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8e5ae9c..31b9f9a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2189,6 +2189,8 @@
     <bool name="config_enableDefaultNotesForWorkProfile">false</bool>
     <!-- The name of the package that will hold the system financed device controller role. -->
     <string name="config_systemFinancedDeviceController" translatable="false">com.android.devicelockcontroller</string>
+    <!-- The name of the package that will hold the call streaming role. -->
+    <string name="config_systemCallStreaming" translatable="false"></string>
 
     <!-- The component name of the wear service class that will be started by the system server. -->
     <string name="config_wearServiceComponent" translatable="false"></string>
@@ -3876,6 +3878,10 @@
          This should only be set when the device has gestural navigation enabled by default. -->
     <bool name="config_showGesturalNavigationHints">false</bool>
 
+    <!-- Controls whether the navigation bar background color provided by the app is transparent by
+         default. This should be controlled in developer options. -->
+    <bool name="config_navBarDefaultTransparent">false</bool>
+
     <!-- Controls the free snap mode for the docked stack divider. In this mode, the divider can be
          snapped to any position between the first target and the last target. -->
     <bool name="config_dockedStackDividerFreeSnapMode">false</bool>
diff --git a/core/res/res/values/config_device_idle.xml b/core/res/res/values/config_device_idle.xml
index 8ed58f3..5576b9f 100644
--- a/core/res/res/values/config_device_idle.xml
+++ b/core/res/res/values/config_device_idle.xml
@@ -28,11 +28,17 @@
     <integer name="device_idle_flex_time_short_ms">60000</integer>
 
     <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT -->
-    <integer name="device_idle_light_after_inactive_to_ms">180000</integer>
+    <integer name="device_idle_light_after_inactive_to_ms">240000</integer>
 
     <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_TIMEOUT -->
     <integer name="device_idle_light_idle_to_ms">300000</integer>
 
+    <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_TIMEOUT_MAX_FLEX -->
+    <integer name="device_idle_light_idle_to_init_flex_ms">60000</integer>
+
+    <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_TIMEOUT_MAX_FLEX -->
+    <integer name="device_idle_light_idle_to_max_flex_ms">900000</integer>
+
     <!-- Default for DeviceIdleController.Constants.LIGHT_IDLE_FACTOR -->
     <item name="device_idle_light_idle_factor" format="float" type="integer">2.0</item>
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e156c44..5bb86dc 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -606,6 +606,9 @@
     <!-- Width of the outline stroke used by the accessibility focus rectangle -->
     <dimen name="accessibility_focus_highlight_stroke_width">4dp</dimen>
 
+    <!-- padding of fullscreen magnification thumbnail -->
+    <dimen name="accessibility_magnification_thumbnail_padding">12dp</dimen>
+
     <!-- The padding ratio of the Accessibility icon foreground drawable -->
     <item name="accessibility_icon_foreground_padding_ratio" type="dimen">21.88%</item>
 
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 7d41f76..b23d5b4 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -148,6 +148,8 @@
     <public name="config_defaultNotes" />
     <!-- @hide @SystemApi -->
     <public name="config_systemFinancedDeviceController" />
+    <!-- @hide @SystemApi -->
+    <public name="config_systemCallStreaming" />
   </staging-public-group>
 
   <staging-public-group type="dimen" first-id="0x01ca0000">
@@ -187,15 +189,15 @@
     <public name="system_error_container_light" />
     <public name="system_on_error_container_light" />
     <public name="system_primary_fixed_light" />
-    <public name="system_primary_fixed_darker_light" />
+    <public name="system_primary_fixed_dim_light" />
     <public name="system_on_primary_fixed_light" />
     <public name="system_on_primary_fixed_variant_light" />
     <public name="system_secondary_fixed_light" />
-    <public name="system_secondary_fixed_darker_light" />
+    <public name="system_secondary_fixed_dim_light" />
     <public name="system_on_secondary_fixed_light" />
     <public name="system_on_secondary_fixed_variant_light" />
     <public name="system_tertiary_fixed_light" />
-    <public name="system_tertiary_fixed_darker_light" />
+    <public name="system_tertiary_fixed_dim_light" />
     <public name="system_on_tertiary_fixed_light" />
     <public name="system_on_tertiary_fixed_variant_light" />
     <public name="system_control_activated_light" />
@@ -242,15 +244,15 @@
     <public name="system_error_container_dark"/>
     <public name="system_on_error_container_dark"/>
     <public name="system_primary_fixed_dark"/>
-    <public name="system_primary_fixed_darker_dark"/>
+    <public name="system_primary_fixed_dim_dark"/>
     <public name="system_on_primary_fixed_dark"/>
     <public name="system_on_primary_fixed_variant_dark"/>
     <public name="system_secondary_fixed_dark"/>
-    <public name="system_secondary_fixed_darker_dark"/>
+    <public name="system_secondary_fixed_dim_dark"/>
     <public name="system_on_secondary_fixed_dark"/>
     <public name="system_on_secondary_fixed_variant_dark"/>
     <public name="system_tertiary_fixed_dark"/>
-    <public name="system_tertiary_fixed_darker_dark"/>
+    <public name="system_tertiary_fixed_dim_dark"/>
     <public name="system_on_tertiary_fixed_dark"/>
     <public name="system_on_tertiary_fixed_variant_dark"/>
     <public name="system_control_activated_dark"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dcd7a31..312ad1f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2996,6 +2996,9 @@
   <java-symbol type="array" name="config_backGestureInsetScales" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
   <java-symbol type="bool" name="config_showGesturalNavigationHints" />
+  <java-symbol type="bool" name="config_navBarDefaultTransparent" />
+  <java-symbol type="color" name="navigation_bar_default"/>
+  <java-symbol type="color" name="navigation_bar_compatible"/>
 
   <!-- EditText suggestion popup. -->
   <java-symbol type="id" name="suggestionWindowContainer" />
@@ -4414,6 +4417,8 @@
   <java-symbol type="integer" name="device_idle_flex_time_short_ms" />
   <java-symbol type="integer" name="device_idle_light_after_inactive_to_ms" />
   <java-symbol type="integer" name="device_idle_light_idle_to_ms" />
+  <java-symbol type="integer" name="device_idle_light_idle_to_init_flex_ms" />
+  <java-symbol type="integer" name="device_idle_light_idle_to_max_flex_ms" />
   <java-symbol type="integer" name="device_idle_light_idle_factor" />
   <java-symbol type="integer" name="device_idle_light_max_idle_to_ms" />
   <java-symbol type="integer" name="device_idle_light_idle_maintenance_min_budget_ms" />
@@ -4499,7 +4504,15 @@
   <java-symbol type="bool" name="config_magnification_area" />
 
   <java-symbol type="bool" name="config_trackerAppNeedsPermissions"/>
-
+  <!-- FullScreenMagnification thumbnail -->
+  <java-symbol type="layout" name="thumbnail_background_view" />
+  <java-symbol type="drawable" name="accessibility_magnification_thumbnail_background_bg" />
+  <java-symbol type="drawable" name="accessibility_magnification_thumbnail_bg" />
+  <java-symbol type="color" name="accessibility_magnification_thumbnail_stroke_color" />
+  <java-symbol type="color" name="accessibility_magnification_thumbnail_background_color" />
+  <java-symbol type="color" name="accessibility_magnification_thumbnail_color" />
+  <java-symbol type="dimen" name="accessibility_magnification_thumbnail_padding" />
+  <java-symbol type="id" name="accessibility_magnification_thumbnail_view" />
   <!-- Package with global data query permissions for AppSearch -->
   <java-symbol type="string" name="config_globalAppSearchDataQuerierPackage" />
 
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index a60862b..e96de582 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -191,7 +191,7 @@
         <item name="windowTranslucentNavigation">false</item>
         <item name="windowDrawsSystemBarBackgrounds">false</item>
         <item name="statusBarColor">@color/black</item>
-        <item name="navigationBarColor">@color/black</item>
+        <item name="navigationBarColor">@color/navigation_bar_default</item>
         <item name="windowActionBarFullscreenDecorLayout">@layout/screen_action_bar</item>
         <item name="windowContentTransitions">false</item>
         <item name="windowActivityTransitions">false</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index e516a6c..cd4c0d6 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -175,7 +175,7 @@
         <item name="windowDrawsSystemBarBackgrounds">true</item>
         <item name="windowActionBarFullscreenDecorLayout">@layout/screen_toolbar</item>
         <item name="statusBarColor">?attr/colorPrimaryDark</item>
-        <item name="navigationBarColor">@color/black</item>
+        <item name="navigationBarColor">@color/navigation_bar_default</item>
         <item name="windowEnterTransition">@transition/fade</item>
         <item name="windowSharedElementEnterTransition">@transition/move</item>
         <item name="windowSharedElementExitTransition">@transition/move</item>
@@ -548,7 +548,7 @@
         <item name="windowDrawsSystemBarBackgrounds">true</item>
         <item name="windowActionBarFullscreenDecorLayout">@layout/screen_toolbar</item>
         <item name="statusBarColor">?attr/colorPrimaryDark</item>
-        <item name="navigationBarColor">@color/black</item>
+        <item name="navigationBarColor">@color/navigation_bar_default</item>
         <item name="windowEnterTransition">@transition/fade</item>
         <item name="windowSharedElementEnterTransition">@transition/move</item>
         <item name="windowSharedElementExitTransition">@transition/move</item>
diff --git a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
new file mode 100644
index 0000000..444e9f2
--- /dev/null
+++ b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
@@ -0,0 +1,626 @@
+/*
+ * 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 android.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.slice.Slice;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ICancellationSignal;
+import android.os.OutcomeReceiver;
+import android.os.RemoteException;
+import android.service.credentials.CredentialEntry;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CredentialManagerTest {
+    @Mock
+    private ICredentialManager mMockCredentialManagerService;
+
+    @Mock
+    private Activity mMockActivity;
+
+    private GetCredentialRequest mGetRequest;
+    private CreateCredentialRequest mCreateRequest;
+
+    private ClearCredentialStateRequest mClearRequest;
+    private RegisterCredentialDescriptionRequest mRegisterRequest;
+    private UnregisterCredentialDescriptionRequest mUnregisterRequest;
+
+    private CredentialManager mCredentialManager;
+    private Executor mExecutor;
+    private String mPackageName;
+
+    private static boolean bundleEquals(Bundle a, Bundle b) {
+        if (a == null && b == null) {
+            return true;
+        }
+        if (a == null || b == null) {
+            return false;
+        }
+        for (String aKey : a.keySet()) {
+            if (!Objects.equals(a.get(aKey), b.get(aKey))) {
+                return false;
+            }
+        }
+
+        for (String bKey : b.keySet()) {
+            if (!Objects.equals(b.get(bKey), a.get(bKey))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private static void assertBundleEquals(Bundle a, Bundle b) {
+        assertThat(bundleEquals(a, b)).isTrue();
+    }
+
+    @Before
+    public void setup() {
+        mGetRequest = new GetCredentialRequest.Builder(Bundle.EMPTY).addCredentialOption(
+                new CredentialOption(Credential.TYPE_PASSWORD_CREDENTIAL, Bundle.EMPTY,
+                        Bundle.EMPTY, false)).build();
+        mCreateRequest = new CreateCredentialRequest(Credential.TYPE_PASSWORD_CREDENTIAL,
+                Bundle.EMPTY, Bundle.EMPTY, false, false);
+        mClearRequest = new ClearCredentialStateRequest(Bundle.EMPTY);
+
+        final Slice slice = new Slice.Builder(Uri.parse("foo://bar"), null).addText("some text",
+                null, List.of(Slice.HINT_TITLE)).build();
+        mRegisterRequest = new RegisterCredentialDescriptionRequest(
+                new CredentialDescription(Credential.TYPE_PASSWORD_CREDENTIAL,
+                        "{ \"foo\": \"bar\" }",
+                        List.of(new CredentialEntry(Credential.TYPE_PASSWORD_CREDENTIAL, slice))));
+        mUnregisterRequest = new UnregisterCredentialDescriptionRequest(
+                new CredentialDescription(Credential.TYPE_PASSWORD_CREDENTIAL,
+                        "{ \"foo\": \"bar\" }",
+                        List.of(new CredentialEntry(Credential.TYPE_PASSWORD_CREDENTIAL, slice))));
+
+        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+        mCredentialManager = new CredentialManager(context, mMockCredentialManagerService);
+        mExecutor = Runnable::run;
+        mPackageName = context.getOpPackageName();
+    }
+
+    @Test
+    public void testGetCredential_nullRequest() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.getCredential(null, mMockActivity, null, mExecutor,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testGetCredential_nullActivity() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.getCredential(mGetRequest, null, null, mExecutor,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testGetCredential_nullExecutor() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.getCredential(mGetRequest, mMockActivity, null, null,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testGetCredential_nullCallback() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.getCredential(mGetRequest, mMockActivity, null, null,
+                        null));
+    }
+
+    @Test
+    public void testGetCredential_noCredential() throws RemoteException {
+        ArgumentCaptor<IGetCredentialCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IGetCredentialCallback.class);
+        ArgumentCaptor<GetCredentialException> errorCaptor = ArgumentCaptor.forClass(
+                GetCredentialException.class);
+
+        OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeGetCredential(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.getCredential(mGetRequest, mMockActivity, null, mExecutor, callback);
+        verify(mMockCredentialManagerService).executeGetCredential(any(), any(), eq(mPackageName));
+
+        callbackCaptor.getValue().onError(GetCredentialException.TYPE_NO_CREDENTIAL,
+                "no credential found");
+        verify(callback).onError(errorCaptor.capture());
+
+        assertThat(errorCaptor.getValue().getType()).isEqualTo(
+                GetCredentialException.TYPE_NO_CREDENTIAL);
+    }
+
+    @Test
+    public void testGetCredential_alreadyCancelled() throws RemoteException {
+        final CancellationSignal cancellation = new CancellationSignal();
+        cancellation.cancel();
+
+        mCredentialManager.getCredential(mGetRequest, mMockActivity, cancellation, mExecutor,
+                result -> {
+                });
+
+        verify(mMockCredentialManagerService, never()).executeGetCredential(any(), any(), any());
+    }
+
+    @Test
+    public void testGetCredential_cancel() throws RemoteException {
+        final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
+        final CancellationSignal cancellation = new CancellationSignal();
+
+        OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeGetCredential(any(), any(), any())).thenReturn(
+                serviceSignal);
+
+        mCredentialManager.getCredential(mGetRequest, mMockActivity, cancellation, mExecutor,
+                callback);
+
+        verify(mMockCredentialManagerService).executeGetCredential(any(), any(), eq(mPackageName));
+
+        cancellation.cancel();
+        verify(serviceSignal).cancel();
+    }
+
+    @Test
+    public void testGetCredential_success() throws RemoteException {
+        final Credential cred = new Credential(Credential.TYPE_PASSWORD_CREDENTIAL, Bundle.EMPTY);
+
+        ArgumentCaptor<IGetCredentialCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IGetCredentialCallback.class);
+        ArgumentCaptor<GetCredentialResponse> responseCaptor = ArgumentCaptor.forClass(
+                GetCredentialResponse.class);
+
+        OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeGetCredential(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.getCredential(mGetRequest, mMockActivity, null, mExecutor, callback);
+        verify(mMockCredentialManagerService).executeGetCredential(any(), any(), eq(mPackageName));
+
+        callbackCaptor.getValue().onResponse(new GetCredentialResponse(cred));
+        verify(callback).onResult(responseCaptor.capture());
+
+        assertThat(responseCaptor.getValue().getCredential().getType()).isEqualTo(cred.getType());
+    }
+
+    @Test
+    public void testCreateCredential_nullRequest() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.createCredential(null, mMockActivity, null, mExecutor,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testCreateCredential_nullActivity() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.createCredential(mCreateRequest, null, null, mExecutor,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testCreateCredential_nullExecutor() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.createCredential(mCreateRequest, mMockActivity, null, null,
+                        result -> {
+                        }));
+    }
+
+    @Test
+    public void testCreateCredential_nullCallback() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.createCredential(mCreateRequest, mMockActivity, null,
+                        mExecutor, null));
+    }
+
+    @Test
+    public void testCreateCredential_alreadyCancelled() throws RemoteException {
+        final CancellationSignal cancellation = new CancellationSignal();
+        cancellation.cancel();
+
+        mCredentialManager.createCredential(mCreateRequest, mMockActivity, cancellation, mExecutor,
+                result -> {
+                });
+
+        verify(mMockCredentialManagerService, never()).executeCreateCredential(any(), any(), any());
+    }
+
+    @Test
+    public void testCreateCredential_cancel() throws RemoteException {
+        final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
+        final CancellationSignal cancellation = new CancellationSignal();
+
+        OutcomeReceiver<CreateCredentialResponse, CreateCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeCreateCredential(any(), any(), any())).thenReturn(
+                serviceSignal);
+
+        mCredentialManager.createCredential(mCreateRequest, mMockActivity, cancellation, mExecutor,
+                callback);
+
+        verify(mMockCredentialManagerService).executeCreateCredential(any(), any(),
+                eq(mPackageName));
+
+        cancellation.cancel();
+        verify(serviceSignal).cancel();
+    }
+
+    @Test
+    public void testCreateCredential_failed() throws RemoteException {
+        ArgumentCaptor<ICreateCredentialCallback> callbackCaptor = ArgumentCaptor.forClass(
+                ICreateCredentialCallback.class);
+        ArgumentCaptor<CreateCredentialException> errorCaptor = ArgumentCaptor.forClass(
+                CreateCredentialException.class);
+
+        OutcomeReceiver<CreateCredentialResponse, CreateCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeCreateCredential(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.createCredential(mCreateRequest, mMockActivity, null, mExecutor,
+                callback);
+        verify(mMockCredentialManagerService).executeCreateCredential(any(), any(),
+                eq(mPackageName));
+
+        callbackCaptor.getValue().onError(CreateCredentialException.TYPE_UNKNOWN, "unknown error");
+        verify(callback).onError(errorCaptor.capture());
+
+        assertThat(errorCaptor.getValue().getType()).isEqualTo(
+                CreateCredentialException.TYPE_UNKNOWN);
+    }
+
+    @Test
+    public void testCreateCredential_success() throws RemoteException {
+        final Bundle responseData = new Bundle();
+        responseData.putString("foo", "bar");
+
+        ArgumentCaptor<ICreateCredentialCallback> callbackCaptor = ArgumentCaptor.forClass(
+                ICreateCredentialCallback.class);
+        ArgumentCaptor<CreateCredentialResponse> responseCaptor = ArgumentCaptor.forClass(
+                CreateCredentialResponse.class);
+
+        OutcomeReceiver<CreateCredentialResponse, CreateCredentialException> callback = mock(
+                OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.executeCreateCredential(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.createCredential(mCreateRequest, mMockActivity, null, mExecutor,
+                callback);
+        verify(mMockCredentialManagerService).executeCreateCredential(any(), any(),
+                eq(mPackageName));
+
+        callbackCaptor.getValue().onResponse(new CreateCredentialResponse(responseData));
+        verify(callback).onResult(responseCaptor.capture());
+
+        assertBundleEquals(responseCaptor.getValue().getData(), responseData);
+    }
+
+    @Test
+    public void testClearCredentialState_nullRequest() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.clearCredentialState(null, null, mExecutor, result -> {
+                }));
+    }
+
+    @Test
+    public void testClearCredentialState_nullExecutor() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.clearCredentialState(mClearRequest, null, null, result -> {
+                }));
+    }
+
+    @Test
+    public void testClearCredentialState_nullCallback() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.clearCredentialState(mClearRequest, null, mExecutor,
+                        null));
+    }
+
+    @Test
+    public void testClearCredential_alreadyCancelled() throws RemoteException {
+        final CancellationSignal cancellation = new CancellationSignal();
+        cancellation.cancel();
+
+        mCredentialManager.clearCredentialState(mClearRequest, cancellation, mExecutor, result -> {
+        });
+
+        verify(mMockCredentialManagerService, never()).clearCredentialState(any(), any(), any());
+    }
+
+    @Test
+    public void testClearCredential_cancel() throws RemoteException {
+        final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
+        final CancellationSignal cancellation = new CancellationSignal();
+
+        OutcomeReceiver<Void, ClearCredentialStateException> callback = mock(OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.clearCredentialState(any(), any(), any())).thenReturn(
+                serviceSignal);
+
+        mCredentialManager.clearCredentialState(mClearRequest, cancellation, mExecutor, callback);
+
+        verify(mMockCredentialManagerService).clearCredentialState(any(), any(), eq(mPackageName));
+
+        cancellation.cancel();
+        verify(serviceSignal).cancel();
+    }
+
+    @Test
+    public void testClearCredential_failed() throws RemoteException {
+        ArgumentCaptor<IClearCredentialStateCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IClearCredentialStateCallback.class);
+        ArgumentCaptor<ClearCredentialStateException> errorCaptor = ArgumentCaptor.forClass(
+                ClearCredentialStateException.class);
+
+        OutcomeReceiver<Void, ClearCredentialStateException> callback = mock(OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.clearCredentialState(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.clearCredentialState(mClearRequest, null, mExecutor, callback);
+        verify(mMockCredentialManagerService).clearCredentialState(any(), any(), eq(mPackageName));
+
+        callbackCaptor.getValue().onError(ClearCredentialStateException.TYPE_UNKNOWN,
+                "unknown error");
+        verify(callback).onError(errorCaptor.capture());
+
+        assertThat(errorCaptor.getValue().getType()).isEqualTo(
+                ClearCredentialStateException.TYPE_UNKNOWN);
+    }
+
+    @Test
+    public void testClearCredential_success() throws RemoteException {
+        ArgumentCaptor<IClearCredentialStateCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IClearCredentialStateCallback.class);
+
+        OutcomeReceiver<Void, ClearCredentialStateException> callback = mock(OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.clearCredentialState(any(), callbackCaptor.capture(),
+                any())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.clearCredentialState(mClearRequest, null, mExecutor, callback);
+        verify(mMockCredentialManagerService).clearCredentialState(any(), any(), eq(mPackageName));
+
+        callbackCaptor.getValue().onSuccess();
+        verify(callback).onResult(any());
+    }
+
+    @Test
+    public void testListEnabledProviders_nullExecutor() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.listEnabledProviders(null, null, result -> {
+                }));
+
+    }
+
+    @Test
+    public void testListEnabledProviders_nullCallback() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.listEnabledProviders(null, mExecutor, null));
+
+    }
+
+    @Test
+    public void testListEnabledProviders_alreadyCancelled() throws RemoteException {
+        final CancellationSignal cancellation = new CancellationSignal();
+        cancellation.cancel();
+
+        mCredentialManager.listEnabledProviders(cancellation, mExecutor, result -> {
+        });
+
+        verify(mMockCredentialManagerService, never()).listEnabledProviders(any());
+    }
+
+    @Test
+    public void testListEnabledProviders_cancel() throws RemoteException {
+        final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
+        final CancellationSignal cancellation = new CancellationSignal();
+
+        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
+                mock(OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.listEnabledProviders(any())).thenReturn(serviceSignal);
+
+        mCredentialManager.listEnabledProviders(cancellation, mExecutor, callback);
+
+        verify(mMockCredentialManagerService).listEnabledProviders(any());
+
+        cancellation.cancel();
+        verify(serviceSignal).cancel();
+    }
+
+    @Test
+    public void testListEnabledProviders_failed() throws RemoteException {
+        ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IListEnabledProvidersCallback.class);
+        ArgumentCaptor<ListEnabledProvidersException> errorCaptor = ArgumentCaptor.forClass(
+                ListEnabledProvidersException.class);
+
+        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
+                mock(OutcomeReceiver.class);
+
+        when(mMockCredentialManagerService.listEnabledProviders(
+                callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.listEnabledProviders(null, mExecutor, callback);
+        verify(mMockCredentialManagerService).listEnabledProviders(any());
+
+        final String errorType = "type";
+        callbackCaptor.getValue().onError("type", "unknown error");
+        verify(callback).onError(errorCaptor.capture());
+
+        assertThat(errorCaptor.getValue().getType()).isEqualTo(errorType);
+    }
+
+    @Test
+    public void testListEnabledProviders_success() throws RemoteException {
+        ListEnabledProvidersResponse response = ListEnabledProvidersResponse.create(
+                List.of("foo", "bar", "baz"));
+
+        OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
+                mock(OutcomeReceiver.class);
+
+        ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
+                IListEnabledProvidersCallback.class);
+        ArgumentCaptor<ListEnabledProvidersResponse> responseCaptor = ArgumentCaptor.forClass(
+                ListEnabledProvidersResponse.class);
+
+        when(mMockCredentialManagerService.listEnabledProviders(
+                callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
+        mCredentialManager.listEnabledProviders(null, mExecutor, callback);
+
+        verify(mMockCredentialManagerService).listEnabledProviders(any());
+
+        callbackCaptor.getValue().onResponse(response);
+
+        verify(callback).onResult(responseCaptor.capture());
+        assertThat(responseCaptor.getValue().getProviderComponentNames()).containsExactlyElementsIn(
+                response.getProviderComponentNames());
+    }
+
+    @Test
+    public void testSetEnabledProviders_nullProviders() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.setEnabledProviders(null, 0, mExecutor, response -> {
+                }));
+
+    }
+
+    @Test
+    public void testSetEnabledProviders_nullExecutor() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.setEnabledProviders(List.of("foo"), 0, null, response -> {
+                }));
+
+    }
+
+    @Test
+    public void testSetEnabledProviders_nullCallback() {
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.setEnabledProviders(List.of("foo"), 0, mExecutor, null));
+
+    }
+
+    @Test
+    public void testSetEnabledProviders_failed() throws RemoteException {
+        OutcomeReceiver<Void, SetEnabledProvidersException> callback = mock(OutcomeReceiver.class);
+
+        ArgumentCaptor<ISetEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
+                ISetEnabledProvidersCallback.class);
+        ArgumentCaptor<SetEnabledProvidersException> errorCaptor = ArgumentCaptor.forClass(
+                SetEnabledProvidersException.class);
+
+        final List<String> providers = List.of("foo", "bar");
+        final int userId = 0;
+        mCredentialManager.setEnabledProviders(providers, userId, mExecutor, callback);
+        verify(mMockCredentialManagerService).setEnabledProviders(eq(providers), eq(0),
+                callbackCaptor.capture());
+
+        final String errorType = "unknown";
+        final String errorMessage = "Unknown error";
+        callbackCaptor.getValue().onError(errorType, errorMessage);
+        verify(callback).onError(errorCaptor.capture());
+
+        assertThat(errorCaptor.getValue().getType()).isEqualTo(errorType);
+        assertThat(errorCaptor.getValue().getMessage()).isEqualTo(errorMessage);
+    }
+
+    @Test
+    public void testSetEnabledProviders_success() throws RemoteException {
+        OutcomeReceiver<Void, SetEnabledProvidersException> callback = mock(OutcomeReceiver.class);
+
+        ArgumentCaptor<ISetEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
+                ISetEnabledProvidersCallback.class);
+
+        final List<String> providers = List.of("foo", "bar");
+        final int userId = 0;
+        mCredentialManager.setEnabledProviders(providers, userId, mExecutor, callback);
+
+        verify(mMockCredentialManagerService).setEnabledProviders(eq(providers), eq(0),
+                callbackCaptor.capture());
+
+        callbackCaptor.getValue().onResponse();
+        verify(callback).onResult(any());
+    }
+
+    @Test
+    public void testRegisterCredentialDescription_nullRequest() {
+        assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.registerCredentialDescription(null));
+    }
+
+    @Test
+    public void testRegisterCredentialDescription_success() throws RemoteException {
+        assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
+
+        mCredentialManager.registerCredentialDescription(mRegisterRequest);
+        verify(mMockCredentialManagerService).registerCredentialDescription(same(mRegisterRequest),
+                eq(mPackageName));
+    }
+
+    @Test
+    public void testUnregisterCredentialDescription_nullRequest() {
+        assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
+
+        assertThrows(NullPointerException.class,
+                () -> mCredentialManager.unregisterCredentialDescription(null));
+    }
+
+    @Test
+    public void testUnregisterCredentialDescription_success() throws RemoteException {
+        assumeTrue(CredentialManager.isCredentialDescriptionApiEnabled());
+
+        mCredentialManager.unregisterCredentialDescription(mUnregisterRequest);
+        verify(mMockCredentialManagerService).unregisterCredentialDescription(
+                same(mUnregisterRequest), eq(mPackageName));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 0d7c8b8..6d635af 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -58,7 +58,7 @@
 
     // The number of flags held in boolean properties. Their values should also be double-checked
     // in the methods above.
-    private static final int NUM_BOOLEAN_PROPERTIES = 25;
+    private static final int NUM_BOOLEAN_PROPERTIES = 26;
 
     @Test
     public void testStandardActions_serializationFlagIsValid() {
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a37cb80..9ebcc75 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -281,6 +281,7 @@
         <permission name="android.permission.MANAGE_GAME_MODE"/>
         <permission name="android.permission.MANAGE_GAME_ACTIVITY" />
         <permission name="android.permission.MANAGE_LOW_POWER_STANDBY" />
+        <permission name="android.permission.SET_LOW_POWER_STANDBY_PORTS" />
         <permission name="android.permission.MANAGE_ROLLBACKS"/>
         <permission name="android.permission.MANAGE_USB"/>
         <!-- Needed for tests only -->
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index b1abc2a1..a39dd08 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2175,23 +2175,26 @@
 
     public static final @NonNull Parcelable.Creator<Bitmap> CREATOR
             = new Parcelable.Creator<Bitmap>() {
-        /**
-         * Rebuilds a bitmap previously stored with writeToParcel().
-         *
-         * @param p    Parcel object to read the bitmap from
-         * @return a new bitmap created from the data in the parcel
-         */
-        public Bitmap createFromParcel(Parcel p) {
-            Bitmap bm = nativeCreateFromParcel(p);
-            if (bm == null) {
-                throw new RuntimeException("Failed to unparcel Bitmap");
-            }
-            return bm;
-        }
-        public Bitmap[] newArray(int size) {
-            return new Bitmap[size];
-        }
-    };
+                /**
+                 * Rebuilds a bitmap previously stored with writeToParcel().
+                 *
+                 * @param p    Parcel object to read the bitmap from
+                 * @return a new bitmap created from the data in the parcel
+                 */
+                public Bitmap createFromParcel(Parcel p) {
+                    Bitmap bm = nativeCreateFromParcel(p);
+                    if (bm == null) {
+                        throw new RuntimeException("Failed to unparcel Bitmap");
+                    }
+                    if (p.readBoolean()) {
+                        bm.setGainmap(p.readTypedObject(Gainmap.CREATOR));
+                    }
+                    return bm;
+                }
+                public Bitmap[] newArray(int size) {
+                    return new Bitmap[size];
+                }
+            };
 
     /**
      * No special parcel contents.
@@ -2215,6 +2218,12 @@
         if (!nativeWriteToParcel(mNativePtr, mDensity, p)) {
             throw new RuntimeException("native writeToParcel failed");
         }
+        if (hasGainmap()) {
+            p.writeBoolean(true);
+            p.writeTypedObject(mGainmap, flags);
+        } else {
+            p.writeBoolean(false);
+        }
     }
 
     /**
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 53f23c0..470a06c 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -18,6 +18,8 @@
 
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -76,7 +78,7 @@
  *
  * In the above math, log() is a natural logarithm and exp() is natural exponentiation.
  */
-public final class Gainmap {
+public final class Gainmap implements Parcelable {
 
     // Use a Holder to allow static initialization of Gainmap in the boot image.
     private static class NoImagePreloadHolder {
@@ -284,6 +286,50 @@
         return nGetDisplayRatioSdr(mNativePtr);
     }
 
+    /**
+     * No special parcel contents.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Write the gainmap to the parcel.
+     *
+     * @param dest Parcel object to write the gainmap data into
+     * @param flags Additional flags about how the object should be written.
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        if (mNativePtr == 0) {
+            throw new IllegalStateException("Cannot be written to a parcel");
+        }
+        dest.writeTypedObject(mGainmapContents, flags);
+        // write gainmapinfo into parcel
+        nWriteGainmapToParcel(mNativePtr, dest);
+    }
+
+    public static final @NonNull Parcelable.Creator<Gainmap> CREATOR =
+            new Parcelable.Creator<Gainmap>() {
+            /**
+             * Rebuilds a gainmap previously stored with writeToParcel().
+             *
+             * @param in Parcel object to read the gainmap from
+             * @return a new gainmap created from the data in the parcel
+             */
+            public Gainmap createFromParcel(Parcel in) {
+                Gainmap gm = new Gainmap(in.readTypedObject(Bitmap.CREATOR));
+                // read gainmapinfo from parcel
+                nReadGainmapFromParcel(gm.mNativePtr, in);
+                return gm;
+            }
+
+            public Gainmap[] newArray(int size) {
+                return new Gainmap[size];
+            }
+        };
+
     private static native long nGetFinalizer();
     private static native long nCreateEmpty();
 
@@ -309,4 +355,6 @@
 
     private static native void nSetDisplayRatioSdr(long ptr, float min);
     private static native float nGetDisplayRatioSdr(long ptr);
+    private static native void nWriteGainmapToParcel(long ptr, Parcel dest);
+    private static native void nReadGainmapFromParcel(long ptr, Parcel src);
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
index bc81710..c9c0e40 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java
@@ -41,6 +41,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArraySet;
+import android.util.Pair;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.DisplayAreaInfo;
@@ -363,10 +364,10 @@
         }
         ProtoLog.d(WM_SHELL_DESKTOP_MODE, "handle shell transition request: %s", request);
 
-        WindowContainerTransaction wct = mTransitions.dispatchRequest(transition, request, this);
-        if (wct == null) {
-            wct = new WindowContainerTransaction();
-        }
+        Pair<Transitions.TransitionHandler, WindowContainerTransaction> subHandler =
+                mTransitions.dispatchRequest(transition, request, this);
+        WindowContainerTransaction wct = subHandler != null
+                ? subHandler.second : new WindowContainerTransaction();
         bringDesktopAppsToFront(wct);
         wct.reorder(request.getTriggerTask().token, true /* onTop */);
 
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 a2d7bc4..c2da705 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
@@ -17,6 +17,7 @@
 package com.android.wm.shell.transition;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -28,11 +29,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.IBinder;
+import android.util.Pair;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
+import android.window.WindowContainerTransactionCallback;
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.pip.PipTransitionController;
@@ -61,6 +64,9 @@
         /** Both the display and split-state (enter/exit) is changing */
         static final int TYPE_DISPLAY_AND_SPLIT_CHANGE = 2;
 
+        /** Pip was entered while handling an intent with its own remoteTransition. */
+        static final int TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE = 3;
+
         /** The default animation for this mixed transition. */
         static final int ANIM_TYPE_DEFAULT = 0;
 
@@ -85,6 +91,23 @@
             mType = type;
             mTransition = transition;
         }
+
+        void joinFinishArgs(WindowContainerTransaction wct,
+                WindowContainerTransactionCallback wctCB) {
+            if (wctCB != null) {
+                // Technically can probably support 1, but don't want to encourage CB usage since
+                // it creates instabliity, so just throw.
+                throw new IllegalArgumentException("Can't mix transitions that require finish"
+                        + " sync callback");
+            }
+            if (wct != null) {
+                if (mFinishWCT == null) {
+                    mFinishWCT = wct;
+                } else {
+                    mFinishWCT.merge(wct, true /* transfer */);
+                }
+            }
+        }
     }
 
     private final ArrayList<MixedTransition> mActiveTransitions = new ArrayList<>();
@@ -125,6 +148,25 @@
             mPipHandler.augmentRequest(transition, request, out);
             mSplitHandler.addEnterOrExitIfNeeded(request, out);
             return out;
+        } else if (request.getRemoteTransition() != null
+                && Transitions.isOpeningType(request.getType())
+                && (request.getTriggerTask() == null
+                || (request.getTriggerTask().topActivityType != ACTIVITY_TYPE_HOME
+                        && request.getTriggerTask().topActivityType != ACTIVITY_TYPE_RECENTS))) {
+            // Only select transitions with an intent-provided remote-animation because that will
+            // usually grab priority and often won't handle PiP. If there isn't an intent-provided
+            // remote, then the transition will be dispatched normally and the PipHandler will
+            // pick it up.
+            Pair<Transitions.TransitionHandler, WindowContainerTransaction> handler =
+                    mPlayer.dispatchRequest(transition, request, this);
+            if (handler == null) {
+                return null;
+            }
+            final MixedTransition mixed = new MixedTransition(
+                    MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE, transition);
+            mixed.mLeftoversHandler = handler.first;
+            mActiveTransitions.add(mixed);
+            return handler.second;
         }
         return null;
     }
@@ -169,6 +211,9 @@
                     finishCallback);
         } else if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) {
             return false;
+        } else if (mixed.mType == MixedTransition.TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE) {
+            return animateOpenIntentWithRemoteAndPip(mixed, info, startTransaction,
+                    finishTransaction, finishCallback);
         } else {
             mActiveTransitions.remove(mixed);
             throw new IllegalStateException("Starting mixed animation without a known mixed type? "
@@ -176,6 +221,59 @@
         }
     }
 
+    private boolean animateOpenIntentWithRemoteAndPip(@NonNull MixedTransition mixed,
+            @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {
+        TransitionInfo.Change pipChange = null;
+        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+            TransitionInfo.Change change = info.getChanges().get(i);
+            if (mPipHandler.isEnteringPip(change, info.getType())) {
+                if (pipChange != null) {
+                    throw new IllegalStateException("More than 1 pip-entering changes in one"
+                            + " transition? " + info);
+                }
+                pipChange = change;
+                info.getChanges().remove(i);
+            }
+        }
+        if (pipChange == null) {
+            if (mixed.mLeftoversHandler != null) {
+                return mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
+                        startTransaction, finishTransaction, finishCallback);
+            }
+            return false;
+        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Splitting PIP into a separate"
+                        + " animation because remote-animation likely doesn't support it");
+        mixed.mFinishCallback = finishCallback;
+        Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
+            --mixed.mInFlightSubAnimations;
+            mixed.joinFinishArgs(wct, wctCB);
+            if (mixed.mInFlightSubAnimations > 0) return;
+            mActiveTransitions.remove(mixed);
+            mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
+        };
+        // Split the transition into 2 parts: the pip part and the rest.
+        mixed.mInFlightSubAnimations = 2;
+        // make a new startTransaction because pip's startEnterAnimation "consumes" it so
+        // we need a separate one to send over to launcher.
+        SurfaceControl.Transaction otherStartT = new SurfaceControl.Transaction();
+
+        mPipHandler.startEnterAnimation(pipChange, otherStartT, finishTransaction, finishCB);
+
+        // Dispatch the rest of the transition normally.
+        if (mixed.mLeftoversHandler != null
+                && mixed.mLeftoversHandler.startAnimation(mixed.mTransition, info,
+                    startTransaction, finishTransaction, finishCB)) {
+            return true;
+        }
+        mixed.mLeftoversHandler = mPlayer.dispatchTransition(mixed.mTransition, info,
+                startTransaction, finishTransaction, finishCB, this);
+        return true;
+    }
+
     private boolean animateEnterPipFromSplit(@NonNull final MixedTransition mixed,
             @NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction startTransaction,
@@ -211,12 +309,13 @@
         mixed.mFinishCallback = finishCallback;
         Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
             --mixed.mInFlightSubAnimations;
+            mixed.joinFinishArgs(wct, wctCB);
             if (mixed.mInFlightSubAnimations > 0) return;
             mActiveTransitions.remove(mixed);
             if (isGoingHome) {
                 mSplitHandler.onTransitionAnimationComplete();
             }
-            mixed.mFinishCallback.onTransitionFinished(wct, wctCB);
+            mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, wctCB);
         };
         if (isGoingHome) {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is actually mixed "
@@ -317,17 +416,7 @@
 
         Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> {
             --mixed.mInFlightSubAnimations;
-            if (wctCB != null) {
-                throw new IllegalArgumentException("Can't mix transitions that require finish"
-                        + " sync callback");
-            }
-            if (wct != null) {
-                if (mixed.mFinishWCT == null) {
-                    mixed.mFinishWCT = wct;
-                } else {
-                    mixed.mFinishWCT.merge(wct, true /* transfer */);
-                }
-            }
+            mixed.joinFinishArgs(wct, wctCB);
             if (mixed.mInFlightSubAnimations > 0) return;
             mActiveTransitions.remove(mixed);
             mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */);
@@ -342,8 +431,7 @@
         // Note: at this point, startT has probably already been applied, so we are basically
         // giving splitHandler an empty startT. This is currently OK because display-change will
         // grab a screenshot and paste it on top anyways.
-        mSplitHandler.startPendingAnimation(
-                transition, everythingElse, startT, finishT, finishCB);
+        mSplitHandler.startPendingAnimation(transition, everythingElse, startT, finishT, finishCB);
         return true;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 75d1939..0826fe2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -47,6 +47,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.Pair;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.window.ITransitionPlayer;
@@ -627,13 +628,14 @@
      * Gives every handler (in order) a chance to handle request until one consumes the transition.
      * @return the WindowContainerTransaction given by the handler which consumed the transition.
      */
-    public WindowContainerTransaction dispatchRequest(@NonNull IBinder transition,
-            @NonNull TransitionRequestInfo request, @Nullable TransitionHandler skip) {
+    public Pair<TransitionHandler, WindowContainerTransaction> dispatchRequest(
+            @NonNull IBinder transition, @NonNull TransitionRequestInfo request,
+            @Nullable TransitionHandler skip) {
         for (int i = mHandlers.size() - 1; i >= 0; --i) {
             if (mHandlers.get(i) == skip) continue;
             WindowContainerTransaction wct = mHandlers.get(i).handleRequest(transition, request);
             if (wct != null) {
-                return wct;
+                return new Pair<>(mHandlers.get(i), wct);
             }
         }
         return null;
@@ -698,9 +700,9 @@
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                 "Transition animation finished (abort=%b), notifying core %s", abort, transition);
         if (active.mStartT != null) {
-            // Applied by now, so close immediately. Do not set to null yet, though, since nullness
-            // is used later to disambiguate malformed transitions.
-            active.mStartT.close();
+            // Applied by now, so clear immediately to remove any references. Do not set to null
+            // yet, though, since nullness is used later to disambiguate malformed transitions.
+            active.mStartT.clear();
         }
         // Merge all relevant transactions together
         SurfaceControl.Transaction fullFinish = active.mFinishT;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 44e4a31..de5f2f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -250,25 +250,30 @@
 
         @Override
         public boolean onTouch(View v, MotionEvent e) {
-            boolean isDrag = false;
             final int id = v.getId();
             if (id != R.id.caption_handle && id != R.id.desktop_mode_caption) {
                 return false;
             }
-            if (id == R.id.caption_handle) {
-                isDrag = mDragDetector.onMotionEvent(e);
+            switch (e.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    mDragDetector.onMotionEvent(e);
+                    final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
+                    if (taskInfo.isFocused) {
+                        return mDragDetector.isDragEvent();
+                    }
+                    final WindowContainerTransaction wct = new WindowContainerTransaction();
+                    wct.reorder(mTaskToken, true /* onTop */);
+                    mSyncQueue.queue(wct);
+                    return false;
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    boolean res = mDragDetector.isDragEvent();
+                    mDragDetector.onMotionEvent(e);
+                    return res;
+                default:
+                    mDragDetector.onMotionEvent(e);
+                    return mDragDetector.isDragEvent();
             }
-            if (e.getAction() != MotionEvent.ACTION_DOWN) {
-                return isDrag;
-            }
-            final RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
-            if (taskInfo.isFocused) {
-                return isDrag;
-            }
-            final WindowContainerTransaction wct = new WindowContainerTransaction();
-            wct.reorder(mTaskToken, true /* onTop */);
-            mSyncQueue.queue(wct);
-            return true;
         }
 
         /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
index 4fac843..cf1850b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -94,6 +94,10 @@
         mTouchSlop = touchSlop;
     }
 
+    boolean isDragEvent() {
+        return mIsDragEvent;
+    }
+
     private void resetState() {
         mIsDragEvent = false;
         mInputDownPoint.set(0, 0);
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 03d89cc..d63b3e7 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -364,6 +364,7 @@
         "jni/PathMeasure.cpp",
         "jni/Picture.cpp",
         "jni/Region.cpp",
+        "jni/ScopedParcel.cpp",
         "jni/Shader.cpp",
         "jni/RenderEffect.cpp",
         "jni/Typeface.cpp",
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index e71a2a5..3f9c4bd 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -10,6 +10,7 @@
 #include "Gainmap.h"
 #include "GraphicsJNI.h"
 #include "HardwareBufferHelpers.h"
+#include "ScopedParcel.h"
 #include "SkBitmap.h"
 #include "SkBlendMode.h"
 #include "SkCanvas.h"
@@ -27,12 +28,7 @@
 
 #ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
 #include <android-base/unique_fd.h>
-#include <android/binder_parcel.h>
-#include <android/binder_parcel_jni.h>
-#include <android/binder_parcel_platform.h>
-#include <cutils/ashmem.h>
 #include <renderthread/RenderProxy.h>
-#include <sys/mman.h>
 #endif
 
 #include <inttypes.h>
@@ -616,91 +612,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 // TODO: Move somewhere else
-#ifdef __ANDROID__ // Layoutlib does not support parcel
-
-class ScopedParcel {
-public:
-    explicit ScopedParcel(JNIEnv* env, jobject parcel) {
-        mParcel = AParcel_fromJavaParcel(env, parcel);
-    }
-
-    ~ScopedParcel() { AParcel_delete(mParcel); }
-
-    int32_t readInt32() {
-        int32_t temp = 0;
-        // TODO: This behavior-matches what android::Parcel does
-        // but this should probably be better
-        if (AParcel_readInt32(mParcel, &temp) != STATUS_OK) {
-            temp = 0;
-        }
-        return temp;
-    }
-
-    uint32_t readUint32() {
-        uint32_t temp = 0;
-        // TODO: This behavior-matches what android::Parcel does
-        // but this should probably be better
-        if (AParcel_readUint32(mParcel, &temp) != STATUS_OK) {
-            temp = 0;
-        }
-        return temp;
-    }
-
-    void writeInt32(int32_t value) { AParcel_writeInt32(mParcel, value); }
-
-    void writeUint32(uint32_t value) { AParcel_writeUint32(mParcel, value); }
-
-    bool allowFds() const { return AParcel_getAllowFds(mParcel); }
-
-    std::optional<sk_sp<SkData>> readData() {
-        struct Data {
-            void* ptr = nullptr;
-            size_t size = 0;
-        } data;
-        auto error = AParcel_readByteArray(mParcel, &data,
-                                           [](void* arrayData, int32_t length,
-                                              int8_t** outBuffer) -> bool {
-                                               Data* data = reinterpret_cast<Data*>(arrayData);
-                                               if (length > 0) {
-                                                   data->ptr = sk_malloc_canfail(length);
-                                                   if (!data->ptr) {
-                                                       return false;
-                                                   }
-                                                   *outBuffer =
-                                                           reinterpret_cast<int8_t*>(data->ptr);
-                                                   data->size = length;
-                                               }
-                                               return true;
-                                           });
-        if (error != STATUS_OK || data.size <= 0) {
-            sk_free(data.ptr);
-            return std::nullopt;
-        } else {
-            return SkData::MakeFromMalloc(data.ptr, data.size);
-        }
-    }
-
-    void writeData(const std::optional<sk_sp<SkData>>& optData) {
-        if (optData) {
-            const auto& data = *optData;
-            AParcel_writeByteArray(mParcel, reinterpret_cast<const int8_t*>(data->data()),
-                                   data->size());
-        } else {
-            AParcel_writeByteArray(mParcel, nullptr, -1);
-        }
-    }
-
-    AParcel* get() { return mParcel; }
-
-private:
-    AParcel* mParcel;
-};
-
-enum class BlobType : int32_t {
-    IN_PLACE,
-    ASHMEM,
-};
-
+#ifdef __ANDROID__  // Layoutlib does not support parcel
 #define ON_ERROR_RETURN(X) \
     if ((error = (X)) != STATUS_OK) return error
 
diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp
index 9cd3fb0..0f8a85d 100644
--- a/libs/hwui/jni/Gainmap.cpp
+++ b/libs/hwui/jni/Gainmap.cpp
@@ -16,8 +16,13 @@
 
 #include <Gainmap.h>
 
+#ifdef __ANDROID__
+#include <binder/Parcel.h>
+#endif
+
 #include "Bitmap.h"
 #include "GraphicsJNI.h"
+#include "ScopedParcel.h"
 #include "graphics_jni_helpers.h"
 
 namespace android {
@@ -154,6 +159,81 @@
     return fromJava(gainmapPtr)->info.fDisplayRatioSdr;
 }
 
+// ----------------------------------------------------------------------------
+// Serialization
+// ----------------------------------------------------------------------------
+
+static void Gainmap_writeToParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) {
+#ifdef __ANDROID__  // Layoutlib does not support parcel
+    if (parcel == NULL) {
+        ALOGD("write null parcel\n");
+        return;
+    }
+    ScopedParcel p(env, parcel);
+    SkGainmapInfo info = fromJava(nativeObject)->info;
+    // write gainmap to parcel
+    // ratio min
+    p.writeFloat(info.fGainmapRatioMin.fR);
+    p.writeFloat(info.fGainmapRatioMin.fG);
+    p.writeFloat(info.fGainmapRatioMin.fB);
+    // ratio max
+    p.writeFloat(info.fGainmapRatioMax.fR);
+    p.writeFloat(info.fGainmapRatioMax.fG);
+    p.writeFloat(info.fGainmapRatioMax.fB);
+    // gamma
+    p.writeFloat(info.fGainmapGamma.fR);
+    p.writeFloat(info.fGainmapGamma.fG);
+    p.writeFloat(info.fGainmapGamma.fB);
+    // epsilonsdr
+    p.writeFloat(info.fEpsilonSdr.fR);
+    p.writeFloat(info.fEpsilonSdr.fG);
+    p.writeFloat(info.fEpsilonSdr.fB);
+    // epsilonhdr
+    p.writeFloat(info.fEpsilonHdr.fR);
+    p.writeFloat(info.fEpsilonHdr.fG);
+    p.writeFloat(info.fEpsilonHdr.fB);
+    // display ratio sdr
+    p.writeFloat(info.fDisplayRatioSdr);
+    // display ratio hdr
+    p.writeFloat(info.fDisplayRatioHdr);
+    // base image type
+    p.writeInt32(static_cast<int32_t>(info.fBaseImageType));
+    // type
+    p.writeInt32(static_cast<int32_t>(info.fType));
+#else
+    doThrowRE(env, "Cannot use parcels outside of Android!");
+#endif
+}
+
+static void Gainmap_readFromParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) {
+#ifdef __ANDROID__  // Layoutlib does not support parcel
+    if (parcel == NULL) {
+        jniThrowNullPointerException(env, "parcel cannot be null");
+        return;
+    }
+    ScopedParcel p(env, parcel);
+
+    SkGainmapInfo info;
+    info.fGainmapRatioMin = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f};
+    info.fGainmapRatioMax = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f};
+    info.fGainmapGamma = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f};
+    info.fEpsilonSdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f};
+    info.fEpsilonHdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f};
+    info.fDisplayRatioSdr = p.readFloat();
+    info.fDisplayRatioHdr = p.readFloat();
+    info.fBaseImageType = static_cast<SkGainmapInfo::BaseImageType>(p.readInt32());
+    info.fType = static_cast<SkGainmapInfo::Type>(p.readInt32());
+
+    fromJava(nativeObject)->info = info;
+#else
+    jniThrowRuntimeException(env, "Cannot use parcels outside of Android");
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
 static const JNINativeMethod gGainmapMethods[] = {
         {"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer},
         {"nCreateEmpty", "()J", (void*)Gainmap_createEmpty},
@@ -172,6 +252,8 @@
         {"nGetDisplayRatioHdr", "(J)F", (void*)Gainmap_getDisplayRatioHdr},
         {"nSetDisplayRatioSdr", "(JF)V", (void*)Gainmap_setDisplayRatioSdr},
         {"nGetDisplayRatioSdr", "(J)F", (void*)Gainmap_getDisplayRatioSdr},
+        {"nWriteGainmapToParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_writeToParcel},
+        {"nReadGainmapFromParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_readFromParcel},
 };
 
 int register_android_graphics_Gainmap(JNIEnv* env) {
diff --git a/libs/hwui/jni/ScopedParcel.cpp b/libs/hwui/jni/ScopedParcel.cpp
new file mode 100644
index 0000000..b0f5423
--- /dev/null
+++ b/libs/hwui/jni/ScopedParcel.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+#include "ScopedParcel.h"
+
+#ifdef __ANDROID__  // Layoutlib does not support parcel
+
+using namespace android;
+
+int32_t ScopedParcel::readInt32() {
+    int32_t temp = 0;
+    // TODO: This behavior-matches what android::Parcel does
+    // but this should probably be better
+    if (AParcel_readInt32(mParcel, &temp) != STATUS_OK) {
+        temp = 0;
+    }
+    return temp;
+}
+
+uint32_t ScopedParcel::readUint32() {
+    uint32_t temp = 0;
+    // TODO: This behavior-matches what android::Parcel does
+    // but this should probably be better
+    if (AParcel_readUint32(mParcel, &temp) != STATUS_OK) {
+        temp = 0;
+    }
+    return temp;
+}
+
+float ScopedParcel::readFloat() {
+    float temp = 0.;
+    if (AParcel_readFloat(mParcel, &temp) != STATUS_OK) {
+        temp = 0.;
+    }
+    return temp;
+}
+
+std::optional<sk_sp<SkData>> ScopedParcel::readData() {
+    struct Data {
+        void* ptr = nullptr;
+        size_t size = 0;
+    } data;
+    auto error = AParcel_readByteArray(
+            mParcel, &data, [](void* arrayData, int32_t length, int8_t** outBuffer) -> bool {
+                Data* data = reinterpret_cast<Data*>(arrayData);
+                if (length > 0) {
+                    data->ptr = sk_malloc_canfail(length);
+                    if (!data->ptr) {
+                        return false;
+                    }
+                    *outBuffer = reinterpret_cast<int8_t*>(data->ptr);
+                    data->size = length;
+                }
+                return true;
+            });
+    if (error != STATUS_OK || data.size <= 0) {
+        sk_free(data.ptr);
+        return std::nullopt;
+    } else {
+        return SkData::MakeFromMalloc(data.ptr, data.size);
+    }
+}
+
+void ScopedParcel::writeData(const std::optional<sk_sp<SkData>>& optData) {
+    if (optData) {
+        const auto& data = *optData;
+        AParcel_writeByteArray(mParcel, reinterpret_cast<const int8_t*>(data->data()),
+                               data->size());
+    } else {
+        AParcel_writeByteArray(mParcel, nullptr, -1);
+    }
+}
+#endif  // __ANDROID__ // Layoutlib does not support parcel
diff --git a/libs/hwui/jni/ScopedParcel.h b/libs/hwui/jni/ScopedParcel.h
new file mode 100644
index 0000000..fd8d6a2
--- /dev/null
+++ b/libs/hwui/jni/ScopedParcel.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+#include "SkData.h"
+
+#ifdef __ANDROID__  // Layoutlib does not support parcel
+#include <android-base/unique_fd.h>
+#include <android/binder_parcel.h>
+#include <android/binder_parcel_jni.h>
+#include <android/binder_parcel_platform.h>
+#include <cutils/ashmem.h>
+#include <renderthread/RenderProxy.h>
+
+class ScopedParcel {
+public:
+    explicit ScopedParcel(JNIEnv* env, jobject parcel) {
+        mParcel = AParcel_fromJavaParcel(env, parcel);
+    }
+
+    ~ScopedParcel() { AParcel_delete(mParcel); }
+
+    int32_t readInt32();
+
+    uint32_t readUint32();
+
+    float readFloat();
+
+    void writeInt32(int32_t value) { AParcel_writeInt32(mParcel, value); }
+
+    void writeUint32(uint32_t value) { AParcel_writeUint32(mParcel, value); }
+
+    void writeFloat(float value) { AParcel_writeFloat(mParcel, value); }
+
+    bool allowFds() const { return AParcel_getAllowFds(mParcel); }
+
+    std::optional<sk_sp<SkData>> readData();
+
+    void writeData(const std::optional<sk_sp<SkData>>& optData);
+
+    AParcel* get() { return mParcel; }
+
+private:
+    AParcel* mParcel;
+};
+
+enum class BlobType : int32_t {
+    IN_PLACE,
+    ASHMEM,
+};
+
+#endif  // __ANDROID__ // Layoutlib does not support parcel
\ No newline at end of file
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 076e0cb..52dfb66 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -681,6 +681,20 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface Flags {}
 
+    /** @hide */
+    @IntDef(flag = true, prefix = "FLAG", value = {
+            FLAG_SHOW_UI,
+            FLAG_ALLOW_RINGER_MODES,
+            FLAG_PLAY_SOUND,
+            FLAG_REMOVE_SOUND_AND_VIBRATE,
+            FLAG_VIBRATE,
+            FLAG_BLUETOOTH_ABS_VOLUME,
+            FLAG_HDMI_SYSTEM_AUDIO_VOLUME,
+            FLAG_FROM_KEY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SystemVolumeFlags {}
+
     // The iterator of TreeMap#entrySet() returns the entries in ascending key order.
     private static final TreeMap<Integer, String> FLAG_NAMES = new TreeMap<>();
 
@@ -1445,7 +1459,7 @@
             android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS,
             android.Manifest.permission.MODIFY_AUDIO_ROUTING
     })
-    public void setVolumeGroupVolumeIndex(int groupId, int index, int flags) {
+    public void setVolumeGroupVolumeIndex(int groupId, int index, @SystemVolumeFlags int flags) {
         final IAudioService service = getService();
         try {
             service.setVolumeGroupVolumeIndex(groupId, index, flags,
@@ -1542,7 +1556,7 @@
      * @throws SecurityException if the adjustment triggers a Do Not Disturb change and the caller
      * is not granted notification policy access.
      */
-    public void adjustVolumeGroupVolume(int groupId, int direction, int flags) {
+    public void adjustVolumeGroupVolume(int groupId, int direction, @SystemVolumeFlags int flags) {
         IAudioService service = getService();
         try {
             service.adjustVolumeGroupVolume(groupId, direction, flags,
@@ -1564,10 +1578,10 @@
     @SystemApi
     @RequiresPermission("android.permission.QUERY_AUDIO_STATE")
     @IntRange(from = 0)
-    public int getLastAudibleVolumeGroupVolume(int groupId) {
+    public int getLastAudibleVolumeForVolumeGroup(int groupId) {
         IAudioService service = getService();
         try {
-            return service.getLastAudibleVolumeGroupVolume(groupId);
+            return service.getLastAudibleVolumeForVolumeGroup(groupId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 324e81a..4808692 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -153,7 +153,7 @@
     int getVolumeGroupMinVolumeIndex(int groupId);
 
     @EnforcePermission("QUERY_AUDIO_STATE")
-    int getLastAudibleVolumeGroupVolume(int groupId);
+    int getLastAudibleVolumeForVolumeGroup(int groupId);
 
     boolean isVolumeGroupMuted(int groupId);
 
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 7ef0f77..9a6d5d7 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -30,7 +30,6 @@
 #include <camera/Camera.h>
 #include <media/mediarecorder.h>
 #include <media/MediaMetricsItem.h>
-#include <media/MicrophoneInfo.h>
 #include <media/stagefright/PersistentSurface.h>
 #include <utils/threads.h>
 
@@ -774,7 +773,7 @@
     }
 
     jint jStatus = AUDIO_JAVA_SUCCESS;
-    std::vector<media::MicrophoneInfo> activeMicrophones;
+    std::vector<media::MicrophoneInfoFw> activeMicrophones;
     status_t status = mr->getActiveMicrophones(&activeMicrophones);
     if (status != NO_ERROR) {
         ALOGE_IF(status != NO_ERROR, "MediaRecorder::getActiveMicrophones error %d", status);
diff --git a/packages/CredentialManager/AndroidManifest.xml b/packages/CredentialManager/AndroidManifest.xml
index 499d130..b36cb5c 100644
--- a/packages/CredentialManager/AndroidManifest.xml
+++ b/packages/CredentialManager/AndroidManifest.xml
@@ -35,6 +35,7 @@
     <activity
         android:name=".CredentialSelectorActivity"
         android:exported="true"
+        android:permission="android.permission.LAUNCH_CREDENTIAL_SELECTOR"
         android:launchMode="singleTop"
         android:label="@string/app_name"
         android:excludeFromRecents="true"
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 9eda82a..3eb58f1 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -92,8 +92,8 @@
   <string name="close_sheet">"Close sheet"</string>
   <!-- Spoken content description of the back arrow button. -->
   <string name="accessibility_back_arrow_button">"Go back to the previous page"</string>
-  <!-- Spoken content description of the close button. -->
-  <string name="accessibility_close_button">"Close the Credential Manager action suggestion appearing at the bottom of the screen"</string>
+  <!-- Spoken content description of the close "X" icon button. -->
+  <string name="accessibility_close_button">Close</string>
 
   <!-- Strings for the get flow. -->
   <!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
@@ -120,6 +120,8 @@
   <string name="locked_credential_entry_label_subtext_tap_to_unlock">Tap to unlock</string>
   <!-- Explanatory label for a disabled button explaining that this option isn't viable because it does not contain any available credential (e.g. password, passkey, etc.) for the user. [CHAR LIMIT=120] -->
   <string name="locked_credential_entry_label_subtext_no_sign_in">No sign-in info</string>
+  <!-- Label displayed when a selected option does not contain any viable credentials that can be used to log into the app. [CHAR LIMIT=80] -->
+  <string name="no_sign_in_info_in">No sign-in info in <xliff:g id="source" example="becket@gmail.com">%1$s</xliff:g></string>
   <!-- Column heading for displaying action chips for managing sign-ins from each credential provider. [CHAR LIMIT=80] -->
   <string name="get_dialog_heading_manage_sign_ins">Manage sign-ins</string>
   <!-- Column heading for displaying option to use sign-ins saved on a different device. [CHAR LIMIT=80] -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index 30b4b86..f57d643 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -115,6 +115,11 @@
         }
     }
 
+    fun onLastLockedAuthEntryNotFoundError() {
+        Log.d(Constants.LOG_TAG, "Unable to find the last unlocked entry")
+        onInternalError()
+    }
+
     private fun onInternalError() {
         Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
         credManRepo.onParsingFailureCancel()
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 438978c..dc9bdec 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -79,7 +79,20 @@
     getCredentialUiState: GetCredentialUiState,
     providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
 ) {
-    if (getCredentialUiState.currentScreenState != GetScreenState.REMOTE_ONLY) {
+    if (getCredentialUiState.currentScreenState == GetScreenState.REMOTE_ONLY) {
+        RemoteCredentialSnackBarScreen(
+            onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
+            onCancel = viewModel::onCancel,
+        )
+    } else if (getCredentialUiState.currentScreenState
+        == GetScreenState.UNLOCKED_AUTH_ENTRIES_ONLY) {
+        EmptyAuthEntrySnackBarScreen(
+            authenticationEntryList =
+            getCredentialUiState.providerDisplayInfo.authenticationEntryList,
+            onCancel = viewModel::onCancel,
+            onLastLokcedAuthEntryNotFound = viewModel::onLastLockedAuthEntryNotFoundError,
+        )
+    } else {
         ModalBottomSheet(
             sheetContent = {
                 // Hide the sheet content as opposed to the whole bottom sheet to maintain the scrim
@@ -124,11 +137,6 @@
             },
             onDismiss = viewModel::onCancel,
         )
-    } else {
-        SnackBarScreen(
-            onClick = viewModel::getFlowOnMoreOptionOnSnackBarSelected,
-            onCancel = viewModel::onCancel,
-        )
     }
 }
 
@@ -622,7 +630,7 @@
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-fun SnackBarScreen(
+fun RemoteCredentialSnackBarScreen(
     onClick: (Boolean) -> Unit,
     onCancel: () -> Unit,
 ) {
@@ -653,4 +661,37 @@
     ) {
         Text(text = stringResource(R.string.get_dialog_use_saved_passkey_for))
     }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun EmptyAuthEntrySnackBarScreen(
+    authenticationEntryList: List<AuthenticationEntryInfo>,
+    onCancel: () -> Unit,
+    onLastLokcedAuthEntryNotFound: () -> Unit,
+) {
+    val lastLocked = authenticationEntryList.firstOrNull({it.isLastUnlocked})
+    if (lastLocked == null) {
+        onLastLokcedAuthEntryNotFound()
+        return
+    }
+
+    // TODO: Change the height, width and position according to the design
+    Snackbar(
+        modifier = Modifier.padding(horizontal = 40.dp).padding(top = 700.dp),
+        shape = EntryShape.FullMediumRoundedCorner,
+        containerColor = LocalAndroidColorScheme.current.colorBackground,
+        contentColor = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+        dismissAction = {
+            IconButton(onClick = onCancel) {
+                Icon(
+                    Icons.Filled.Close,
+                    contentDescription = stringResource(R.string.accessibility_close_button),
+                    tint = LocalAndroidColorScheme.current.colorAccentTertiary
+                )
+            }
+        },
+    ) {
+        Text(text = stringResource(R.string.no_sign_in_info_in, lastLocked.title))
+    }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index d04f926..49415c0 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -28,8 +28,8 @@
 data class GetCredentialUiState(
     val providerInfoList: List<ProviderInfo>,
     val requestDisplayInfo: RequestDisplayInfo,
-    val currentScreenState: GetScreenState = toGetScreenState(providerInfoList),
     val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerInfoList),
+    val currentScreenState: GetScreenState = toGetScreenState(providerDisplayInfo),
     val activeEntry: BaseEntry? = toActiveEntry(providerDisplayInfo),
     val isNoAccount: Boolean = false,
 )
@@ -167,6 +167,9 @@
 
     /** The snackbar only page when there's no account but only a remoteEntry. */
     REMOTE_ONLY,
+
+    /** The snackbar when there are only auth entries and all of them turn out to be empty. */
+    UNLOCKED_AUTH_ENTRIES_ONLY,
 }
 
 // IMPORTANT: new invocation should be mindful that this method will throw if more than 1 remote
@@ -174,7 +177,6 @@
 private fun toProviderDisplayInfo(
     providerInfoList: List<ProviderInfo>
 ): ProviderDisplayInfo {
-
     val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
     val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
     val remoteEntryList = mutableListOf<RemoteEntryInfo>()
@@ -241,22 +243,18 @@
 }
 
 private fun toGetScreenState(
-    providerInfoList: List<ProviderInfo>
+    providerDisplayInfo: ProviderDisplayInfo
 ): GetScreenState {
-    var noLocalAccount = true
-    var remoteInfo: RemoteEntryInfo? = null
-    providerInfoList.forEach { providerInfo ->
-        if (providerInfo.credentialEntryList.isNotEmpty() ||
-            providerInfo.authenticationEntryList.isNotEmpty()) {
-            noLocalAccount = false
-        }
-        if (providerInfo.remoteEntry != null) {
-            remoteInfo = providerInfo.remoteEntry
-        }
-    }
 
-    return if (noLocalAccount && remoteInfo != null)
-        GetScreenState.REMOTE_ONLY else GetScreenState.PRIMARY_SELECTION
+    return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
+        providerDisplayInfo.remoteEntry == null &&
+        providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
+        GetScreenState.UNLOCKED_AUTH_ENTRIES_ONLY
+    else if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
+        providerDisplayInfo.authenticationEntryList.isEmpty() &&
+        providerDisplayInfo.remoteEntry != null)
+        GetScreenState.REMOTE_ONLY
+    else GetScreenState.PRIMARY_SELECTION
 }
 
 internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> {
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index a7e44d3..006c9c1 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Het gefiltreer geaktiveer"</item>
     <item msgid="2779123106632690576">"Geaktiveer"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (verstek)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index b1f2cee..31f50e8 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Hierdie foon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Hierdie tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan nie op hierdie toestel speel nie"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Gradeer rekening op om oor te skakel"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Kan nie aflaaie hier speel nie"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Probeer weer ná die advertensie"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Maak toestel wakker om hier te speel"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Toestel is nie goedgekeur om te speel nie"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kan nie hierdie media hier speel nie"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en terugvoer"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 7bef7fa..43c89b1 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ማጣሪያን አንቃ"</item>
     <item msgid="2779123106632690576">"ነቅቷል"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ነባሪ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index cf4b62d..b9117ee 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ይህ ስልክ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ይህ ጡባዊ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"በዚህ መሣሪያ ላይ ማጫወት አልተቻለም"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ለመቀየር መለያ ያልቁ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ውርዶችን እዚህ ማጫወት አይቻልም"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ከማስታወቂያው በኋላ እንደገና ይሞክሩ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"እዚህ ጋር ለመጫወት መሣሪያን ያንቁ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"መሣሪያ ለማጫወት አልጸደቀም"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ይህን ሚዲያ እዚህ ጋር ማጫወት አይቻልም"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string>
     <string name="help_label" msgid="3528360748637781274">"እገዛ እና ግብረመልስ"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 0720cf5..1a16f5a 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"تمّ تفعيل التصفية"</item>
     <item msgid="2779123106632690576">"مفعّل"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (تلقائي)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 1b4b521..ef7bf08 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"هذا الهاتف"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"هذا الجهاز اللوحي"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"لا يمكن تشغيل الوسائط على هذا الجهاز."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"يجب ترقية الحساب للتبديل."</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"لا يمكن تشغيل المحتوى الذي تم تنزيله هنا."</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"يمكنك إعادة المحاولة بعد الإعلان."</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"يجب تنشيط الجهاز لتشغيل الوسائط هنا."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"غير مسموح لهذا الجهاز بتشغيل الوسائط."</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"لا يمكن تشغيل هذه الوسائط هنا."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
     <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات"</string>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index cbacce8..456fa3d 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"সক্ষম কৰাবিলাক ফিল্টাৰ কৰা হৈছে"</item>
     <item msgid="2779123106632690576">"সক্ষম কৰা আছে"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফ’ল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP ১.৩"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 454c6ed..67b18da 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"এই ফ’নটো"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"এই টেবলেটটো"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"এই ডিভাইচটো প্লে\' কৰিব নোৱাৰি"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"সলনি কৰিবলৈ একাউণ্ট আপগ্ৰে’ড কৰক"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ইয়াত ডাউনল’ডসমূহ প্লে’ কৰিব নোৱাৰি"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"বিজ্ঞাপনটোৰ পাছত পুনৰ চেষ্টা কৰক"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ইয়াত প্লে\' কৰিবলৈ ডিভাইচটো সক্ৰিয় কৰক"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"প্লে\' কৰিবলৈ ডিভাইচটো অনুমোদিত নহয়"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ইয়াত এই মিডিয়াটো প্লে\' কৰিব নোৱাৰি"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
     <string name="help_label" msgid="3528360748637781274">"সহায় আৰু মতামত"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index d1f157a..dacaaca 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrləmə aktivdir"</item>
     <item msgid="2779123106632690576">"Aktivdir"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Defolt)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index fa7af3b..000fd1b 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu planşet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oxutmaq mümkün deyil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Keçirmək üçün hesabı təkmilləşdirin"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Burada endirmələri oxutmaq mümkün deyil"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamdan sonra yenidən cəhd edin"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Burada oxutmaq üçün cihazı oyadın"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Cihaz oxudulmaq üçün təsdiqlənməyib"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Bu medianı burada oxutmaq mümkün deyil"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım və rəy"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 63b08fa..8e6fae6 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (podrazumevano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index ef74b68..6a9ba8a 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ne možete da pustite na ovom uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite nalog radi prebacivanja"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Preuzimanja ne mogu da se puštaju ovde"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Probajte ponovo posle oglasa"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Probudite uređaj da biste pustili ovde"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Uređaj nije odobren za reprodukciju"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Ne možete da pustite ovaj medijski fajl ovde"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index f16e1c5..ced9acf 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Уключана з фільтрацыяй"</item>
     <item msgid="2779123106632690576">"Уключана"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (стандартная)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 0c75f26..f93ca4b 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Гэты тэлефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Гэты планшэт"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не ўдаецца прайграць на гэтай прыладзе"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Для пераключэння перайдзіце на іншую версію ўліковага запісу"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Тут не ўдаецца прайграць спампоўкі"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Паўтарыце спробу пасля рэкламы"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Для прайгравання на гэтай прыладзе абудзіце яе"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Для прайгравання на прыладзе патрабуецца ўхваленне"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Тут не ўдаецца прайграць мультымедыя"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
     <string name="help_label" msgid="3528360748637781274">"Даведка і водгукі"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 849e694..c129304 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Филтрирането е активирано"</item>
     <item msgid="2779123106632690576">"Активирано"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (основно)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index cd5572a..650f405 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Този телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Този таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Възпроизвеждането не е възможно на това устройство"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надстройте профила, за да превключите"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Изтеглянията не могат да се възпроизвеждат тук"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Опитайте отново след рекламата"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Активирайте устройството, за да възпроизведете съдържанието тук"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Устройството не е одобрено да възпроизвежда съдържание"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Мултимедийното съдържание не може да се възпроизведе тук"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
     <string name="help_label" msgid="3528360748637781274">"Помощ и отзиви"</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index a3bc4fd..d583738 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ফিল্টার করা চালু আছে"</item>
     <item msgid="2779123106632690576">"চালু করা আছে"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 926ad84..c2e80b6 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
+    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
+    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Onemogućeno"</item>
+    <item msgid="5884245882825346396">"Čarolija"</item>
+    <item msgid="6569400572915342949">"Zaglavlje"</item>
+    <item msgid="1239386221416967664">"Potpuni filtar"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 574fa9d..e8cabfa 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nije moguće reproducirati na uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite račun da promijenite"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Nije moguće reproducirati preuzimanja ovdje"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Pokušajte ponovo nakon oglasa"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktivirajte uređaj da reproducirate ovdje"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Uređaj nije odobren za reprodukciju"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Nije moguće ovdje reproducirati medij"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 3062e7d..20a3d03 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Activat amb filtres"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminada)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 0ccd82a..83b32d4 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Aquest telèfon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Aquesta tauleta"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No es pot reproduir en aquest dispositiu"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualitza el compte per canviar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Les baixades no es poden reproduir aquí"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Torna-ho a provar després de l\'anunci"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activa el dispositiu per reproduir aquí"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"El dispositiu no està aprovat per reproduir contingut"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"No es pot reproduir aquest contingut multimèdia aquí"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda i suggeriments"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index e1d033c..ad6062c 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Povolit filtrované"</item>
     <item msgid="2779123106632690576">"Zapnuto"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (výchozí)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f2bf000..e511f04 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Na tomto zařízení média přehrávat nelze"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Pokud chcete přejít, upgradujte účet"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Stažený obsah zde nelze přehrát"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Zkuste to znovu po reklamě"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Pokud zde chcete přehrávat média, probuďte zařízení"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Zařízení není schváleno k přehrávání"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tato média zde přehrát nelze"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
     <string name="help_label" msgid="3528360748637781274">"Nápověda a zpětná vazba"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 48a33f6..6fc4714 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtreret er aktiveret"</item>
     <item msgid="2779123106632690576">"Aktiveret"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 9671f5e..c52c661 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Denne tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Indholdet kan ikke afspilles på denne enhed"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Opgrader kontoen for at skifte"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Downloads kan ikke afspilles her"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prøv igen efter annoncen"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Væk enheden for at afspille her"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheden er ikke godkendt til afspilning"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Mediet kan ikke afspilles her"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjælp og feedback"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index ca999db..636a7a4 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filter aktiviert"</item>
     <item msgid="2779123106632690576">"Aktiviert"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 9e77007..dd677c9 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Dieses Smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dieses Tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Wiedergabe auf diesem Gerät nicht möglich"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Zum Umstellen Kontoupgrade durchführen"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Downloads können hier nicht abgespielt werden"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Nach Werbung noch einmal versuchen"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Gerät aktivieren, um hier etwas wiedergeben zu lassen"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Gerät nicht für die Wiedergabe zugelassen"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Diese Medien können hier nicht wiedergegeben werden"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus &amp; und wieder ein."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
     <string name="help_label" msgid="3528360748637781274">"Hilfe und Feedback"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index b95f6fc..986adf5 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Ενεργοποιήθηκε το φιλτράρισμα"</item>
     <item msgid="2779123106632690576">"Ενεργοποιήθηκε"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Προεπιλογή)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 2ca882d..1e11424 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Αυτό το tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφωνο"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Δεν είναι δυνατή η αναπαραγωγή σε αυτήν τη συσκευή"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Αναβαθμίστε τον λογαριασμό για εναλλαγή"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Δεν είναι δυνατή η αναπαραγωγή των λήψεων εδώ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Δοκιμάστε ξανά μετά τη διαφήμιση"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Αφύπνιση συσκευής για αναπαραγωγή εδώ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Η συσκευή δεν έχει εγκριθεί για αναπαραγωγή"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Δεν είναι δυνατή η αναπαραγωγή αυτού του πολυμέσου εδώ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string>
     <string name="help_label" msgid="3528360748637781274">"Βοήθεια και σχόλια"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 327e4e9..de63386 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Headers filtered"</item>
+    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
+    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Disabled"</item>
+    <item msgid="5884245882825346396">"Magic"</item>
+    <item msgid="6569400572915342949">"Header"</item>
+    <item msgid="1239386221416967664">"Full filter"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 8a57232..0af8b4e 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Headers Filtered"</item>
+    <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
+    <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Disabled"</item>
+    <item msgid="5884245882825346396">"Magic"</item>
+    <item msgid="6569400572915342949">"Header"</item>
+    <item msgid="1239386221416967664">"Full Filter"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 327e4e9..de63386 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Headers filtered"</item>
+    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
+    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Disabled"</item>
+    <item msgid="5884245882825346396">"Magic"</item>
+    <item msgid="6569400572915342949">"Header"</item>
+    <item msgid="1239386221416967664">"Full filter"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 327e4e9..de63386 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Headers filtered"</item>
+    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
+    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Disabled"</item>
+    <item msgid="5884245882825346396">"Magic"</item>
+    <item msgid="6569400572915342949">"Header"</item>
+    <item msgid="1239386221416967664">"Full filter"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index 8af0a4a..30c9a49 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎Enabled Filtered‎‏‎‎‏‎"</item>
     <item msgid="2779123106632690576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎Enabled‎‏‎‎‏‎"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎Headers Filtered‎‏‎‎‏‎"</item>
+    <item msgid="4818549483446395865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎A2DP Media Packets Filtered‎‏‎‎‏‎"</item>
+    <item msgid="8207123990453243311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎RFCOMM Channel Filtered‎‏‎‎‏‎"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎Disabled‎‏‎‎‏‎"</item>
+    <item msgid="5884245882825346396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎Magic‎‏‎‎‏‎"</item>
+    <item msgid="6569400572915342949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎Header‎‏‎‎‏‎"</item>
+    <item msgid="1239386221416967664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎Full Filter‎‏‎‎‏‎"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎AVRCP 1.5 (Default)‎‏‎‎‏‎"</item>
     <item msgid="1637054408779685086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎AVRCP 1.3‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 3813808..e272cd5 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrado habilitado"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 3e97c32..fcb454a 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"No se pueden reproducir las descargas aquí"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Vuelve a intentarlo después del anuncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activa el dispositivo para reproducir aquí"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"El dispositivo no está aprobado para reproducir"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"No se puede reproducir el contenido multimedia aquí"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
@@ -585,7 +581,7 @@
     <string name="user_add_user_type_title" msgid="551279664052914497">"Agregar"</string>
     <string name="user_new_user_name" msgid="60979820612818840">"Usuario nuevo"</string>
     <string name="user_new_profile_name" msgid="2405500423304678841">"Perfil nuevo"</string>
-    <string name="user_info_settings_title" msgid="6351390762733279907">"Datos de usuario"</string>
+    <string name="user_info_settings_title" msgid="6351390762733279907">"Datos del usuario"</string>
     <string name="profile_info_settings_title" msgid="105699672534365099">"Datos del perfil"</string>
     <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar un bloqueo de pantalla que proteja tus aplicaciones y datos personales."</string>
     <string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 4924407..fc28d4ae 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Habilitado con filtros"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index eb176a9..7c8421f 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"No se puede reproducir contenido en este dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Actualiza la cuenta para cambiar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"No se pueden reproducir descargas aquí"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prueba de nuevo después del anuncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activa el dispositivo para reproducir contenido aquí"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Dispositivo no aprobado para reproducir contenido"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"No se puede reproducir el contenido multimedia aquí"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 0402ac2..282bfb1 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Luba filtreeritud"</item>
     <item msgid="2779123106632690576">"Lubatud"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (vaikeseade)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 3f0a6ed..fd9bcd6 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"See telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"See tahvelarvuti"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Selles seadmes ei saa esitada"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lülitamiseks täiendage kontot"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Siin ei saa allalaaditud faile esitada"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Proovige pärast reklaami uuesti"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Äratage seade siin esitamiseks"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Seade ei ole esitamiseks heaks kiidetud"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Seda meediat ei saa siin esitada"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
     <string name="help_label" msgid="3528360748637781274">"Abi ja tagasiside"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index d15712a..8cd3da8 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Gaituta baina iragazita"</item>
     <item msgid="2779123106632690576">"Gaituta"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (lehenetsia)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 4fe2e23..82e0eea 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefono hau"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tableta hau"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ezin da erreproduzitu gailu honetan"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Aldatzeko, bertsio-berritu kontua"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Deskargak ezin dira hemen erreproduzitu"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Saiatu berriro iragarkiaren ondoren"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktibatu gailua hemen erreproduzitzeko"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Gailua ez dago erreproduzitzeko onartuta"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Ezin da erreproduzitu multimedia-eduki hau hemen"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazo bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
     <string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 41410cb..3a7bada 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"فیلترشده فعال شده است"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP نسخه ۱.۵ (پیش‌فرض)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index c7f01af..0732fcf 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"این تلفن"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"این رایانه لوحی"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"نمی‌توان در این دستگاه پخش کرد"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"برای تغییر، حساب را ارتقا دهید"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"نمی‌توان بارگیری‌ها را در اینجا پخش کرد"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"بعداز آگهی دوباره امتحان کنید"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"برای پخش در اینجا، دستگاه را بیدار کنید"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"دستگاه برای پخش تأیید نشده است"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"نمی‌توان این رسانه را اینجا پخش کرد"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
     <string name="help_label" msgid="3528360748637781274">"راهنما و بازخورد"</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 842fb8f..541ae38 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Suodatus käytössä"</item>
     <item msgid="2779123106632690576">"Päällä"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (oletus)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index a81c176..089fa42 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tämä puhelin"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tämä tabletti"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ei voi toistaa tällä laitteella"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Vaihda päivittämällä tili"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Latauksia ei voi toistaa täällä"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Kokeile uudelleen mainoksen jälkeen"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktivoi laite, jotta voit toistaa sillä"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Laitetta ei ole hyväksytty toistoa varten"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Mediaa ei voi toistaa tällä"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
     <string name="help_label" msgid="3528360748637781274">"Ohje ja palaute"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index dfa6db3..4bcf9d2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtres activés"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6e1d09e..489bea1c 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de faire jouer le contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à jour le compte pour passer à la version payante"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Lecture des téléchargements impossible ici"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Réessayez après l\'annonce"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activer l\'appareil pour faire jouer le contenu ici"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"L\'appareil n\'est pas autorisé à faire jouer le contenu"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Impossible de faire jouer ce contenu multimédia ici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
     <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 92546da..b154354 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Activé et filtré"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index f74b2bb..a4d5f20 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ce téléphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Cette tablette"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossible de lire du contenu sur cet appareil"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Mettez à niveau le compte pour changer"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Impossible de lire les téléchargements ici"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Réessayez après l\'annonce"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activer l\'appareil pour lire du contenu ici"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Appareil non autorisé à lire du contenu"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Impossible de lire ce contenu multimédia ici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string>
     <string name="help_label" msgid="3528360748637781274">"Aide et commentaires"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index fb8e5f2..07c4b29 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Está activado o filtrado"</item>
     <item msgid="2779123106632690576">"Activada"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index d1d6afe..8aa4d62 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este teléfono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Esta tableta"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Non se pode reproducir contido neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Cambia a conta a un plan superior para facer a modificación"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Non se poden reproducir as descargas neste dispositivo"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Téntao de novo despois de que remate o anuncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activa o dispositivo para reproducir o contido aquí"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"O dispositivo non está autorizado para reproducir contido"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Non se pode reproducir este produto multimedia aquí"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
     <string name="help_label" msgid="3528360748637781274">"Axuda e comentarios"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index e527d81..69fe7bb 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ફિલ્ટર કરેલ ચાલુ છે"</item>
     <item msgid="2779123106632690576">"ચાલુ છે"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ડિફૉલ્ટ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 00435d8..e253bbf 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"આ ફોન"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"આ ટૅબ્લેટ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"આ ડિવાઇસ પર ચલાવી શકતા નથી"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"સ્વિચ કરવા માટે એકાઉન્ટ અપગ્રેડ કરો"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ડાઉનલોડ કરેલું કન્ટેન્ટ અહીં ચલાવી શકતા નથી"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"જાહેરાત પછી ફરીથી પ્રયાસ કરો"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"અહીં ચલાવવા માટે ડિવાઇસને સક્રિય કરો"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ડિવાઇસ દ્વારા ચલાવવાની મંજૂરી આપવામાં આવી નથી"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"અહીં આ મીડિયા ચલાવી શકતા નથી"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string>
     <string name="help_label" msgid="3528360748637781274">"સહાય અને પ્રતિસાદ"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 9b8d83e..5ed88a9 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"चालू और फ़िल्टर किया गया"</item>
     <item msgid="2779123106632690576">"चालू है"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index b5bee94..adf09d7 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यह फ़ोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यह टैबलेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"इस डिवाइस पर मीडिया नहीं चलाया जा सकता"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"प्रीमियम खाते में स्विच करने के लिए, अपना खाता अपग्रेड करें"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"डाउनलोड किए गए वीडियो यहां नहीं चलाए जा सकते"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"विज्ञापन खत्म होने के बाद फिर से कोशिश करें"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"मीडिया को यहां चलाने के लिए, डिवाइस को अनलॉक करें"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"डिवाइस को मीडिया चलाने की अनुमति नहीं दी गई है"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"इस मीडिया को यहां नहीं चलाया जा सकता"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"सहायता और सुझाव"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 559383a..812f8d2 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
+    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
+    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Onemogućeno"</item>
+    <item msgid="5884245882825346396">"Čarolija"</item>
+    <item msgid="6569400572915342949">"Zaglavlje"</item>
+    <item msgid="1239386221416967664">"Potpuni filtar"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index bf6ee8b..9489d6e 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ovaj telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ovaj tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nije moguće reproducirati na ovom uređaju"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nadogradite račun radi prebacivanja"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Preuzimanja se ne mogu reproducirati ovdje"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Pokušajte ponovo nakon oglasa"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Aktivirajte uređaj da biste na njemu reproducirali"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Uređaj nije odobren za reprodukciju"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Ti se mediji ne mogu reproducirati ovdje"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoć i povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 409d600..55a2d28 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Szűrtek engedélyezve"</item>
     <item msgid="2779123106632690576">"Engedélyezve"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (alapértelmezett)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 327acde..0d4d09d 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ez a telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ez a táblagép"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nem lehet tartalmat lejátszani ezen az eszközön"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"A váltáshoz frissítse fiókját magasabb kategóriára"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Itt nem lehet lejátszani a letöltött elemeket"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Próbálja újra a hirdetés után"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"A tartalom itteni lejátszásához ébressze fel az eszközt"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Az eszköz nem játszhat le tartalmat"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"A médiatartalom nem játszható le itt"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
     <string name="help_label" msgid="3528360748637781274">"Súgó és visszajelzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 009875d..d2c46ac 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Միացված է զտիչներով"</item>
     <item msgid="2779123106632690576">"Միացված է"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (կանխադրված)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 1e584f9..0a3161b 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Այս հեռախոսը"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Այս պլանշետը"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Հնարավոր չէ նվագարկել այս սարքում"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Փոխելու համար անցեք հաշվի պրեմիում տարբերակին"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Հնարավոր չէ նվագարկել ներբեռնումներն այստեղ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Նորից փորձեք գովազդից հետո"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Արթնացրեք սարքը՝ այստեղ նվագարկելու համար"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Նվագարկելու համար հաստատեք սարքը"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Չհաջողվեց նվագարկել մեդիա ֆայլն այստեղ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
     <string name="help_label" msgid="3528360748637781274">"Օգնություն և հետադարձ կապ"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 9527417..87cede7 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Diaktifkan Difilter"</item>
     <item msgid="2779123106632690576">"Diaktifkan"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index acedc1c..2ee096b 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -335,7 +335,7 @@
     <string name="enable_terminal_summary" msgid="2481074834856064500">"Aktifkan aplikasi terminal yang menawarkan akses kerangka lokal"</string>
     <string name="hdcp_checking_title" msgid="3155692785074095986">"Pemeriksaan HDCP"</string>
     <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Setel perilaku pemeriksaan HDCP"</string>
-    <string name="debug_debugging_category" msgid="535341063709248842">"Debugging"</string>
+    <string name="debug_debugging_category" msgid="535341063709248842">"Proses debug"</string>
     <string name="debug_app" msgid="8903350241392391766">"Pilih aplikasi debug"</string>
     <string name="debug_app_not_set" msgid="1934083001283807188">"Tidak ada aplikasi debug yang disetel"</string>
     <string name="debug_app_set" msgid="6599535090477753651">"Aplikasi debug: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ponsel ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat memutar di perangkat ini"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade akun untuk beralih"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tidak dapat memutar hasil download di sini"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Coba lagi setelah iklan"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Mengaktifkan perangkat untuk memutar di sini"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Perangkat tidak disetujui untuk memutar"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tidak dapat memutar media ini di sini"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat &amp; aktifkan kembali"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; masukan"</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 0b5b978..5c5841c 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Kveikt á síuðu"</item>
     <item msgid="2779123106632690576">"Kveikt"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (sjálfgefið)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index cf9d475..95dc268 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Þessi sími"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Þessi spjaldtölva"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ekki er hægt að spila í þessu tæki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppfærðu reikninginn til að skipta"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Ekki er hægt að spila niðurhal hér"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reyndu aftur eftir auglýsinguna"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Vektu tæki til að spila hér"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Tæki er ekki samþykkt til spilunar"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Ekki er hægt að spila þetta efni hér"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjálp og ábendingar"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index ae1e515..4cd775a 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtro attivo"</item>
     <item msgid="2779123106632690576">"Attiva"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (versione predefinita)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 524e83d..dc96364 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Questo telefono"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Questo tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Impossibile riprodurre su questo dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Esegui l\'upgrade dell\'account per cambiare"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Qui non è possibile riprodurre i download"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Riprova dopo l\'annuncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Riattiva il dispositivo per riprodurre qui"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Dispositivo non approvato per la riproduzione"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Impossibile riprodurre questo contenuto multimediale qui"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
     <string name="help_label" msgid="3528360748637781274">"Guida e feedback"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 5d72aff..a09bccb 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"המסננים המופעלים"</item>
     <item msgid="2779123106632690576">"מופעל"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ברירת המחדל)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index c1a2a4c..5c54d62 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"הטלפון הזה"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"הטאבלט הזה"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"לא ניתן להפעיל במכשיר הזה"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"צריך לשדרג את החשבון כדי לעבור"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"לא ניתן להפעיל את ההורדות כאן"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"אפשר לנסות שוב לאחר המודעה"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"צריך להוציא את המכשיר ממצב השינה כדי להפעיל כאן"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"המכשיר לא קיבל אישור להפעלה"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"אי אפשר להפעיל את המדיה הזו כאן"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
     <string name="help_label" msgid="3528360748637781274">"עזרה ומשוב"</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 775e31c..2090266 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"有効(フィルタ済み)"</item>
     <item msgid="2779123106632690576">"有効"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 7143f47..09984c2 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"このスマートフォン"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"このタブレット"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"このデバイスで再生できません"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"アカウントを更新して切り替えてください"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ダウンロードしたコンテンツをここでは再生できません"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"広告が表示されてから、もう一度試してください"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ここで再生するにはデバイスを起動してください"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"このデバイスでの再生が許可されていません"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"このメディアはここで再生できません"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
     <string name="help_label" msgid="3528360748637781274">"ヘルプとフィードバック"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index f3545b6..616633f 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"გაფილტრულის ჩართვა"</item>
     <item msgid="2779123106632690576">"ჩართულია"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ნაგულისხმევი)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 61bad37..2abd85a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ეს ტელეფონი"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ეს ტაბლეტი"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ამ მოწყობილობაზე დაკვრა შეუძლებელია"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"გადასართავად განაახლეთ ანგარიში"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"აქ ჩამოტვირთვების თამაში შეუძლებელია"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"სცადეთ ხელახლა რეკლამის შემდეგ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"დასაკრავად გამოაღვიძეთ ტელეფონი"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"მოწყობილობა არ არის ავტორიზებული დასაკრავად"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ამ მედიის აქ დაკვრა შეუძლებელია"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string>
     <string name="help_label" msgid="3528360748637781274">"დახმარება და გამოხმაურება"</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 3fd1b50..9aa8d85 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Сүзгіленгендері қосулы"</item>
     <item msgid="2779123106632690576">"Қосулы"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (әдепкі)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 111c6c2..ba68253 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Осы телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Осы планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Осы құрылғыда ойнату мүмкін емес."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Ауысу үшін аккаунтты жаңартыңыз."</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Жүктеп алынғандарды осы жерде ойнату мүмкін емес."</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Жарнамадан кейін қайталап көріңіз."</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Осы жерде ойнату үшін құрылғыны оятыңыз."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Ойнату үшін авторизация керек."</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Бұл мультимедиа файлын осы жерде ойнату мүмкін емес."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
     <string name="help_label" msgid="3528360748637781274">"Анықтама және пікір"</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 2269df1..c2c1290 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"បានបើក​ការត្រង"</item>
     <item msgid="2779123106632690576">"បាន​បើក"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (លំនាំដើម)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 36769b9..2e33159 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ថេប្លេតនេះ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"មិនអាចចាក់នៅលើ​ឧបករណ៍នេះបានទេ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ដំឡើងកម្រិតគណនី ដើម្បីប្ដូរ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"មិនអាចចាក់ខ្លឹមសារដែលបានទាញយកនៅទីនេះបានទេ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ព្យាយាមម្ដងទៀត បន្ទាប់ពីការផ្សាយពាណិជ្ជកម្ម"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ដាស់ឧបករណ៍ឱ្យចាក់នៅទីនេះ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ឧបករណ៍មិន​យល់ព្រមឱ្យចាក់ទេ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"មិនអាចចាក់មេឌៀនេះ​នៅទីនេះបានទេ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មាន​បញ្ហា​ក្នុងការ​ភ្ជាប់។ បិទ រួច​បើក​ឧបករណ៍​វិញ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍​សំឡេងប្រើខ្សែ"</string>
     <string name="help_label" msgid="3528360748637781274">"ជំនួយ និងមតិកែលម្អ"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 975f60f..22bfe22 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ಫಿಲ್ಟರ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
     <item msgid="2779123106632690576">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ಡೀಫಾಲ್ಟ್)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 42749bf..a3ce673 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ಈ ಟ್ಯಾಬ್ಲೆಟ್"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ಈ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ಬದಲಾಯಿಸಲು ಖಾತೆಯನ್ನು ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಿ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ಇಲ್ಲಿ ಡೌನ್‌ಲೋಡ್‌ಗಳನ್ನು ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ಜಾಹೀರಾತಿನ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧನವನ್ನು ಎಚ್ಚರಿಸಿ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ಸಾಧನವನ್ನು ಪ್ಲೇ ಮಾಡಲು ಅನುಮೋದಿಸಲಾಗಿಲ್ಲ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ಈ ಮಾಧ್ಯಮವನ್ನು ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
     <string name="help_label" msgid="3528360748637781274">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 16b840b..547eabf 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"필터링 사용 설정됨"</item>
     <item msgid="2779123106632690576">"사용 설정됨"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index a65afb1..27c5a70 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"이 휴대전화"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"태블릿"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"이 기기에서 재생할 수 없음"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"전환하려면 계정을 업그레이드하세요."</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"여기서 다운로드한 콘텐츠를 재생할 수 없습니다."</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"광고 후에 다시 시도해 주세요."</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"기기 절전 모드 해제 후 여기에서 재생"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"기기에서 재생을 승인하지 않음"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"여기에서 이 미디어를 재생할 수 없음"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
     <string name="help_label" msgid="3528360748637781274">"고객센터"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 700aae1..6e3cd74 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Чыпкалар иштетилди"</item>
     <item msgid="2779123106632690576">"Иштетилди"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Демейки)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index f893fa4..604731a 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ушул телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ушул планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Бул түзмөктө ойнотуу мүмкүн эмес"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Которулуу үчүн аккаунтуңузду жаңыртыңыз"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Жүктөлүп алынгандарды бул жерде ойнотуу мүмкүн эмес"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Жарнамадан кийин кайталап көрүңүз"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Угуу үчүн түзмөктү уйку режиминен чыгарыңыз"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Бул түзмөктө ойнотуу үчүн уруксат алуу керек"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Бул медианы ойнотуу мүмкүн эмес"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
     <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index f116e6f..b74aab74 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ເປີດການກັ່ນຕອງແລ້ວ"</item>
     <item msgid="2779123106632690576">"ເປີດໃຊ້ແລ້ວ"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 37ef733..5722f4f 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ແທັບເລັດນີ້"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ຫຼິ້ນຢູ່ອຸປະກອນນີ້ບໍ່ໄດ້"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ອັບເກຣດບັນຊີເພື່ອສະຫຼັບ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ບໍ່ສາມາດຫຼິ້ນເນື້ອຫາທີ່ດາວໂຫຼດຢູ່ນີ້ໄດ້"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ລອງໃໝ່ຫຼັງຈາກໂຄສະນາ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ປຸກອຸປະກອນເພື່ອຫຼິ້ນຢູ່ບ່ອນນີ້"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ອຸປະກອນບໍ່ອະນຸມັດໃຫ້ຫຼິ້ນ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ຫຼິ້ນມີເດຍນີ້ຢູ່ບ່ອນນີ້ບໍ່ໄດ້"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string>
     <string name="help_label" msgid="3528360748637781274">"ຊ່ວຍເຫຼືອ ແລະ ຕິຊົມ"</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index c0aafdc..a25078c 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Įgalinta filtruota"</item>
     <item msgid="2779123106632690576">"Įgalinta"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (numatytoji)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 05c65c4..949a865 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis telefonas"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetinis kompiuteris"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Negalima leisti šiame įrenginyje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Jei norite perjungti, naujovinkite paskyrą"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Čia negalima paleisti atsisiuntimų"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Bandykite dar kartą po skelbimo"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Pažadinkite įrenginį, kad galėtumėte čia leisti"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Įrenginys nepatvirtintas, kad būtų galima leisti"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Čia negalima leisti šio medijos failo"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
     <string name="help_label" msgid="3528360748637781274">"Pagalba ir atsiliepimai"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 0f9ee52..908ebf8 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Iespējot filtrētos"</item>
     <item msgid="2779123106632690576">"Iespējots"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (noklusējums)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b125b40..0e23cee 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Šis tālrunis"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Šis planšetdators"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nevar atskaņot šajā ierīcē."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Lai pārslēgtu, jauniniet kontu"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Šeit nevar atskaņot lejupielādes"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Mēģiniet vēlreiz, kad beigsies reklāma"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Lai atskaņotu šeit, aktivizējiet ierīci."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Ierīce nav apstiprināta atskaņošanai."</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Šo multivides saturu nevar atskaņot šeit."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
     <string name="help_label" msgid="3528360748637781274">"Palīdzība un atsauksmes"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 41427c1..98b3de2 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Овозможено е филтрирано"</item>
     <item msgid="2779123106632690576">"Овозможено"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Стандардна)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index a843ea1..f57412c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овој телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овој таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не може да се пушти на уредов"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надградете ја сметката за да се префрлите"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Не може да се пуштаат преземања тука"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Обидете се повторно по рекламата"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Разбудете го уредот за да пуштате овде"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Уредот не е одобрен за репродукција"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Не може да се пуштат аудиовизуелните содржини овде"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
     <string name="help_label" msgid="3528360748637781274">"Помош и повратни информации"</string>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 98e3bd6..75a5921 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ഫിൽട്ടറിംഗ് പ്രവർത്തനക്ഷമമാക്കി"</item>
     <item msgid="2779123106632690576">"പ്രവർത്തനക്ഷമമാക്കി"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ഡിഫോൾട്ട്)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index da27136..6d39bc2 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ഈ ടാബ്‌ലെറ്റ്"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ഈ ഉപകരണത്തിൽ പ്ലേ ചെയ്യാൻ കഴിയില്ല"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"അക്കൗണ്ട് മാറുന്നതിന്, അത് അപ്‌ഗ്രേഡ് ചെയ്യുക"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ഡൗൺലോഡ് ചെയ്തവ ഇവിടെ പ്ലേ ചെയ്യാനാകില്ല"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"പരസ്യത്തിന് ശേഷം വീണ്ടും ശ്രമിക്കുക"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ഇവിടെ പ്ലേ ചെയ്യാൻ ഉപകരണം സജീവമാക്കുക"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ഉപകരണത്തിന് പ്ലേ ചെയ്യാനുള്ള അനുമതിയില്ല"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ഈ മീഡിയ ഇവിടെ പ്ലേ ചെയ്യാൻ കഴിയില്ല"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്‌റ്റ് ചെയ്യുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string>
     <string name="help_label" msgid="3528360748637781274">"സഹായവും ഫീഡ്‌ബാക്കും"</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index f3c10d7..2ca88a5 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Идэвхжүүлсэн Шүүсэн"</item>
     <item msgid="2779123106632690576">"Идэвхжүүлсэн"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Өгөгдмөл)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 0af5596..b1c25f5 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Энэ утас"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Энэ таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Энэ төхөөрөмжид тоглуулах боломжгүй"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Сэлгэхийн тулд бүртгэлийг сайжруулна уу"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Татаж авсан файлыг энд тоглуулах боломжгүй"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Зарын дараа дахин оролдоно уу"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Энд тоглуулахын тулд төхөөрөмжийг сэрээнэ үү"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Төхөөрөмжийг тоглуулахыг зөвшөөрөөгүй"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Энэ медиаг энд тоглуулах боломжгүй"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
     <string name="help_label" msgid="3528360748637781274">"Тусламж, санал хүсэлт"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index c37baaa2..eaf4c66 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर केलेले सुरू केले"</item>
     <item msgid="2779123106632690576">"सुरू केले"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डीफॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 9773ecf..b015ba8 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"हा फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"हा टॅबलेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"या डिव्हाइसवर प्ले करू शकत नाही"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"स्विच करण्यासाठी खाते अपग्रेड करा"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"येथे डाउनलोड प्ले केले जाऊ शकत नाही"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"जाहिरातीनंतर पुन्हा प्रयत्न करा"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"येथे प्ले करण्यासाठी डिव्हाइस सुरू करा"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"प्ले करण्यासाठी डिव्हाइस हे मंजुरी दिलेले नाही"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"हा मीडिया येथे प्ले करू शकत नाही"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्‍ट करण्‍यात समस्‍या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
     <string name="help_label" msgid="3528360748637781274">"मदत आणि फीडबॅक"</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index b19f038..727f475 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Didayakan Ditapis"</item>
     <item msgid="2779123106632690576">"Didayakan"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Lalai)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 6e7d430..c557bfd 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Telefon ini"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tablet ini"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Tidak dapat dimainkan pada peranti ini"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Tingkatkan akaun untuk bertukar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tidak dapat memainkan muat turun di sini"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Cuba lagi selepas iklan"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Bangkitkan peranti untuk main di sini"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Peranti tidak diluluskan untuk main"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tidak dapat memainkan media ini di sini"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan &amp; hidupkan kembali peranti"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
     <string name="help_label" msgid="3528360748637781274">"Bantuan &amp; maklum balas"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 3398c5b..768b749 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"စစ်ထုတ်ထားသည်များကို ဖွင့်ထားသည်"</item>
     <item msgid="2779123106632690576">"ဖွင့်ထားသည်"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (မူလ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 197143a..dc013d5 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ဤဖုန်း"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ဤတက်ဘလက်"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ဤစက်ပစ္စည်းတွင် ဖွင့်၍မရပါ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ပြောင်းရန်အကောင့်ကို အဆင့်မြှင့်ပါ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ဤနေရာတွင် ဒေါင်းလုဒ်များကို ဖွင့်၍မရပါ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ကြော်ငြာအပြီးတွင် ထပ်စမ်းကြည့်ပါ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ဤနေရာတွင်ဖွင့်ရန် စက်ပစ္စည်းကိုနှိုးပါ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"စက်ပစ္စည်းက ဖွင့်ခွင့်မပြုပါ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ဤမီဒီယာကို ဒီမှာဖွင့်၍မရပါ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
     <string name="help_label" msgid="3528360748637781274">"အကူအညီနှင့် အကြံပြုချက်"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 928ebc3..6f2370d 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering er slått på"</item>
     <item msgid="2779123106632690576">"Slått på"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d021702..2a14766 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Denne telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Dette nettbrettet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan ikke spille på denne enheten"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oppgrader kontoen for å bytte"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Kan ikke spille av nedlastinger her"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Prøv igjen etter annonsen"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Vekk enheten for å spille her"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten er ikke godkjent for avspilling"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kan ikke spille dette medieinnholdet her"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjelp og tilbakemelding"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index ac1f187..46edebe 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
     <item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP १.५ (डिफल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP १.३"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index c024503..ae7e8b3 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"यो फोन"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"यो ट्याब्लेट"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"यो डिभाइसमा मिडिया प्ले गर्न मिल्दैन"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"आफूले प्रयोग गर्न चाहेको खाता अपग्रेड गर्नुहोस्"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"डाउनलोड गरिएका सामग्री यहाँ प्ले गर्न मिल्दैन"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"विज्ञापन सकिएपछि फेरि प्रयास गर्नुहोस्"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"यो मिडिया यहाँ प्ले गर्न डिभाइस सक्रिय गर्नुहोस्"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"यो डिभाइसलाई मिडिया प्ले गर्ने अनुमोदन दिइएको छैन"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"यो मिडिया यहाँ प्ले गर्न मिल्दैन"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि अन गर्नुहोस्"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
     <string name="help_label" msgid="3528360748637781274">"मद्दत र प्रतिक्रिया"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 7c90eab..b839ffe7 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Gefilterd staat aan"</item>
     <item msgid="2779123106632690576">"Aangezet"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standaard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 3090990..55852d2 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Deze telefoon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Deze tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Kan niet afspelen op dit apparaat"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Upgrade het account om te schakelen"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Kan hier geen downloads afspelen"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Probeer het na de advertentie nog een keer"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activeer het apparaat om hier af te spelen"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Apparaat niet goedgekeurd voor afspelen"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kan deze media hier niet afspelen"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Zet het apparaat uit en weer aan."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
     <string name="help_label" msgid="3528360748637781274">"Hulp en feedback"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index a6c40b0..57da268 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ଫିଲ୍ଟର୍‌କୁ ସକ୍ଷମ କରାଯାଇଛି"</item>
     <item msgid="2779123106632690576">"ସକ୍ଷମ କରାଯାଇଛି"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ଡିଫଲ୍ଟ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index a509f31..1e61b24 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ଏହି ଟାବଲେଟ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ଏହି ଡିଭାଇସରେ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ସ୍ୱିଚ କରିବା ପାଇଁ ଆକାଉଣ୍ଟକୁ ଅପଗ୍ରେଡ କରନ୍ତୁ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ଏଠାରେ ଡାଉନଲୋଡଗୁଡ଼ିକୁ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ବିଜ୍ଞାପନ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ଏଠାରେ ପ୍ଲେ କରିବା ପାଇଁ ଡିଭାଇସକୁ ସକ୍ରିୟ କରନ୍ତୁ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ପ୍ଲେ କରିବା ପାଇଁ ଡିଭାଇସକୁ ଅନୁମୋଦନ କରାଯାଇନାହିଁ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ଏଠାରେ ମିଡିଆ ପ୍ଲେ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
     <string name="help_label" msgid="3528360748637781274">"ସାହାଯ୍ୟ ଓ ମତାମତ"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 0fd5c56..083f5aa 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ਫਿਲਟਰ ਕੀਤਿਆਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</item>
     <item msgid="2779123106632690576">"ਚਾਲੂ"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index dcff45c..d4b7632 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ਇਹ ਟੈਬਲੈੱਟ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"ਸਵਿੱਚ ਕਰਨ ਲਈ ਖਾਤੇ ਨੂੰ ਅੱਪਗ੍ਰੇਡ ਕਰੋ"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ਡਾਊਨਲੋਡਾਂ ਨੂੰ ਇੱਥੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ਵਿਗਿਆਪਨ ਤੋਂ ਬਾਅਦ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ਇੱਥੇ ਮੀਡੀਆ ਚਲਾਉਣ ਲਈ ਡੀਵਾਈਸ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ਡੀਵਾਈਸ ਨੂੰ ਮੀਡੀਆ ਚਲਾਉਣ ਦੀ ਮਨਜ਼ੂਰੀ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ਇਸ ਮੀਡੀਆ ਨੂੰ ਇੱਥੇ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string>
     <string name="help_label" msgid="3528360748637781274">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 71ecd46..87aeb50 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrowanie włączone"</item>
     <item msgid="2779123106632690576">"Włączono"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 0f51432..84aa66a 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ten telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ten tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nie można odtworzyć na tym urządzeniu"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uaktualnij konto, aby przełączyć"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tutaj nie można odtworzyć pobranych plików"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Spróbuj ponownie po reklamie"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Wybudź urządzenie, aby odtworzyć tutaj"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Urządzenie nie ma uprawnień do odtwarzania"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Nie można odtworzyć tego pliku multimedialnego"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoc i opinie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index f218fab..b64383f 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 14f2e60..168207d 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível abrir os downloads aqui"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Tente de novo depois do anúncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ativar dispositivo para tocar aqui"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"O dispositivo não foi aprovado para reprodução"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Não é possível reproduzir essa mídia aqui"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index e323455..b134be6 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -50,8 +50,8 @@
   </string-array>
   <string-array name="hdcp_checking_titles">
     <item msgid="2377230797542526134">"Nunca verificar"</item>
-    <item msgid="3919638466823112484">"Verificar apenas conteúdo DRM"</item>
-    <item msgid="9048424957228926377">"Verificar sempre"</item>
+    <item msgid="3919638466823112484">"Rever apenas conteúdo DRM"</item>
+    <item msgid="9048424957228926377">"Rever sempre"</item>
   </string-array>
   <string-array name="hdcp_checking_summaries">
     <item msgid="4045840870658484038">"Nunca utilizar a verificação HDCP"</item>
@@ -63,6 +63,17 @@
     <item msgid="6336372935919715515">"Filtrado ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
+  <string-array name="bt_hci_snoop_log_filters_entries">
+    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
+    <item msgid="4818549483446395865">"Pacotes de multimédia A2DP filtrados"</item>
+    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
+  </string-array>
+  <string-array name="bt_hci_snoop_log_profile_filter_entries">
+    <item msgid="6348114316510677939">"Desativado"</item>
+    <item msgid="5884245882825346396">"Magia"</item>
+    <item msgid="6569400572915342949">"Cabeçalho"</item>
+    <item msgid="1239386221416967664">"Filtro completo"</item>
+  </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predefinição)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index c6cb7ae..91d1204 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -325,8 +325,8 @@
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revogar acesso à depuração USB de todos os computadores anteriormente autorizados?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permitir definições de programação?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Estas definições destinam-se apenas a programação. Podem fazer com que o seu aparelho e as aplicações nele existentes falhem ou funcionem mal."</string>
-    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verificar apps por USB"</string>
-    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso"</string>
+    <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Rever apps por USB"</string>
+    <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Rever as aplicações instaladas via ADB/ADT para detetar comportamento perigoso"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"São apresentados os dispositivos Bluetooth sem nomes (apenas endereços MAC)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo"</string>
     <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ativa a pilha de funcionalidades Bluetooth Gabeldorche."</string>
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este telemóvel"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Atualize a conta para mudar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível reproduzir as transferências aqui"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Tente novamente depois do anúncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ative o dispositivo para reproduzir aqui"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Dispositivo não aprovado para reprodução"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Não é possível reproduzir este conteúdo multimédia aqui"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e comentários"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index f218fab..b64383f 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 14f2e60..168207d 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Este smartphone"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Este tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Não é possível reproduzir neste dispositivo"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Faça upgrade da conta para trocar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Não é possível abrir os downloads aqui"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Tente de novo depois do anúncio"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ativar dispositivo para tocar aqui"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"O dispositivo não foi aprovado para reprodução"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Não é possível reproduzir essa mídia aqui"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajuda e feedback"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index faa15c2..8062339 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Este activat Filtrat"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (prestabilit)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 23e6459..dba7507 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Acest telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Această tabletă"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nu se poate reda pe acest dispozitiv"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Fă upgrade contului pentru a comuta"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Aici nu se pot reda descărcări"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Încearcă din nou după anunț"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Activează dispozitivul pentru a reda aici"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Dispozitivul nu este aprobat pentru redare"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Conținutul media nu poate fi redat aici"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Oprește și repornește dispozitivul."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
     <string name="help_label" msgid="3528360748637781274">"Ajutor și feedback"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 4b6e692..5f7597d 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Включены фильтры"</item>
     <item msgid="2779123106632690576">"Включено"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (по умолчанию)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index a437153..76d163c 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Этот смартфон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Этот планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Невозможно воспроизвести на этом устройстве."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Для переключения требуется премиум-аккаунт"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Не удается воспроизвести скачанные файлы"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Повторите попытку после просмотра объявления"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Для воспроизведения выведите устройство из спящего режима."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Для воспроизведения необходима авторизация."</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Невозможно воспроизвести медиафайл."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
     <string name="help_label" msgid="3528360748637781274">"Справка/отзыв"</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index eaacfb8..b03b811 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"සබල පෙරහන් කළ"</item>
     <item msgid="2779123106632690576">"සබලයි"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (පෙරනිමි)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 9887eb7..5ba553d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"මෙම ටැබ්ලටය"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"මෙම උපාංගය මත ධාවනය කළ නොහැක"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"මාරු වීමට ගිණුම උත්ශ්‍රේණි කරන්න"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"මෙහි බාගැනීම් වාදනය කළ නොහැක"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"දැන්වීමෙන් පසු නැවත උත්සාහ කරන්න"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"මෙහි වාදනය කිරීමට උපාංගය අවදි කරන්න"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"උපාංගය වාදනය කිරීමට අනුමත කර නැත"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"මෙම මාධ්‍ය මෙහි වාදනය කළ නොහැක"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්‍රියාවිරහිත කර &amp; ආපසු ක්‍රියාත්මක කරන්න"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
     <string name="help_label" msgid="3528360748637781274">"උදවු &amp; ප්‍රතිපෝෂණ"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index bbfe969..902531c 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Aktivované filtrované"</item>
     <item msgid="2779123106632690576">"Aktivované"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predvolené)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e4c2b20..5e56aba6 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Tento telefón"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Tento tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"V tomto zariadení sa nedá prehrávať obsah"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Inovujte účet a prejdite naň"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tu sa nedajú prehrať stiahnuté súbory"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Skúste to znova po reklame"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ak chcete prehrávať obsah tu, prebuďte zariadenie"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Prehrávanie v tomto zariadení nie je schválené"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Tu sa toto médium nedá prehrať"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomocník a spätná väzba"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index b2003e5..ef5bf53 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Omogočeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogočeno"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (privzeto)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 02991c4..dc65447 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ta telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ta tablični računalnik"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ni mogoče predvajati v tej napravi."</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Za preklop je potrebna nadgradnja računa"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Tukaj ni mogoče predvajati prenosov"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Poskusite znova po oglasu"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Zbudite napravo, če želite predvajati tukaj."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Naprava ni odobrena za predvajanje."</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Te predstavnosti ni mogoče predvajati tukaj."</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
     <string name="help_label" msgid="3528360748637781274">"Pomoč in povratne informacije"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index ed86380..c31d4fb 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Të aktivizuara të filtruara"</item>
     <item msgid="2779123106632690576">"Aktiv"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (I parazgjedhur)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 9ff415d..e61c34a 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ky telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ky tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Nuk mund të luhet në këtë pajisje"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Përmirëso llogarinë për të ndryshuar"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Shkarkimet nuk mund të luhen këtu"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Provo përsëri pas reklamës"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Riaktivizoje pajisjen për të luajtur këtu"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Pajisja nuk është miratuar për të luajtur"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Kjo media nuk mund të luhet këtu"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
     <string name="help_label" msgid="3528360748637781274">"Ndihma dhe komentet"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index a95e47b..e5a9f50 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Омогућено филтрирано"</item>
     <item msgid="2779123106632690576">"Омогућено"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (подразумевано)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4d2352d..cfac256 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Овај телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Овај таблет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можете да пустите на овом уређају"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Надоградите налог ради пребацивања"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Преузимања не могу да се пуштају овде"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Пробајте поново после огласа"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Пробудите уређај да бисте пустили овде"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Уређај није одобрен за репродукцију"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Не можете да пустите овај медијски фајл овде"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
     <string name="help_label" msgid="3528360748637781274">"Помоћ и повратне информације"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index c63465c..4f4ded1 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering har aktiverats"</item>
     <item msgid="2779123106632690576">"Aktiverad"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d8dc9f6..99b8c4f 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Den här telefonen"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Den här surfplattan"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Det går inte att spela upp denna enhet"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Uppgradera kontot för att byta"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Det går inte att spela upp nedladdningar här"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Försök igen efter annonsen"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Väck enheten för att spela upp här"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Enheten har inte godkänts för uppspelning"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Det går inte att spela upp detta här"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
     <string name="help_label" msgid="3528360748637781274">"Hjälp och feedback"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 6ed4d5a..aee1cde 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Vichujio Vilivyowekwa"</item>
     <item msgid="2779123106632690576">"Imewashwa"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Chaguomsingi)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 414c218..ce3068f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Simu hii"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Kompyuta kibao hii"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Huwezi kucheza maudhui kwenye kifaa hiki"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Pata toleo jipya la akaunti ili ubadilishe"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Imeshindwa kucheza maudhui yaliyopakuliwa hapa"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Jaribu tena baada ya tangazo"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Washa skrini ya kifaa ili ucheze maudhui hapa"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Kifaa hakijaidhinishwa ili kucheza maudhui"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Huwezi kucheza maudhui haya hapa"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string>
     <string name="help_label" msgid="3528360748637781274">"Usaidizi na maoni"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 236f899..9fd1b6e 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"இயக்கப்பட்டு வடிகட்டப்பட்டது"</item>
     <item msgid="2779123106632690576">"இயக்கப்பட்டது"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (இயல்பு)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 3b11cab..ea12899 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"இந்த மொபைல்"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"இந்த டேப்லெட்"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"இந்தச் சாதனத்தில் பிளே செய்ய முடியவில்லை"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"மாற்ற, கணக்கை மேம்படுத்துங்கள்"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"பதிவிறக்கங்களை இங்கே பிளே செய்ய முடியாது"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"விளம்பரம் முடிந்த பிறகு மீண்டும் முயலுங்கள்"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"இங்கே பிளே செய்ய உங்கள் சாதனத்தைச் சார்ஜ் செய்யுங்கள்"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"பிளே செய்வதற்குச் சாதனம் அனுமதிக்கப்படவில்லை"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"இந்த மீடியாவை இங்கே பிளே செய்ய முடியவில்லை"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string>
     <string name="help_label" msgid="3528360748637781274">"உதவியும் கருத்தும்"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index fb4cff1..c4494f9 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"ప్రారంభించబడింది ఫిల్టర్ చేయబడింది"</item>
     <item msgid="2779123106632690576">"ప్రారంభించబడింది"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.4 (ఆటోమేటిక్ సెట్టింగ్)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index d539a3d..ed91fea 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"ఈ ఫోన్"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"ఈ టాబ్లెట్"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"ఈ పరికరంలో ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"మారడానికి ఖాతాను అప్‌గ్రేడ్ చేయండి"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ఇక్కడ డౌన్‌లోడ్‌లను ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"యాడ్ తర్వాత మళ్లీ ట్రై చేయండి"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ఇక్కడ ప్లే చేయడానికి పరికరాన్ని మేల్కొలపండి"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"ప్లే చేయడానికి పరికరానికి అధికారం ఇవ్వలేదు"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"ఇక్కడ ఈ మీడియాను ప్లే చేయడం సాధ్యపడదు"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
     <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 782e95e..1fb18a0 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"เปิดใช้รายการที่กรอง"</item>
     <item msgid="2779123106632690576">"เปิดใช้"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ค่าเริ่มต้น)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index beabce4..a1dec58 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"แท็บเล็ตเครื่องนี้"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"เล่นในอุปกรณ์นี้ไม่ได้"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"อัปเกรดบัญชีเพื่อเปลี่ยน"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"เล่นเนื้อหาที่ดาวน์โหลดที่นี่ไม่ได้"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"ลองอีกครั้งหลังจากโฆษณา"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"ปลุกระบบอุปกรณ์เพื่อเล่นที่นี่"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"อุปกรณ์ไม่อนุมัติให้เล่น"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"เล่นสื่อนี้ที่นี่ไม่ได้"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
     <string name="help_label" msgid="3528360748637781274">"ความช่วยเหลือและความคิดเห็น"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 19d3423..7b55436 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Na-enable Na-filter"</item>
     <item msgid="2779123106632690576">"Naka-enable"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 53b6d8e..7847da6 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Ang teleponong ito"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Ang tablet na ito"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Hindi ma-play sa device na ito"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"I-upgrade ang account para lumipat"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Hindi mape-play ang mga download dito"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Subukan ulit pagkatapos ng ad"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"I-wake ang device para i-play dito"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Hindi naaprubahan ang device para sa pag-play"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Hindi ma-play ang media na ito rito"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
     <string name="help_label" msgid="3528360748637781274">"Tulong at feedback"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 37891ae..016b5a9 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Etkin Filtrelenmiş"</item>
     <item msgid="2779123106632690576">"Etkin"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Varsayılan)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 7110381..86d53e7 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Bu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Bu tablet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu cihazda oynatılamıyor"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Geçiş yapmak için hesabı yükseltin"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"İndirilenler burada oynatılamıyor"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamdan sonra tekrar deneyin"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Burada oynatmak için cihazı uyandırın"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Cihaz, oynatma işlemini onaylamadı"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Bu medya burada oynatılamıyor"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
     <string name="help_label" msgid="3528360748637781274">"Yardım ve geri bildirim"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index c32da85..ff19fa3 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Увімкнено з фільтром"</item>
     <item msgid="2779123106632690576">"Увімкнено"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (за умовчанням)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 54ef3a4a..92c0e11 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Цей телефон"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Цей планшет"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Не можна відтворювати медіаконтент на цьому пристрої"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Щоб змінити, перейдіть на платний обліковий запис"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Тут не можна відтворювати завантажений контент"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Повторіть спробу після реклами"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Виведіть пристрій із режиму сну, щоб відтворювати медіаконтент"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Пристрій не схвалений для відтворення медіаконтенту"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"На пристрої не можна відтворювати цей медіафайл"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
     <string name="help_label" msgid="3528360748637781274">"Довідка й відгуки"</string>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index db9941e..09cd765 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"فعال کردہ فلٹر کردہ"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ڈیفالٹ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index b1bd695..94bb557 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"یہ فون"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"یہ ٹیبلیٹ"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"اس آلے پر چلایا نہیں جا سکتا"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"سوئچ کرنے کے لیے اکاؤنٹ اپ گریڈ کریں"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"ڈاؤن لوڈز کو یہاں چلایا نہیں جا سکتا"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"اشتہار کے بعد پھر سے کوشش کریں"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"یہاں چلانے کے لیے آلہ کو اٹھائیں"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"آلہ کو چلانے کے لیے اجازت نہیں دی گئی ہے"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"یہاں اس میڈیا کو چلایا نہیں جا سکتا"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
     <string name="help_label" msgid="3528360748637781274">"مدد اور تاثرات"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index edbd180..0893e06 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Filtrlar yoniq"</item>
     <item msgid="2779123106632690576">"Yoniq"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (asosiy)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 2df56d7..48705dd 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Shu telefon"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Shu planshet"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Bu qurilmada ijro etilmaydi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Oʻtish uchun hisobingizni yangilang"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Yuklab olingan fayllar ijro etilmaydi"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Reklamadan keyin qayta urining"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Ijro etish uchun qurilmani uyqu rejimidan chiqaring."</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Qurilmaga ijro etish uchun ruxsat berilmagan"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Media fayl ijro etilmaydi"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
     <string name="help_label" msgid="3528360748637781274">"Yordam/fikr-mulohaza"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index ee599d6..fd9ac04 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Đã bật và lọc"</item>
     <item msgid="2779123106632690576">"Đã bật"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Mặc định)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index e4f392f..1b7d651 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Điện thoại này"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Máy tính bảng này"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Không phát được trên thiết bị này"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Nâng cấp tài khoản để chuyển đổi"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Không thể phát các tệp đã tải xuống tại đây"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Thử lại sau quảng cáo"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Đánh thức thiết bị để phát tại đây"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Thiết bị chưa được phép phát"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Không thể phát nội dung nghe nhìn này tại đây"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
     <string name="help_label" msgid="3528360748637781274">"Trợ giúp và phản hồi"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 2a85d31..1b856c7 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"已启用“已过滤”"</item>
     <item msgid="2779123106632690576">"已启用"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 1cf0acf..1716124 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"这部手机"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"这台平板电脑"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"无法在此设备上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"升级帐号后才能切换"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"无法在此设备上播放下载的内容"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"广告之后重试"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"若要在此设备上播放,请唤醒设备"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"设备未获准播放"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"无法在此设备上播放该媒体内容"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
     <string name="help_label" msgid="3528360748637781274">"帮助和反馈"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index a84f0e2..6170f4a 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index d195cf8..56f17fa 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"此手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"此平板電腦"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在此裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"無法在此播放下載內容"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"請在廣告結束後再試一次"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"喚醒裝置即可在此播放"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"裝置未獲核准播放"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"無法在此播放此媒體內容"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見反映"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index b69fd53..9241798 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選結果"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9511db8..8bfbd7a 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"這支手機"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"這台平板電腦"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"無法在這部裝置上播放"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"請升級要切換的帳戶"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"這裡無法播放下載內容"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"請在廣告結束後再試一次"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"必須喚醒裝置才能在此播放"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"裝置未獲准播放"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"無法在此播放這個媒體內容"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
     <string name="help_label" msgid="3528360748637781274">"說明與意見回饋"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 0494f1c..f36d99c 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -63,6 +63,13 @@
     <item msgid="6336372935919715515">"Okuhlungiwe okunikwe amandla"</item>
     <item msgid="2779123106632690576">"Kunikwe amandla"</item>
   </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (5118179698172834473) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (4818549483446395865) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8207123990453243311) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (6348114316510677939) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (5884245882825346396) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (6569400572915342949) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1239386221416967664) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"I-AVRCP 1.5 (Okuzenzakalelayo)"</item>
     <item msgid="1637054408779685086">"I-AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index e921efc..6c35510 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -540,17 +540,13 @@
     <string name="media_transfer_this_device_name" product="default" msgid="2357329267148436433">"Le foni"</string>
     <string name="media_transfer_this_device_name" product="tablet" msgid="3714653244000242800">"Le thebulethi"</string>
     <string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
-    <!-- no translation found for media_output_status_unknown_error (5098565887497902222) -->
-    <skip />
+    <string name="media_output_status_unknown_error" msgid="5098565887497902222">"Ayikwazi ukudlala kule divayisi"</string>
     <string name="media_output_status_require_premium" msgid="8411255800047014822">"Thuthukisa i-akhawunti ukuze ushintshe"</string>
     <string name="media_output_status_not_support_downloads" msgid="4523828729240373315">"Awukwazi ukudlala okudawunilodiwe lapha"</string>
     <string name="media_output_status_try_after_ad" msgid="8312579066856015441">"Zama futhi ngemva kwesikhangiso"</string>
-    <!-- no translation found for media_output_status_device_in_low_power_mode (8184631698321758451) -->
-    <skip />
-    <!-- no translation found for media_output_status_unauthorized (5880222828273853838) -->
-    <skip />
-    <!-- no translation found for media_output_status_track_unsupported (5576313219317709664) -->
-    <skip />
+    <string name="media_output_status_device_in_low_power_mode" msgid="8184631698321758451">"Vusa idivayisi ukuze udlale lapha"</string>
+    <string name="media_output_status_unauthorized" msgid="5880222828273853838">"Idivayisi ayigunyaziwe ukuthi idlale"</string>
+    <string name="media_output_status_track_unsupported" msgid="5576313219317709664">"Awukwazi ukudlala le midiya lapha"</string>
     <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
     <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
     <string name="help_label" msgid="3528360748637781274">"Usizo nempendulo"</string>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 7cd8d70..09a1ba2 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -99,6 +99,7 @@
         Settings.Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_MS,
         Settings.Global.Wearable.WEAR_ACTIVITY_AUTO_RESUME_TIMEOUT_SET_BY_USER,
         Settings.Global.Wearable.DYNAMIC_COLOR_THEME_ENABLED,
+        Settings.Global.Wearable.UPGRADE_DATA_MIGRATION_STATUS,
         Settings.Global.HDR_CONVERSION_MODE,
         Settings.Global.HDR_FORCE_CONVERSION_TYPE,
     };
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index dcddde4..210a387 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -131,6 +131,7 @@
         Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO,
         Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
         Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
+        Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
         Settings.Secure.VR_DISPLAY_MODE,
         Settings.Secure.NOTIFICATION_BADGING,
         Settings.Secure.NOTIFICATION_DISMISS_RTL,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index d733dfb..be49940 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -404,5 +404,12 @@
                           }));
         VALIDATORS.put(Global.Wearable.DYNAMIC_COLOR_THEME_ENABLED, BOOLEAN_VALIDATOR);
 	VALIDATORS.put(Global.Wearable.SCREENSHOT_ENABLED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Global.Wearable.UPGRADE_DATA_MIGRATION_STATUS,
+                       new DiscreteValueValidator(
+                        new String[] {
+                            String.valueOf(Global.Wearable.UPGRADE_DATA_MIGRATION_NOT_NEEDED),
+                            String.valueOf(Global.Wearable.UPGRADE_DATA_MIGRATION_PENDING),
+                            String.valueOf(Global.Wearable.UPGRADE_DATA_MIGRATION_DONE)
+                        }));
     }
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 1c5e6ea..39cd24a 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -191,6 +191,8 @@
                 ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS,
                 ANY_STRING_VALIDATOR);
+        VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
+                ANY_STRING_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5039624..4777680 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -265,6 +265,7 @@
     <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" />
     <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
     <uses-permission android:name="android.permission.MANAGE_LOW_POWER_STANDBY" />
+    <uses-permission android:name="android.permission.SET_LOW_POWER_STANDBY_PORTS" />
     <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
     <uses-permission android:name="android.permission.MANAGE_SMARTSPACE" />
     <uses-permission android:name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION" />
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index ed6e619..ab36d58 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -51,9 +51,12 @@
     defaultClockProvider: ClockProvider,
     val fallbackClockId: ClockId = DEFAULT_CLOCK_ID,
 ) {
-    // Usually this would be a typealias, but a SAM provides better java interop
-    fun interface ClockChangeListener {
-        fun onClockChanged()
+    interface ClockChangeListener {
+        // Called when the active clock changes
+        fun onCurrentClockChanged() {}
+
+        // Called when the list of available clocks changes
+        fun onAvailableClocksChanged() {}
     }
 
     private val availableClocks = mutableMapOf<ClockId, ClockInfo>()
@@ -92,7 +95,7 @@
         protected set(value) {
             if (field != value) {
                 field = value
-                scope.launch(mainDispatcher) { onClockChanged() }
+                scope.launch(mainDispatcher) { onClockChanged { it.onCurrentClockChanged() } }
             }
         }
 
@@ -164,9 +167,9 @@
         Assert.isNotMainThread()
     }
 
-    private fun onClockChanged() {
+    private fun onClockChanged(func: (ClockChangeListener) -> Unit) {
         assertMainThread()
-        clockChangeListeners.forEach { it.onClockChanged() }
+        clockChangeListeners.forEach(func)
     }
 
     private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
@@ -241,6 +244,7 @@
     }
 
     private fun connectClocks(provider: ClockProvider) {
+        var isAvailableChanged = false
         val currentId = currentClockId
         for (clock in provider.getClocks()) {
             val id = clock.clockId
@@ -251,10 +255,11 @@
                     "Clock Id conflict: $id is registered by both " +
                         "${provider::class.simpleName} and ${current.provider::class.simpleName}"
                 )
-                return
+                continue
             }
 
             availableClocks[id] = ClockInfo(clock, provider)
+            isAvailableChanged = true
             if (DEBUG) {
                 Log.i(TAG, "Added ${clock.clockId}")
             }
@@ -263,24 +268,35 @@
                 if (DEBUG) {
                     Log.i(TAG, "Current clock ($currentId) was connected")
                 }
-                onClockChanged()
+                onClockChanged { it.onCurrentClockChanged() }
             }
         }
+
+        if (isAvailableChanged) {
+            onClockChanged { it.onAvailableClocksChanged() }
+        }
     }
 
     private fun disconnectClocks(provider: ClockProvider) {
+        var isAvailableChanged = false
         val currentId = currentClockId
         for (clock in provider.getClocks()) {
             availableClocks.remove(clock.clockId)
+            isAvailableChanged = true
+
             if (DEBUG) {
                 Log.i(TAG, "Removed ${clock.clockId}")
             }
 
             if (currentId == clock.clockId) {
                 Log.w(TAG, "Current clock ($currentId) was disconnected")
-                onClockChanged()
+                onClockChanged { it.onCurrentClockChanged() }
             }
         }
+
+        if (isAvailableChanged) {
+            onClockChanged { it.onAvailableClocksChanged() }
+        }
     }
 
     fun getClocks(): List<ClockMetadata> {
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 176bb6b..ec860b5 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -451,7 +451,6 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -736,7 +735,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
index 91f3309..26eefa9 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
@@ -252,49 +252,49 @@
             DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 90.0,
                     (s) -> highestSurface(s));
 
-    public static final DynamicColor primaryFixedDarker =
+    public static final DynamicColor primaryFixedDim =
             DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 80.0,
                     (s) -> highestSurface(s));
 
     public static final DynamicColor onPrimaryFixed =
             DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 10.0,
-                    (s) -> primaryFixedDarker);
+                    (s) -> primaryFixedDim);
 
     public static final DynamicColor onPrimaryFixedVariant =
             DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 30.0,
-                    (s) -> primaryFixedDarker);
+                    (s) -> primaryFixedDim);
 
     public static final DynamicColor secondaryFixed =
             DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 90.0,
                     (s) -> highestSurface(s));
 
-    public static final DynamicColor secondaryFixedDarker =
+    public static final DynamicColor secondaryFixedDim =
             DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 80.0,
                     (s) -> highestSurface(s));
 
     public static final DynamicColor onSecondaryFixed =
             DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 10.0,
-                    (s) -> secondaryFixedDarker);
+                    (s) -> secondaryFixedDim);
 
     public static final DynamicColor onSecondaryFixedVariant =
             DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 30.0,
-                    (s) -> secondaryFixedDarker);
+                    (s) -> secondaryFixedDim);
 
     public static final DynamicColor tertiaryFixed =
             DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 90.0,
                     (s) -> highestSurface(s));
 
-    public static final DynamicColor tertiaryFixedDarker =
+    public static final DynamicColor tertiaryFixedDim =
             DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 80.0,
                     (s) -> highestSurface(s));
 
     public static final DynamicColor onTertiaryFixed =
             DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 10.0,
-                    (s) -> tertiaryFixedDarker);
+                    (s) -> tertiaryFixedDim);
 
     public static final DynamicColor onTertiaryFixedVariant =
             DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 30.0,
-                    (s) -> tertiaryFixedDarker);
+                    (s) -> tertiaryFixedDim);
 
     /**
      * These colors were present in Android framework before Android U, and used by MDC controls.
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
deleted file mode 100644
index 8497ff0..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is the host view that generally contains two sub views: the widget view
-    and the security view. -->
-<com.android.keyguard.KeyguardHostView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/keyguard_host_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:clipChildren="false"
-    android:clipToPadding="false"
-    android:paddingTop="@dimen/keyguard_lock_padding"
-    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
-                                                  from this view when bouncer is shown -->
-
-    <com.android.keyguard.KeyguardSecurityContainer
-        android:id="@+id/keyguard_security_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:padding="0dp"
-        android:fitsSystemWindows="true"
-        android:layout_gravity="center">
-        <com.android.keyguard.KeyguardSecurityViewFlipper
-            android:id="@+id/view_flipper"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:clipChildren="false"
-            android:clipToPadding="false"
-            android:paddingTop="@dimen/keyguard_security_view_top_margin"
-            android:layout_gravity="center"
-            android:gravity="center">
-        </com.android.keyguard.KeyguardSecurityViewFlipper>
-    </com.android.keyguard.KeyguardSecurityContainer>
-
-</com.android.keyguard.KeyguardHostView>
-
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
new file mode 100644
index 0000000..426cfaf
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.keyguard.KeyguardSecurityContainer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/keyguard_security_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingTop="@dimen/keyguard_lock_padding"
+    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
+                                                  from this view when bouncer is shown -->
+    <com.android.keyguard.KeyguardSecurityViewFlipper
+        android:id="@+id/view_flipper"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:paddingTop="@dimen/keyguard_security_view_top_margin"
+        android:layout_gravity="center"
+        android:gravity="center">
+    </com.android.keyguard.KeyguardSecurityViewFlipper>
+</com.android.keyguard.KeyguardSecurityContainer>
+
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 12e5f19..738cfd7 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -120,6 +120,9 @@
     <!-- Minimum display time for a heads up notification, in milliseconds. -->
     <integer name="heads_up_notification_minimum_time">2000</integer>
 
+    <!-- Display time for a sticky heads up notification, in milliseconds. -->
+    <integer name="sticky_heads_up_notification_time">60000</integer>
+
     <!-- Whether to hide the notification header when the HUN is expanded. -->
     <bool name="heads_up_notification_hides_header">false</bool>
 
@@ -460,7 +463,7 @@
     <integer name="watch_heap_limit">256000</integer>
 
     <!-- SystemUI Plugins that can be loaded on user builds. -->
-    <string-array name="config_pluginWhitelist" translatable="false">
+    <string-array name="config_pluginAllowlist" translatable="false">
         <item>com.android.systemui</item>
     </string-array>
 
@@ -834,7 +837,7 @@
     <string name="config_wallpaperPickerPackage" translatable="false">
         com.android.wallpaper
     </string>
-    
+
     <!-- Whether the floating rotation button should be on the left/right in the device's natural
          orientation -->
     <bool name="floating_rotation_button_position_left">true</bool>
diff --git a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
index ead1a10..c4f1ce8 100644
--- a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
@@ -29,8 +29,9 @@
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED
-import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE
+import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS
+import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD
 import android.util.Log
 import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser
 import com.android.systemui.Dumpable
@@ -60,9 +61,27 @@
      * Indicates the origin for an active unlock request.
      */
     enum class ActiveUnlockRequestOrigin {
+        /**
+         * Trigger ActiveUnlock on wake ups that'd trigger FaceAuth, see [FaceWakeUpTriggersConfig]
+         */
         WAKE,
+
+        /**
+         * Trigger ActiveUnlock on unlock intents. This includes the bouncer showing or tapping on
+         * a notification. May also include wakeups: [wakeupsConsideredUnlockIntents].
+         */
         UNLOCK_INTENT,
+
+        /**
+         * Trigger ActiveUnlock on biometric failures. This may include soft errors depending on
+         * the other settings. See: [faceErrorsToTriggerBiometricFailOn],
+         * [faceAcquireInfoToTriggerBiometricFailOn].
+         */
         BIOMETRIC_FAIL,
+
+        /**
+         * Trigger ActiveUnlock when the assistant is triggered.
+         */
         ASSISTANT,
     }
 
@@ -85,6 +104,7 @@
     private var faceAcquireInfoToTriggerBiometricFailOn = mutableSetOf<Int>()
     private var onUnlockIntentWhenBiometricEnrolled = mutableSetOf<Int>()
     private var wakeupsConsideredUnlockIntents = mutableSetOf<Int>()
+    private var wakeupsToForceDismissKeyguard = mutableSetOf<Int>()
 
     private val settingsObserver = object : ContentObserver(handler) {
         private val wakeUri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE)
@@ -97,6 +117,8 @@
                 secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED)
         private val wakeupsConsideredUnlockIntentsUri =
             secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS)
+        private val wakeupsToForceDismissKeyguardUri =
+            secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD)
 
         fun register() {
             registerUri(
@@ -108,6 +130,7 @@
                         faceAcquireInfoUri,
                         unlockIntentWhenBiometricEnrolledUri,
                         wakeupsConsideredUnlockIntentsUri,
+                        wakeupsToForceDismissKeyguardUri,
                     )
             )
 
@@ -182,6 +205,15 @@
                     wakeupsConsideredUnlockIntents,
                     setOf(WAKE_REASON_UNFOLD_DEVICE))
             }
+
+            if (selfChange || uris.contains(wakeupsToForceDismissKeyguardUri)) {
+                processStringArray(
+                    secureSettings.getStringForUser(
+                        ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
+                        getCurrentUser()),
+                    wakeupsToForceDismissKeyguard,
+                    setOf(WAKE_REASON_UNFOLD_DEVICE))
+            }
         }
 
         /**
@@ -249,6 +281,14 @@
     }
 
     /**
+     * Whether the PowerManager wake reason should force dismiss the keyguard if active
+     * unlock is successful.
+     */
+    fun shouldWakeupForceDismissKeyguard(pmWakeReason: Int): Boolean {
+        return wakeupsToForceDismissKeyguard.contains(pmWakeReason)
+    }
+
+    /**
      * Whether to trigger active unlock based on where the request is coming from and
      * the current settings.
      */
@@ -321,6 +361,9 @@
         pw.println("   activeUnlockWakeupsConsideredUnlockIntents=${
             wakeupsConsideredUnlockIntents.map { PowerManager.wakeReasonToString(it) }
         }")
+        pw.println("   activeUnlockFromWakeupsToAlwaysDismissKeyguard=${
+            wakeupsToForceDismissKeyguard.map { PowerManager.wakeReasonToString(it) }
+        }")
 
         pw.println("Current state:")
         keyguardUpdateMonitor?.let {
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt
index a0c43fb..788a66d 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt
@@ -29,7 +29,7 @@
 import java.util.stream.Collectors
 import javax.inject.Inject
 
-/** Determines which device wake-ups should trigger face authentication. */
+/** Determines which device wake-ups should trigger passive authentication. */
 @SysUISingleton
 class FaceWakeUpTriggersConfig
 @Inject
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index f1b90e3..5ec59ab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -151,8 +151,13 @@
         mLogBuffer = logBuffer;
         mView.setLogBuffer(mLogBuffer);
 
-        mClockChangedListener = () -> {
-            setClock(mClockRegistry.createCurrentClock());
+        mClockChangedListener = new ClockRegistry.ClockChangeListener() {
+            @Override
+            public void onCurrentClockChanged() {
+                setClock(mClockRegistry.createCurrentClock());
+            }
+            @Override
+            public void onAvailableClocksChanged() { }
         };
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
index 998dc09..57130ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
@@ -27,6 +27,7 @@
     override var userId: Int = 0,
     override var listening: Boolean = false,
     // keepSorted
+    var alternateBouncerShowing: Boolean = false,
     var biometricEnabledForUser: Boolean = false,
     var bouncerIsOrWillShow: Boolean = false,
     var canSkipBouncer: Boolean = false,
@@ -57,6 +58,7 @@
             userId.toString(),
             listening.toString(),
             // keep sorted
+            alternateBouncerShowing.toString(),
             biometricEnabledForUser.toString(),
             bouncerIsOrWillShow.toString(),
             canSkipBouncer.toString(),
@@ -96,6 +98,7 @@
                 userId = model.userId
                 listening = model.listening
                 // keep sorted
+                alternateBouncerShowing = model.alternateBouncerShowing
                 biometricEnabledForUser = model.biometricEnabledForUser
                 bouncerIsOrWillShow = model.bouncerIsOrWillShow
                 canSkipBouncer = model.canSkipBouncer
@@ -141,6 +144,7 @@
                 "userId",
                 "listening",
                 // keep sorted
+                "alternateBouncerShowing",
                 "biometricAllowedForUser",
                 "bouncerIsOrWillShow",
                 "canSkipBouncer",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
deleted file mode 100644
index 2a389b6..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2007 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.keyguard;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-/**
- * Base class for keyguard view.  {@link #reset} is where you should
- * reset the state of your view.  Use the {@link KeyguardViewCallback} via
- * {@link #getCallback()} to send information back (such as poking the wake lock,
- * or finishing the keyguard).
- *
- * Handles intercepting of media keys that still work when the keyguard is
- * showing.
- */
-public class KeyguardHostView extends FrameLayout {
-
-    protected ViewMediatorCallback mViewMediatorCallback;
-    private boolean mIsInteractable;
-
-    public KeyguardHostView(Context context) {
-        this(context, null);
-    }
-
-    public KeyguardHostView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        if (mViewMediatorCallback != null) {
-            mViewMediatorCallback.keyguardDoneDrawing();
-        }
-    }
-
-    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
-        mViewMediatorCallback = viewMediatorCallback;
-    }
-
-    /** Set true if the view can be interacted with */
-    public void setInteractable(boolean isInteractable) {
-        mIsInteractable = isInteractable;
-    }
-
-    /**
-     * Make sure to disallow touches while transitioning the bouncer, otherwise
-     * it can remain interactable even when barely visible.
-     */
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        return !mIsInteractable;
-    }
-
-    /** True to consume any events that are sent to it */
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        return true;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
deleted file mode 100644
index 77f6318..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import android.app.ActivityManager;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.media.AudioManager;
-import android.os.SystemClock;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnKeyListener;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-import android.window.OnBackAnimationCallback;
-
-import androidx.annotation.NonNull;
-
-import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
-import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.settingslib.Utils;
-import com.android.systemui.R;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.util.ViewController;
-
-import java.io.File;
-
-import javax.inject.Inject;
-
-/** Controller for a {@link KeyguardHostView}. */
-@KeyguardBouncerScope
-public class KeyguardHostViewController extends ViewController<KeyguardHostView> {
-    private static final String TAG = "KeyguardViewBase";
-    public static final boolean DEBUG = KeyguardConstants.DEBUG;
-    // Whether the volume keys should be handled by keyguard. If true, then
-    // they will be handled here for specific media types such as music, otherwise
-    // the audio service will bring up the volume dialog.
-    private static final boolean KEYGUARD_MANAGES_VOLUME = false;
-
-    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
-
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final KeyguardSecurityContainerController mKeyguardSecurityContainerController;
-    private final TelephonyManager mTelephonyManager;
-    private final ViewMediatorCallback mViewMediatorCallback;
-    private final AudioManager mAudioManager;
-
-    private ActivityStarter.OnDismissAction mDismissAction;
-    private Runnable mCancelAction;
-    private int mTranslationY;
-
-    private final KeyguardUpdateMonitorCallback mUpdateCallback =
-            new KeyguardUpdateMonitorCallback() {
-                @Override
-                public void onTrustGrantedForCurrentUser(
-                        boolean dismissKeyguard,
-                        boolean newlyUnlocked,
-                        TrustGrantFlags flags,
-                        String message
-                ) {
-                    if (dismissKeyguard) {
-                        if (!mView.isVisibleToUser()) {
-                            // The trust agent dismissed the keyguard without the user proving
-                            // that they are present (by swiping up to show the bouncer). That's
-                            // fine if the user proved presence via some other way to the trust
-                            // agent.
-                            Log.i(TAG, "TrustAgent dismissed Keyguard.");
-                        }
-                        mSecurityCallback.dismiss(
-                                false /* authenticated */,
-                                KeyguardUpdateMonitor.getCurrentUser(),
-                                /* bypassSecondaryLockScreen */ false,
-                                SecurityMode.Invalid
-                        );
-                    } else {
-                        if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
-                            mViewMediatorCallback.playTrustedSound();
-                        }
-                    }
-                }
-            };
-
-    private final SecurityCallback mSecurityCallback = new SecurityCallback() {
-
-        @Override
-        public boolean dismiss(boolean authenticated, int targetUserId,
-                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
-            return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
-                    authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
-        }
-
-        @Override
-        public void userActivity() {
-            mViewMediatorCallback.userActivity();
-        }
-
-        @Override
-        public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
-            mViewMediatorCallback.setNeedsInput(needsInput);
-        }
-
-        /**
-         * Authentication has happened and it's time to dismiss keyguard. This function
-         * should clean up and inform KeyguardViewMediator.
-         *
-         * @param strongAuth whether the user has authenticated with strong authentication like
-         *                   pattern, password or PIN but not by trust agents or fingerprint
-         * @param targetUserId a user that needs to be the foreground user at the dismissal
-         *                    completion.
-         */
-        @Override
-        public void finish(boolean strongAuth, int targetUserId) {
-            // If there's a pending runnable because the user interacted with a widget
-            // and we're leaving keyguard, then run it.
-            boolean deferKeyguardDone = false;
-            if (mDismissAction != null) {
-                deferKeyguardDone = mDismissAction.onDismiss();
-                mDismissAction = null;
-                mCancelAction = null;
-            }
-            if (mViewMediatorCallback != null) {
-                if (deferKeyguardDone) {
-                    mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
-                } else {
-                    mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
-                }
-            }
-        }
-
-        @Override
-        public void reset() {
-            mViewMediatorCallback.resetKeyguard();
-        }
-
-        @Override
-        public void onCancelClicked() {
-            mViewMediatorCallback.onCancelClicked();
-        }
-    };
-
-    private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
-
-    @Inject
-    public KeyguardHostViewController(KeyguardHostView view,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            AudioManager audioManager,
-            TelephonyManager telephonyManager,
-            ViewMediatorCallback viewMediatorCallback,
-            KeyguardSecurityContainerController.Factory
-                    keyguardSecurityContainerControllerFactory) {
-        super(view);
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mAudioManager = audioManager;
-        mTelephonyManager = telephonyManager;
-        mViewMediatorCallback = viewMediatorCallback;
-        mKeyguardSecurityContainerController = keyguardSecurityContainerControllerFactory.create(
-                mSecurityCallback);
-    }
-
-    /** Initialize the Controller. */
-    public void onInit() {
-        mKeyguardSecurityContainerController.init();
-        updateResources();
-    }
-
-    @Override
-    protected void onViewAttached() {
-        mView.setViewMediatorCallback(mViewMediatorCallback);
-        // Update ViewMediator with the current input method requirements
-        mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
-        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
-        mView.setOnKeyListener(mOnKeyListener);
-        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
-    }
-
-    @Override
-    protected void onViewDetached() {
-        mKeyguardUpdateMonitor.removeCallback(mUpdateCallback);
-        mView.setOnKeyListener(null);
-    }
-
-     /** Called before this view is being removed. */
-    public void cleanUp() {
-        mKeyguardSecurityContainerController.onPause();
-    }
-
-    public void resetSecurityContainer() {
-        mKeyguardSecurityContainerController.reset();
-    }
-
-    /**
-     * Reinflate the view flipper child view.
-     */
-    public void reinflateViewFlipper() {
-        mKeyguardSecurityContainerController.reinflateViewFlipper();
-    }
-
-    /**
-     * Dismisses the keyguard by going to the next screen or making it gone.
-     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
-     * @return True if the keyguard is done.
-     */
-    public boolean dismiss(int targetUserId) {
-        return mSecurityCallback.dismiss(false, targetUserId, false,
-                getCurrentSecurityMode());
-    }
-
-    /**
-     * Called when the Keyguard is actively shown on the screen.
-     */
-    public void onResume() {
-        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
-        mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON);
-        mView.requestFocus();
-    }
-
-    public CharSequence getAccessibilityTitleForCurrentMode() {
-        return mKeyguardSecurityContainerController.getTitle();
-    }
-
-    /**
-     * Starts the animation when the Keyguard gets shown.
-     */
-    public void appear() {
-        // We might still be collapsed and the view didn't have time to layout yet or still
-        // be small, let's wait on the predraw to do the animation in that case.
-        mView.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        mView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        mKeyguardSecurityContainerController.startAppearAnimation();
-                        return true;
-                    }
-                });
-        mView.requestLayout();
-    }
-
-    /**
-     * Show a string explaining why the security view needs to be solved.
-     *
-     * @param reason a flag indicating which string should be shown, see
-     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE},
-     *               {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
-     *               {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
-     *               {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
-     */
-    public void showPromptReason(int reason) {
-        mKeyguardSecurityContainerController.showPromptReason(reason);
-    }
-
-    public void showMessage(CharSequence message, ColorStateList colorState) {
-        mKeyguardSecurityContainerController.showMessage(message, colorState);
-    }
-
-    public void showErrorMessage(CharSequence customMessage) {
-        showMessage(customMessage, Utils.getColorError(mView.getContext()));
-    }
-
-    /**
-     * Sets an action to run when keyguard finishes.
-     *
-     * @param action
-     */
-    public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
-        if (mCancelAction != null) {
-            mCancelAction.run();
-            mCancelAction = null;
-        }
-        mDismissAction = action;
-        mCancelAction = cancelAction;
-    }
-
-    public void cancelDismissAction() {
-        setOnDismissAction(null, null);
-    }
-
-    public void startDisappearAnimation(Runnable finishRunnable) {
-        if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable)
-                && finishRunnable != null) {
-            finishRunnable.run();
-        }
-    }
-
-    /**
-     * Called when the Keyguard is not actively shown anymore on the screen.
-     */
-    public void onPause() {
-        if (DEBUG) {
-            Log.d(TAG, String.format("screen off, instance %s at %s",
-                    Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
-        }
-        mKeyguardSecurityContainerController.showPrimarySecurityScreen(true);
-        mKeyguardSecurityContainerController.onPause();
-        mView.clearFocus();
-    }
-
-    /**
-     * Called when the view needs to be shown.
-     */
-    public void showPrimarySecurityScreen() {
-        if (DEBUG) Log.d(TAG, "show()");
-        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
-    }
-
-    /**
-     * Fades and translates in/out the security screen.
-     * Fades in as expansion approaches 0.
-     * Animation duration is between 0.33f and 0.67f of panel expansion fraction.
-     * @param fraction amount of the screen that should show.
-     */
-    public void setExpansion(float fraction) {
-        float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
-        mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
-        mView.setTranslationY(scaledFraction * mTranslationY);
-    }
-
-    /**
-     * When bouncer was visible and is starting to become hidden.
-     */
-    public void onStartingToHide() {
-        mKeyguardSecurityContainerController.onStartingToHide();
-    }
-
-    /** Called when bouncer visibility changes. */
-    public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
-        mKeyguardSecurityContainerController.onBouncerVisibilityChanged(visibility);
-    }
-
-    public boolean hasDismissActions() {
-        return mDismissAction != null || mCancelAction != null;
-    }
-
-    public SecurityMode getCurrentSecurityMode() {
-        return mKeyguardSecurityContainerController.getCurrentSecurityMode();
-    }
-
-    public int getTop() {
-        int top = mView.getTop();
-        // The password view has an extra top padding that should be ignored.
-        if (getCurrentSecurityMode() == SecurityMode.Password) {
-            View messageArea = mView.findViewById(R.id.keyguard_message_area);
-            top += messageArea.getTop();
-        }
-        return top;
-    }
-
-    public boolean handleBackKey() {
-        SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
-        if (securityMode != SecurityMode.None) {
-            mKeyguardSecurityContainerController.dismiss(
-                    false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
-     * some cases where we wish to disable it, notably when the menu button placement or technology
-     * is prone to false positives.
-     *
-     * @return true if the menu key should be enabled
-     */
-    public boolean shouldEnableMenuKey() {
-        final Resources res = mView.getResources();
-        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
-        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
-        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
-        return !configDisabled || isTestHarness || fileOverride;
-    }
-
-    /**
-     * @return true if the current bouncer is password
-     */
-    public boolean dispatchBackKeyEventPreIme() {
-        if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
-                == SecurityMode.Password) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
-     */
-    @NonNull
-    public OnBackAnimationCallback getBackCallback() {
-        return mKeyguardSecurityContainerController.getBackCallback();
-    }
-
-    /**
-     * Allows the media keys to work when the keyguard is showing.
-     * The media keys should be of no interest to the actual keyguard view(s),
-     * so intercepting them here should not be of any harm.
-     * @param event The key event
-     * @return whether the event was consumed as a media key.
-     */
-    public boolean interceptMediaKey(KeyEvent event) {
-        int keyCode = event.getKeyCode();
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
-                     * in-call to avoid music playback */
-                    if (mTelephonyManager != null &&
-                            mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
-                        return true;  // suppress key event
-                    }
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-
-                case KeyEvent.KEYCODE_VOLUME_UP:
-                case KeyEvent.KEYCODE_VOLUME_DOWN:
-                case KeyEvent.KEYCODE_VOLUME_MUTE: {
-                    if (KEYGUARD_MANAGES_VOLUME) {
-                        // Volume buttons should only function for music (local or remote).
-                        // TODO: Actually handle MUTE.
-                        mAudioManager.adjustSuggestedStreamVolume(
-                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
-                                        ? AudioManager.ADJUST_RAISE
-                                        : AudioManager.ADJUST_LOWER /* direction */,
-                                AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
-                        // Don't execute default volume behavior
-                        return true;
-                    } else {
-                        return false;
-                    }
-                }
-            }
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MUTE:
-                case KeyEvent.KEYCODE_HEADSETHOOK:
-                case KeyEvent.KEYCODE_MEDIA_PLAY:
-                case KeyEvent.KEYCODE_MEDIA_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                case KeyEvent.KEYCODE_MEDIA_STOP:
-                case KeyEvent.KEYCODE_MEDIA_NEXT:
-                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
-                case KeyEvent.KEYCODE_MEDIA_REWIND:
-                case KeyEvent.KEYCODE_MEDIA_RECORD:
-                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
-                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
-                    handleMediaKeyEvent(event);
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-
-    private void handleMediaKeyEvent(KeyEvent keyEvent) {
-        mAudioManager.dispatchMediaKeyEvent(keyEvent);
-    }
-
-    public void finish(boolean strongAuth, int currentUser) {
-        mSecurityCallback.finish(strongAuth, currentUser);
-    }
-
-    /**
-     * Apply keyguard configuration from the currently active resources. This can be called when the
-     * device configuration changes, to re-apply some resources that are qualified on the device
-     * configuration.
-     */
-    public void updateResources() {
-        int gravity;
-
-        Resources resources = mView.getResources();
-
-        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
-            gravity = resources.getInteger(
-                    R.integer.keyguard_host_view_one_handed_gravity);
-        } else {
-            gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
-        }
-
-        mTranslationY = resources
-                .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
-        // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
-        // We're just changing the gravity here though (which can't be applied to RelativeLayout),
-        // so only attempt the update if mView is inside a FrameLayout.
-        if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
-            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
-            if (lp.gravity != gravity) {
-                lp.gravity = gravity;
-                mView.setLayoutParams(lp);
-            }
-        }
-
-        if (mKeyguardSecurityContainerController != null) {
-            mKeyguardSecurityContainerController.updateResources();
-        }
-    }
-
-    /** Update keyguard position based on a tapped X coordinate. */
-    public void updateKeyguardPosition(float x) {
-        if (mKeyguardSecurityContainerController != null) {
-            mKeyguardSecurityContainerController.updateKeyguardPosition(x);
-        }
-    }
-
-    /** Set true if the view can be interacted with */
-    public void setInteractable(boolean isInteractable) {
-        mView.setInteractable(isInteractable);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 48844db..bec8547 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -52,26 +52,7 @@
     // The following is used to ignore callbacks from SecurityViews that are no longer current
     // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
     // state for the current security method.
-    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
-        @Override
-        public void userActivity() { }
-        @Override
-        public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { }
-        @Override
-        public boolean isVerifyUnlockOnly() {
-            return false;
-        }
-        @Override
-        public void dismiss(boolean securityVerified, int targetUserId,
-                SecurityMode expectedSecurityMode) { }
-        @Override
-        public void dismiss(boolean authenticated, int targetId,
-                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
-        @Override
-        public void onUserInput() { }
-        @Override
-        public void reset() {}
-    };
+    private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {};
 
     protected KeyguardInputViewController(T view, SecurityMode securityMode,
             KeyguardSecurityCallback keyguardSecurityCallback,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index bc72f79..bf9c3bb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -25,7 +25,9 @@
      * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
      * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
+    default void dismiss(boolean securityVerified, int targetUserId,
+            SecurityMode expectedSecurityMode) {
+    }
 
     /**
      * Dismiss the given security screen.
@@ -35,19 +37,26 @@
      *                                  if any, during this dismissal.
      * @param expectedSecurityMode The security mode that is invoking this dismiss.
      */
-    void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
-            SecurityMode expectedSecurityMode);
+    default boolean dismiss(boolean securityVerified, int targetUserId,
+            boolean bypassSecondaryLockScreen,
+            SecurityMode expectedSecurityMode) {
+        return false;
+    }
 
     /**
      * Manually report user activity to keep the device awake.
      */
-    void userActivity();
+    default void userActivity() {
+    }
 
     /**
      * Checks if keyguard is in "verify credentials" mode.
+     *
      * @return true if user has been asked to verify security.
      */
-    boolean isVerifyUnlockOnly();
+    default boolean isVerifyUnlockOnly() {
+        return false;
+    }
 
     /**
      * Call to report an unlock attempt.
@@ -56,12 +65,14 @@
      * @param timeoutMs timeout in milliseconds to wait before reattempting an unlock.
      *                  Only nonzero if 'success' is false
      */
-    void reportUnlockAttempt(int userId, boolean success, int timeoutMs);
+    default void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
+    }
 
     /**
      * Resets the keyguard view.
      */
-    void reset();
+    default void reset() {
+    }
 
     /**
      * Call when cancel button is pressed in bouncer.
@@ -73,5 +84,19 @@
     /**
      * Invoked whenever users are typing their password or drawing a pattern.
      */
-    void onUserInput();
+    default void onUserInput() {
+    }
+
+
+    /**
+     * Dismisses keyguard and go to unlocked state.
+     */
+    default void finish(boolean strongAuth, int targetUserId) {
+    }
+
+    /**
+     * Specifies that security mode has changed.
+     */
+    default void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 9f07a20..eec788b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -50,6 +50,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BlendMode;
+import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -164,6 +165,8 @@
     private boolean mDisappearAnimRunning;
     private SwipeListener mSwipeListener;
     private ViewMode mViewMode = new DefaultViewMode();
+    private boolean mIsInteractable;
+    protected ViewMediatorCallback mViewMediatorCallback;
     /*
      * Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
      * yet been called on it. This will happen when the ViewController is initialized.
@@ -265,31 +268,6 @@
         return mBackCallback;
     }
 
-    // Used to notify the container when something interesting happens.
-    public interface SecurityCallback {
-        /**
-         * Potentially dismiss the current security screen, after validating that all device
-         * security has been unlocked. Otherwise show the next screen.
-         */
-        boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
-                SecurityMode expectedSecurityMode);
-
-        void userActivity();
-
-        void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
-
-        /**
-         * @param strongAuth   wheher the user has authenticated with strong authentication like
-         *                     pattern, password or PIN but not by trust agents or fingerprint
-         * @param targetUserId a user that needs to be the foreground user at the finish completion.
-         */
-        void finish(boolean strongAuth, int targetUserId);
-
-        void reset();
-
-        void onCancelClicked();
-    }
-
     public interface SwipeListener {
         void onSwipeUp();
     }
@@ -342,7 +320,7 @@
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
+        mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y);
         mViewConfiguration = ViewConfiguration.get(context);
         mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
     }
@@ -445,6 +423,11 @@
         mViewMode.reset();
     }
 
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mIsInteractable = isInteractable;
+    }
+
     @Override
     public boolean shouldDelayChildPressedState() {
         return true;
@@ -452,6 +435,10 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
+        if (!mIsInteractable) {
+            return true;
+        }
+
         boolean result =  mMotionEventListeners.stream().anyMatch(
                 listener -> listener.onInterceptTouchEvent(event))
                 || super.onInterceptTouchEvent(event);
@@ -639,6 +626,18 @@
         return insets.inset(0, 0, 0, inset);
     }
 
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.keyguardDoneDrawing();
+        }
+    }
+
+    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
+        mViewMediatorCallback = viewMediatorCallback;
+    }
+
     private void showDialog(String title, String message) {
         if (mAlertDialog != null) {
             mAlertDialog.dismiss();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index b135652..23f887e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -29,18 +29,27 @@
 import static com.android.keyguard.KeyguardSecurityContainer.USER_TYPE_WORK_PROFILE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 
+import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.hardware.biometrics.BiometricOverlayConstants;
 import android.hardware.biometrics.BiometricSourceType;
+import android.media.AudioManager;
 import android.metrics.LogMaker;
+import android.os.SystemClock;
 import android.os.UserHandle;
+import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.Slog;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
 import android.window.OnBackAnimationCallback;
 
 import androidx.annotation.NonNull;
@@ -54,7 +63,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityContainer.BouncerUiEvent;
-import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
 import com.android.keyguard.KeyguardSecurityContainer.SwipeListener;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.dagger.KeyguardBouncerScope;
@@ -68,6 +76,7 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
 import com.android.systemui.log.SessionTracker;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -76,6 +85,7 @@
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.settings.GlobalSettings;
 
+import java.io.File;
 import java.util.Optional;
 
 import javax.inject.Inject;
@@ -96,7 +106,6 @@
     private final UiEventLogger mUiEventLogger;
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
-    private final SecurityCallback mSecurityCallback;
     private final ConfigurationController mConfigurationController;
     private final FalsingCollector mFalsingCollector;
     private final FalsingManager mFalsingManager;
@@ -106,6 +115,20 @@
     private final SessionTracker mSessionTracker;
     private final Optional<SideFpsController> mSideFpsController;
     private final FalsingA11yDelegate mFalsingA11yDelegate;
+    private int mTranslationY;
+    // Whether the volume keys should be handled by keyguard. If true, then
+    // they will be handled here for specific media types such as music, otherwise
+    // the audio service will bring up the volume dialog.
+    private static final boolean KEYGUARD_MANAGES_VOLUME = false;
+
+    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+
+    private final TelephonyManager mTelephonyManager;
+    private final ViewMediatorCallback mViewMediatorCallback;
+    private final AudioManager mAudioManager;
+    private View.OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event);
+    private ActivityStarter.OnDismissAction mDismissAction;
+    private Runnable mCancelAction;
 
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
 
@@ -150,11 +173,6 @@
     };
 
     private KeyguardSecurityCallback mKeyguardSecurityCallback = new KeyguardSecurityCallback() {
-        public void userActivity() {
-            if (mSecurityCallback != null) {
-                mSecurityCallback.userActivity();
-            }
-        }
 
         @Override
         public void onUserInput() {
@@ -169,16 +187,23 @@
         }
 
         @Override
-        public void dismiss(boolean authenticated, int targetId,
+        public boolean dismiss(boolean authenticated, int targetId,
                 boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
-            mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
-                    expectedSecurityMode);
+            return showNextSecurityScreenOrFinish(
+                    authenticated, targetId, bypassSecondaryLockScreen, expectedSecurityMode);
         }
 
+        @Override
+        public void userActivity() {
+            mViewMediatorCallback.userActivity();
+        }
+
+        @Override
         public boolean isVerifyUnlockOnly() {
             return false;
         }
 
+        @Override
         public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
             int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
             if (mView.isSidedSecurityMode()) {
@@ -215,12 +240,47 @@
                             : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());
         }
 
+        @Override
         public void reset() {
-            mSecurityCallback.reset();
+            mViewMediatorCallback.resetKeyguard();
         }
 
+        @Override
         public void onCancelClicked() {
-            mSecurityCallback.onCancelClicked();
+            mViewMediatorCallback.onCancelClicked();
+        }
+
+        /**
+         * Authentication has happened and it's time to dismiss keyguard. This function
+         * should clean up and inform KeyguardViewMediator.
+         *
+         * @param strongAuth whether the user has authenticated with strong authentication like
+         *                   pattern, password or PIN but not by trust agents or fingerprint
+         * @param targetUserId a user that needs to be the foreground user at the dismissal
+         *                    completion.
+         */
+        @Override
+        public void finish(boolean strongAuth, int targetUserId) {
+            // If there's a pending runnable because the user interacted with a widget
+            // and we're leaving keyguard, then run it.
+            boolean deferKeyguardDone = false;
+            if (mDismissAction != null) {
+                deferKeyguardDone = mDismissAction.onDismiss();
+                mDismissAction = null;
+                mCancelAction = null;
+            }
+            if (mViewMediatorCallback != null) {
+                if (deferKeyguardDone) {
+                    mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
+                } else {
+                    mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
+                }
+            }
+        }
+
+        @Override
+        public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
+            mViewMediatorCallback.setNeedsInput(needsInput);
         }
     };
 
@@ -265,6 +325,34 @@
     private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
                 @Override
+                public void onTrustGrantedForCurrentUser(
+                        boolean dismissKeyguard,
+                        boolean newlyUnlocked,
+                        TrustGrantFlags flags,
+                        String message
+                ) {
+                    if (dismissKeyguard) {
+                        if (!mView.isVisibleToUser()) {
+                            // The trust agent dismissed the keyguard without the user proving
+                            // that they are present (by swiping up to show the bouncer). That's
+                            // fine if the user proved presence via some other way to the trust
+                            // agent.
+                            Log.i(TAG, "TrustAgent dismissed Keyguard.");
+                        }
+                        mKeyguardSecurityCallback.dismiss(
+                                false /* authenticated */,
+                                KeyguardUpdateMonitor.getCurrentUser(),
+                                /* bypassSecondaryLockScreen */ false,
+                                SecurityMode.Invalid
+                        );
+                    } else {
+                        if (flags.isInitiatedByUser() || flags.dismissKeyguardRequested()) {
+                            mViewMediatorCallback.playTrustedSound();
+                        }
+                    }
+                }
+
+                @Override
                 public void onDevicePolicyManagerStateChanged() {
                     showPrimarySecurityScreen(false);
                 }
@@ -283,7 +371,8 @@
                 }
             };
 
-    private KeyguardSecurityContainerController(KeyguardSecurityContainer view,
+    @Inject
+    public KeyguardSecurityContainerController(KeyguardSecurityContainer view,
             AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
             LockPatternUtils lockPatternUtils,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -291,7 +380,6 @@
             MetricsLogger metricsLogger,
             UiEventLogger uiEventLogger,
             KeyguardStateController keyguardStateController,
-            SecurityCallback securityCallback,
             KeyguardSecurityViewFlipperController securityViewFlipperController,
             ConfigurationController configurationController,
             FalsingCollector falsingCollector,
@@ -301,7 +389,11 @@
             GlobalSettings globalSettings,
             SessionTracker sessionTracker,
             Optional<SideFpsController> sideFpsController,
-            FalsingA11yDelegate falsingA11yDelegate) {
+            FalsingA11yDelegate falsingA11yDelegate,
+            TelephonyManager telephonyManager,
+            ViewMediatorCallback viewMediatorCallback,
+            AudioManager audioManager
+    ) {
         super(view);
         mLockPatternUtils = lockPatternUtils;
         mUpdateMonitor = keyguardUpdateMonitor;
@@ -309,7 +401,6 @@
         mMetricsLogger = metricsLogger;
         mUiEventLogger = uiEventLogger;
         mKeyguardStateController = keyguardStateController;
-        mSecurityCallback = securityCallback;
         mSecurityViewFlipperController = securityViewFlipperController;
         mAdminSecondaryLockScreenController = adminSecondaryLockScreenControllerFactory.create(
                 mKeyguardSecurityCallback);
@@ -323,11 +414,15 @@
         mSessionTracker = sessionTracker;
         mSideFpsController = sideFpsController;
         mFalsingA11yDelegate = falsingA11yDelegate;
+        mTelephonyManager = telephonyManager;
+        mViewMediatorCallback = viewMediatorCallback;
+        mAudioManager = audioManager;
     }
 
     @Override
     public void onInit() {
         mSecurityViewFlipperController.init();
+        updateResources();
         configureMode();
     }
 
@@ -338,6 +433,11 @@
         mView.addMotionEventListener(mGlobalTouchListener);
         mConfigurationController.addCallback(mConfigurationListener);
         mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
+        mView.setViewMediatorCallback(mViewMediatorCallback);
+        // Update ViewMediator with the current input method requirements
+        mViewMediatorCallback.setNeedsInput(needsInput());
+        mView.setOnKeyListener(mOnKeyListener);
+        showPrimarySecurityScreen(false);
     }
 
     @Override
@@ -350,6 +450,11 @@
 
     /** */
     public void onPause() {
+        if (DEBUG) {
+            Log.d(TAG, String.format("screen off, instance %s at %s",
+                    Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+        }
+        showPrimarySecurityScreen(true);
         mAdminSecondaryLockScreenController.hide();
         if (mCurrentSecurityMode != SecurityMode.None) {
             getCurrentSecurityController().onPause();
@@ -358,6 +463,7 @@
         // It might happen that onStartingToHide is not called when the device is locked while on
         // bouncer.
         setBouncerVisible(false);
+        mView.clearFocus();
     }
 
     private void updateSideFpsVisibility() {
@@ -394,12 +500,22 @@
      * @param turningOff true if the device is being turned off
      */
     public void showPrimarySecurityScreen(boolean turningOff) {
+        if (DEBUG) Log.d(TAG, "show()");
         SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
                 KeyguardUpdateMonitor.getCurrentUser()));
         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
         showSecurityScreen(securityMode);
     }
 
+    /**
+     * Show a string explaining why the security view needs to be solved.
+     *
+     * @param reason a flag indicating which string should be shown, see
+     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE},
+     *               {@link KeyguardSecurityView#PROMPT_REASON_RESTART},
+     *               {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and
+     *               {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}.
+     */
     @Override
     public void showPromptReason(int reason) {
         if (mCurrentSecurityMode != SecurityMode.None) {
@@ -416,8 +532,32 @@
         }
     }
 
-    public SecurityMode getCurrentSecurityMode() {
-        return mCurrentSecurityMode;
+    /**
+     * Sets an action to run when keyguard finishes.
+     *
+     * @param action callback to be invoked when keyguard disappear animation completes.
+     */
+    public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) {
+        if (mCancelAction != null) {
+            mCancelAction.run();
+            mCancelAction = null;
+        }
+        mDismissAction = action;
+        mCancelAction = cancelAction;
+    }
+
+    /**
+     * @return whether dismiss action or cancel action has been set.
+     */
+    public boolean hasDismissActions() {
+        return mDismissAction != null || mCancelAction != null;
+    }
+
+    /**
+     * Remove any dismiss action or cancel action that was set.
+     */
+    public void cancelDismissAction() {
+        setOnDismissAction(null, null);
     }
 
     /**
@@ -429,17 +569,64 @@
         mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
     }
 
+    /**
+     * Dismisses the keyguard by going to the next screen or making it gone.
+     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+     * @return True if the keyguard is done.
+     */
+    public boolean dismiss(int targetUserId) {
+        return mKeyguardSecurityCallback.dismiss(false, targetUserId, false,
+                getCurrentSecurityMode());
+    }
+
+    public SecurityMode getCurrentSecurityMode() {
+        return mCurrentSecurityMode;
+    }
+
+    /**
+     * @return the top of the corresponding view.
+     */
+    public int getTop() {
+        int top = mView.getTop();
+        // The password view has an extra top padding that should be ignored.
+        if (getCurrentSecurityMode() == SecurityMode.Password) {
+            View messageArea = mView.findViewById(R.id.keyguard_message_area);
+            top += messageArea.getTop();
+        }
+        return top;
+    }
+
+    /** Set true if the view can be interacted with */
+    public void setInteractable(boolean isInteractable) {
+        mView.setInteractable(isInteractable);
+    }
+
+    /**
+     * Dismiss keyguard due to a user unlock event.
+     */
+    public void finish(boolean strongAuth, int currentUser) {
+        mKeyguardSecurityCallback.finish(strongAuth, currentUser);
+    }
+
+    /**
+     * @return the text of the KeyguardMessageArea.
+     */
+    public CharSequence getTitle() {
+        return mView.getTitle();
+    }
+
+    /**
+     *  Resets the state of the views.
+     */
     public void reset() {
         mView.reset();
         mSecurityViewFlipperController.reset();
     }
 
-    public CharSequence getTitle() {
-        return mView.getTitle();
-    }
-
     @Override
     public void onResume(int reason) {
+        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+        mView.requestFocus();
         if (mCurrentSecurityMode != SecurityMode.None) {
             int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN;
             if (mView.isSidedSecurityMode()) {
@@ -457,6 +644,25 @@
                 mKeyguardStateController.isFaceAuthEnabled());
     }
 
+    /**
+     * Show the bouncer and start appear animations.
+     *
+     */
+    public void appear() {
+        // We might still be collapsed and the view didn't have time to layout yet or still
+        // be small, let's wait on the predraw to do the animation in that case.
+        mView.getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mView.getViewTreeObserver().removeOnPreDrawListener(this);
+                        startAppearAnimation();
+                        return true;
+                    }
+                });
+        mView.requestLayout();
+    }
+
     public void startAppearAnimation() {
         if (mCurrentSecurityMode != SecurityMode.None) {
             mView.setAlpha(1f);
@@ -466,12 +672,19 @@
     }
 
     public boolean startDisappearAnimation(Runnable onFinishRunnable) {
+        boolean didRunAnimation = false;
+
         if (mCurrentSecurityMode != SecurityMode.None) {
             mView.startDisappearAnimation(mCurrentSecurityMode);
-            return getCurrentSecurityController().startDisappearAnimation(onFinishRunnable);
+            didRunAnimation = getCurrentSecurityController().startDisappearAnimation(
+                    onFinishRunnable);
         }
 
-        return false;
+        if (!didRunAnimation && onFinishRunnable != null) {
+            onFinishRunnable.run();
+        }
+
+        return didRunAnimation;
     }
 
     public void onStartingToHide() {
@@ -586,7 +799,7 @@
             mUiEventLogger.log(uiEvent, getSessionId());
         }
         if (finish) {
-            mSecurityCallback.finish(strongAuth, targetUserId);
+            mKeyguardSecurityCallback.finish(strongAuth, targetUserId);
         }
         return finish;
     }
@@ -599,11 +812,114 @@
      * @return the {@link OnBackAnimationCallback} to animate this view during a back gesture.
      */
     @NonNull
-    OnBackAnimationCallback getBackCallback() {
+    public OnBackAnimationCallback getBackCallback() {
         return mView.getBackCallback();
     }
 
     /**
+     * @return whether we should dispatch the back key event before Ime.
+     */
+    public boolean dispatchBackKeyEventPreIme() {
+        return getCurrentSecurityMode() == SecurityMode.Password;
+    }
+
+    /**
+     * Allows the media keys to work when the keyguard is showing.
+     * The media keys should be of no interest to the actual keyguard view(s),
+     * so intercepting them here should not be of any harm.
+     * @param event The key event
+     * @return whether the event was consumed as a media key.
+     */
+    public boolean interceptMediaKey(KeyEvent event) {
+        int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                    /* Suppress PLAY/PAUSE toggle when phone is ringing or
+                     * in-call to avoid music playback */
+                    if (mTelephonyManager != null
+                            && mTelephonyManager.getCallState()
+                            != TelephonyManager.CALL_STATE_IDLE) {
+                        return true;  // suppress key event
+                    }
+                    return false;
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+
+                case KeyEvent.KEYCODE_VOLUME_UP:
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                case KeyEvent.KEYCODE_VOLUME_MUTE: {
+                    if (KEYGUARD_MANAGES_VOLUME) {
+                        // Volume buttons should only function for music (local or remote).
+                        // TODO: Actually handle MUTE.
+                        mAudioManager.adjustSuggestedStreamVolume(
+                                keyCode == KeyEvent.KEYCODE_VOLUME_UP
+                                        ? AudioManager.ADJUST_RAISE
+                                        : AudioManager.ADJUST_LOWER /* direction */,
+                                AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */);
+                        // Don't execute default volume behavior
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            }
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_MUTE:
+                case KeyEvent.KEYCODE_HEADSETHOOK:
+                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                case KeyEvent.KEYCODE_MEDIA_STOP:
+                case KeyEvent.KEYCODE_MEDIA_NEXT:
+                case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+                case KeyEvent.KEYCODE_MEDIA_REWIND:
+                case KeyEvent.KEYCODE_MEDIA_RECORD:
+                case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+                case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
+                    handleMediaKeyEvent(event);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
+    private void handleMediaKeyEvent(KeyEvent keyEvent) {
+        mAudioManager.dispatchMediaKeyEvent(keyEvent);
+    }
+
+    /**
+     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+     * some cases where we wish to disable it, notably when the menu button placement or technology
+     * is prone to false positives.
+     *
+     * @return true if the menu key should be enabled
+     */
+    public boolean shouldEnableMenuKey() {
+        final Resources res = mView.getResources();
+        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+        return !configDisabled || isTestHarness || fileOverride;
+    }
+
+
+    /**
      * Switches to the given security view unless it's already being shown, in which case
      * this is a no-op.
      *
@@ -631,7 +947,7 @@
             configureMode();
         }
 
-        mSecurityCallback.onSecurityModeChanged(
+        mKeyguardSecurityCallback.onSecurityModeChanged(
                 securityMode, newView != null && newView.needsInput());
     }
 
@@ -729,6 +1045,30 @@
      * configuration.
      */
     public void updateResources() {
+        int gravity;
+
+        Resources resources = mView.getResources();
+
+        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
+            gravity = resources.getInteger(
+                    R.integer.keyguard_host_view_one_handed_gravity);
+        } else {
+            gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
+        }
+
+        mTranslationY = resources
+                .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
+        // Android SysUI uses a FrameLayout as the top-level, but Auto uses RelativeLayout.
+        // We're just changing the gravity here though (which can't be applied to RelativeLayout),
+        // so only attempt the update if mView is inside a FrameLayout.
+        if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
+            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
+            if (lp.gravity != gravity) {
+                lp.gravity = gravity;
+                mView.setLayoutParams(lp);
+            }
+        }
+
         int newOrientation = getResources().getConfiguration().orientation;
         if (newOrientation != mLastOrientation) {
             mLastOrientation = newOrientation;
@@ -765,77 +1105,15 @@
                 mKeyguardSecurityCallback);
     }
 
-    static class Factory {
-
-        private final KeyguardSecurityContainer mView;
-        private final AdminSecondaryLockScreenController.Factory
-                mAdminSecondaryLockScreenControllerFactory;
-        private final LockPatternUtils mLockPatternUtils;
-        private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-        private final KeyguardSecurityModel mKeyguardSecurityModel;
-        private final MetricsLogger mMetricsLogger;
-        private final UiEventLogger mUiEventLogger;
-        private final KeyguardStateController mKeyguardStateController;
-        private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
-        private final ConfigurationController mConfigurationController;
-        private final FalsingCollector mFalsingCollector;
-        private final FalsingManager mFalsingManager;
-        private final GlobalSettings mGlobalSettings;
-        private final FeatureFlags mFeatureFlags;
-        private final UserSwitcherController mUserSwitcherController;
-        private final SessionTracker mSessionTracker;
-        private final Optional<SideFpsController> mSidefpsController;
-        private final FalsingA11yDelegate mFalsingA11yDelegate;
-
-        @Inject
-        Factory(KeyguardSecurityContainer view,
-                AdminSecondaryLockScreenController.Factory
-                        adminSecondaryLockScreenControllerFactory,
-                LockPatternUtils lockPatternUtils,
-                KeyguardUpdateMonitor keyguardUpdateMonitor,
-                KeyguardSecurityModel keyguardSecurityModel,
-                MetricsLogger metricsLogger,
-                UiEventLogger uiEventLogger,
-                KeyguardStateController keyguardStateController,
-                KeyguardSecurityViewFlipperController securityViewFlipperController,
-                ConfigurationController configurationController,
-                FalsingCollector falsingCollector,
-                FalsingManager falsingManager,
-                UserSwitcherController userSwitcherController,
-                FeatureFlags featureFlags,
-                GlobalSettings globalSettings,
-                SessionTracker sessionTracker,
-                Optional<SideFpsController> sidefpsController,
-                FalsingA11yDelegate falsingA11yDelegate) {
-            mView = view;
-            mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
-            mLockPatternUtils = lockPatternUtils;
-            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-            mKeyguardSecurityModel = keyguardSecurityModel;
-            mMetricsLogger = metricsLogger;
-            mUiEventLogger = uiEventLogger;
-            mKeyguardStateController = keyguardStateController;
-            mSecurityViewFlipperController = securityViewFlipperController;
-            mConfigurationController = configurationController;
-            mFalsingCollector = falsingCollector;
-            mFalsingManager = falsingManager;
-            mFeatureFlags = featureFlags;
-            mGlobalSettings = globalSettings;
-            mUserSwitcherController = userSwitcherController;
-            mSessionTracker = sessionTracker;
-            mSidefpsController = sidefpsController;
-            mFalsingA11yDelegate = falsingA11yDelegate;
-        }
-
-        public KeyguardSecurityContainerController create(
-                SecurityCallback securityCallback) {
-            return new KeyguardSecurityContainerController(mView,
-                    mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
-                    mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
-                    mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
-                    mConfigurationController, mFalsingCollector, mFalsingManager,
-                    mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker,
-                    mSidefpsController, mFalsingA11yDelegate);
-        }
+    /**
+     * Fades and translates in/out the security screen.
+     * Fades in as expansion approaches 0.
+     * Animation duration is between 0.33f and 0.67f of panel expansion fraction.
+     * @param fraction amount of the screen that should show.
+     */
+    public void setExpansion(float fraction) {
+        float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction);
+        mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f));
+        mView.setTranslationY(scaledFraction * mTranslationY);
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 5b628f8..addae72 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1942,11 +1942,23 @@
             FACE_AUTH_UPDATED_STARTED_WAKING_UP.setExtraInfo(pmWakeReason);
             updateFaceListeningState(BIOMETRIC_ACTION_UPDATE,
                     FACE_AUTH_UPDATED_STARTED_WAKING_UP);
-            requestActiveUnlock(
+
+            final ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin =
                     mActiveUnlockConfig.isWakeupConsideredUnlockIntent(pmWakeReason)
                             ? ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT
-                            : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE,
-                    "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason));
+                            : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE;
+            final String reason = "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason);
+            if (mActiveUnlockConfig.shouldWakeupForceDismissKeyguard(pmWakeReason)) {
+                requestActiveUnlockDismissKeyguard(
+                        requestOrigin,
+                        reason
+                );
+            } else {
+                requestActiveUnlock(
+                        requestOrigin,
+                        reason
+                );
+            }
         } else {
             mLogger.logSkipUpdateFaceListeningOnWakeup(pmWakeReason);
         }
@@ -2606,6 +2618,7 @@
         }
     }
 
+
     /**
      * Attempts to trigger active unlock from trust agent.
      * Only dismisses the keyguard under certain conditions.
@@ -2648,6 +2661,7 @@
                     ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT,
                     "alternateBouncer");
         }
+        updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
     }
 
     private boolean shouldTriggerActiveUnlock() {
@@ -2732,7 +2746,7 @@
                         || shouldListenForFingerprintAssistant
                         || (mKeyguardOccluded && mIsDreaming)
                         || (mKeyguardOccluded && userDoesNotHaveTrust
-                            && (mOccludingAppRequestingFp || isUdfps));
+                            && (mOccludingAppRequestingFp || isUdfps || mAlternateBouncerShowing));
 
         // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
@@ -2773,6 +2787,7 @@
                     System.currentTimeMillis(),
                     user,
                     shouldListen,
+                    mAlternateBouncerShowing,
                     biometricEnabledForUser,
                     mPrimaryBouncerIsOrWillBeShowing,
                     userCanSkipBouncer,
@@ -3803,7 +3818,7 @@
     }
 
     // TODO: use these callbacks elsewhere in place of the existing notifyScreen*()
-    // (KeyguardViewMediator, KeyguardHostView)
+    // (KeyguardViewMediator, KeyguardSecurityContainer)
     /**
      * Dispatch wakeup events to:
      *  - update biometric listening states
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 413a3ca..bfd99d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -468,6 +468,17 @@
         }
     }
 
+    /**
+     * @return whether the userUnlockedWithBiometric state changed
+     */
+    private boolean updateUserUnlockedWithBiometric() {
+        final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric;
+        mUserUnlockedWithBiometric =
+                mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
+                        KeyguardUpdateMonitor.getCurrentUser());
+        return wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric;
+    }
+
     private StatusBarStateController.StateListener mStatusBarStateListener =
             new StatusBarStateController.StateListener() {
                 @Override
@@ -505,11 +516,7 @@
 
                 @Override
                 public void onBiometricsCleared() {
-                    final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric;
-                    mUserUnlockedWithBiometric =
-                            mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
-                                    KeyguardUpdateMonitor.getCurrentUser());
-                    if (wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric) {
+                    if (updateUserUnlockedWithBiometric()) {
                         updateVisibility();
                     }
                 }
@@ -518,10 +525,8 @@
                 public void onBiometricRunningStateChanged(boolean running,
                         BiometricSourceType biometricSourceType) {
                     final boolean wasRunningFps = mRunningFPS;
-                    final boolean wasUserUnlockedWithBiometric = mUserUnlockedWithBiometric;
-                    mUserUnlockedWithBiometric =
-                            mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
-                                    KeyguardUpdateMonitor.getCurrentUser());
+                    final boolean userUnlockedWithBiometricChanged =
+                            updateUserUnlockedWithBiometric();
 
                     if (biometricSourceType == FINGERPRINT) {
                         mRunningFPS = running;
@@ -539,8 +544,7 @@
                         }
                     }
 
-                    if (wasUserUnlockedWithBiometric != mUserUnlockedWithBiometric
-                            || wasRunningFps != mRunningFPS) {
+                    if (userUnlockedWithBiometricChanged || wasRunningFps != mRunningFPS) {
                         updateVisibility();
                     }
                 }
@@ -551,6 +555,7 @@
         @Override
         public void onUnlockedChanged() {
             mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
+            updateUserUnlockedWithBiometric();
             updateKeyguardShowing();
             updateVisibility();
         }
@@ -568,9 +573,7 @@
 
             updateKeyguardShowing();
             if (mIsKeyguardShowing) {
-                mUserUnlockedWithBiometric =
-                    mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
-                        KeyguardUpdateMonitor.getCurrentUser());
+                updateUserUnlockedWithBiometric();
             }
             updateVisibility();
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index 5ad21df..154b0ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -18,7 +18,7 @@
 
 import android.view.ViewGroup;
 
-import com.android.keyguard.KeyguardHostViewController;
+import com.android.keyguard.KeyguardSecurityContainerController;
 import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
 
@@ -37,6 +37,6 @@
         KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
     }
 
-    /** Returns a {@link KeyguardHostViewController}. */
-    KeyguardHostViewController getKeyguardHostViewController();
+    /** Returns a {@link KeyguardSecurityContainerController}. */
+    KeyguardSecurityContainerController getSecurityContainerController();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index cb7a0a9..38f252a 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -23,7 +23,6 @@
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
-import com.android.keyguard.KeyguardHostView;
 import com.android.keyguard.KeyguardSecurityContainer;
 import com.android.keyguard.KeyguardSecurityViewFlipper;
 import com.android.systemui.R;
@@ -47,19 +46,13 @@
     /** */
     @Provides
     @KeyguardBouncerScope
-    static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView,
+    static KeyguardSecurityContainer providesKeyguardSecurityContainer(@RootView ViewGroup rootView,
             LayoutInflater layoutInflater) {
-        KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate(
-                R.layout.keyguard_host_view, rootView, false);
-        rootView.addView(hostView);
-        return hostView;
-    }
-
-    /** */
-    @Provides
-    @KeyguardBouncerScope
-    static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) {
-        return hostView.findViewById(R.id.keyguard_security_container);
+        KeyguardSecurityContainer securityContainer =
+                (KeyguardSecurityContainer) layoutInflater.inflate(
+                        R.layout.keyguard_security_container_view, rootView, false);
+        rootView.addView(securityContainer);
+        return securityContainer;
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
index 621b99d..6721c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.controls.controller.ControlsFavoritePersistenceWrapper
 import com.android.systemui.keyguard.domain.backup.KeyguardQuickAffordanceBackupHelper
 import com.android.systemui.people.widget.PeopleBackupHelper
+import com.android.systemui.settings.UserFileManagerImpl
 
 /**
  * Helper for backing up elements in SystemUI
@@ -58,17 +59,8 @@
 
     override fun onCreate(userHandle: UserHandle, operationType: Int) {
         super.onCreate()
-        // The map in mapOf is guaranteed to be order preserving
-        val controlsMap = mapOf(CONTROLS to getPPControlsFile(this))
-        NoOverwriteFileBackupHelper(controlsDataLock, this, controlsMap).also {
-            addHelper(NO_OVERWRITE_FILES_BACKUP_KEY, it)
-        }
 
-        // Conversations widgets backup only works for system user, because widgets' information is
-        // stored in system user's SharedPreferences files and we can't open those from other users.
-        if (!userHandle.isSystem) {
-            return
-        }
+        addControlsHelper(userHandle.identifier)
 
         val keys = PeopleBackupHelper.getFilesToBackup()
         addHelper(
@@ -95,6 +87,18 @@
         sendBroadcastAsUser(intent, UserHandle.SYSTEM, PERMISSION_SELF)
     }
 
+    private fun addControlsHelper(userId: Int) {
+        val file = UserFileManagerImpl.createFile(
+            userId = userId,
+            fileName = CONTROLS,
+        )
+        // The map in mapOf is guaranteed to be order preserving
+        val controlsMap = mapOf(file.getPath() to getPPControlsFile(this, userId))
+        NoOverwriteFileBackupHelper(controlsDataLock, this, controlsMap).also {
+            addHelper(NO_OVERWRITE_FILES_BACKUP_KEY, it)
+        }
+    }
+
     /**
      * Helper class for restoring files ONLY if they are not present.
      *
@@ -136,17 +140,21 @@
     }
 }
 
-private fun getPPControlsFile(context: Context): () -> Unit {
+private fun getPPControlsFile(context: Context, userId: Int): () -> Unit {
     return {
-        val filesDir = context.filesDir
-        val file = Environment.buildPath(filesDir, BackupHelper.CONTROLS)
+        val file = UserFileManagerImpl.createFile(
+            userId = userId,
+            fileName = BackupHelper.CONTROLS,
+        )
         if (file.exists()) {
-            val dest =
-                Environment.buildPath(filesDir, AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME)
+            val dest = UserFileManagerImpl.createFile(
+                userId = userId,
+                fileName = AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME,
+            )
             file.copyTo(dest)
             val jobScheduler = context.getSystemService(JobScheduler::class.java)
             jobScheduler?.schedule(
-                AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context)
+                AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context, userId)
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index c8cf5d7..e698faf 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -134,7 +134,6 @@
     private float mScaleFactor = 1f;
     // sensor locations without any resolution scaling nor rotation adjustments:
     @Nullable private final Point mFaceSensorLocationDefault;
-    @Nullable private final Point mFingerprintSensorLocationDefault;
     // cached sensor locations:
     @Nullable private Point mFaceSensorLocation;
     @Nullable private Point mFingerprintSensorLocation;
@@ -595,11 +594,23 @@
     @Nullable private Point getFingerprintSensorLocationInNaturalOrientation() {
         if (getUdfpsLocation() != null) {
             return getUdfpsLocation();
+        } else {
+            int xFpLocation = mCachedDisplayInfo.getNaturalWidth() / 2;
+            try {
+                xFpLocation = mContext.getResources().getDimensionPixelSize(
+                        com.android.systemui.R.dimen
+                                .physical_fingerprint_sensor_center_screen_location_x);
+            } catch (Resources.NotFoundException e) {
+            }
+
+            return new Point(
+                    (int) (xFpLocation * mScaleFactor),
+                    (int) (mContext.getResources().getDimensionPixelSize(
+                            com.android.systemui.R.dimen
+                                    .physical_fingerprint_sensor_center_screen_location_y)
+                            * mScaleFactor)
+            );
         }
-        return new Point(
-                (int) (mFingerprintSensorLocationDefault.x * mScaleFactor),
-                (int) (mFingerprintSensorLocationDefault.y * mScaleFactor)
-        );
     }
 
     /**
@@ -778,19 +789,6 @@
         }
 
         mDisplay = mContext.getDisplay();
-        mDisplay.getDisplayInfo(mCachedDisplayInfo);
-        int xFpLocation = mCachedDisplayInfo.getNaturalWidth() / 2;
-        try {
-            xFpLocation = mContext.getResources().getDimensionPixelSize(
-                    com.android.systemui.R.dimen
-                            .physical_fingerprint_sensor_center_screen_location_x);
-        } catch (Resources.NotFoundException e) {
-        }
-        mFingerprintSensorLocationDefault = new Point(
-                xFpLocation,
-                mContext.getResources().getDimensionPixelSize(com.android.systemui.R.dimen
-                        .physical_fingerprint_sensor_center_screen_location_y)
-        );
         updateSensorLocations();
 
         IntentFilter filter = new IntentFilter();
@@ -1265,7 +1263,6 @@
         pw.println("  mScaleFactor=" + mScaleFactor);
         pw.println("  faceAuthSensorLocationDefault=" + mFaceSensorLocationDefault);
         pw.println("  faceAuthSensorLocation=" + getFaceSensorLocation());
-        pw.println("  fingerprintSensorLocationDefault=" + mFingerprintSensorLocationDefault);
         pw.println("  fingerprintSensorLocationInNaturalOrientation="
                 + getFingerprintSensorLocationInNaturalOrientation());
         pw.println("  fingerprintSensorLocation=" + getFingerprintSensorLocation());
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
index 2e2970f..9847c10 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/EllipseOverlapDetector.kt
@@ -22,7 +22,9 @@
 import com.android.systemui.biometrics.EllipseOverlapDetectorParams
 import com.android.systemui.dagger.SysUISingleton
 import kotlin.math.cos
+import kotlin.math.pow
 import kotlin.math.sin
+import kotlin.math.sqrt
 
 private enum class SensorPixelPosition {
     OUTSIDE, // Pixel that falls outside of sensor circle
@@ -40,6 +42,11 @@
 @SysUISingleton
 class EllipseOverlapDetector(private val params: EllipseOverlapDetectorParams) : OverlapDetector {
     override fun isGoodOverlap(touchData: NormalizedTouchData, nativeSensorBounds: Rect): Boolean {
+        // First, check if entire ellipse is within the sensor
+        if (isEllipseWithinSensor(touchData, nativeSensorBounds)) {
+            return true
+        }
+
         var isTargetTouched = false
         var sensorPixels = 0
         var coveredPixels = 0
@@ -112,4 +119,28 @@
 
         return result <= 1
     }
+
+    /** Returns whether the entire ellipse is contained within the sensor area */
+    private fun isEllipseWithinSensor(
+        touchData: NormalizedTouchData,
+        nativeSensorBounds: Rect
+    ): Boolean {
+        val a2 = (touchData.minor / 2.0).pow(2.0)
+        val b2 = (touchData.major / 2.0).pow(2.0)
+
+        val sin2a = sin(touchData.orientation.toDouble()).pow(2.0)
+        val cos2a = cos(touchData.orientation.toDouble()).pow(2.0)
+
+        val cx = sqrt(a2 * cos2a + b2 * sin2a)
+        val cy = sqrt(a2 * sin2a + b2 * cos2a)
+
+        val ellipseRect =
+            Rect(
+                (-cx + touchData.x).toInt(),
+                (-cy + touchData.y).toInt(),
+                (cx + touchData.x).toInt(),
+                (cy + touchData.y).toInt()
+            )
+        return nativeSensorBounds.contains(ellipseRect)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index 0a6335e..b3c18fb 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -21,8 +21,10 @@
 import android.app.job.JobService
 import android.content.ComponentName
 import android.content.Context
+import android.os.PersistableBundle
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.backup.BackupHelper
+import com.android.systemui.settings.UserFileManagerImpl
 import java.io.File
 import java.util.concurrent.Executor
 import java.util.concurrent.TimeUnit
@@ -33,14 +35,14 @@
  * This file is a copy of the `controls_favorites.xml` file restored from a back up. It is used to
  * keep track of controls that were restored but its corresponding app has not been installed yet.
  */
-class AuxiliaryPersistenceWrapper @VisibleForTesting internal constructor(
-    wrapper: ControlsFavoritePersistenceWrapper
-) {
+class AuxiliaryPersistenceWrapper
+@VisibleForTesting
+internal constructor(wrapper: ControlsFavoritePersistenceWrapper) {
 
     constructor(
         file: File,
         executor: Executor
-    ): this(ControlsFavoritePersistenceWrapper(file, executor))
+    ) : this(ControlsFavoritePersistenceWrapper(file, executor))
 
     companion object {
         const val AUXILIARY_FILE_NAME = "aux_controls_favorites.xml"
@@ -48,9 +50,7 @@
 
     private var persistenceWrapper: ControlsFavoritePersistenceWrapper = wrapper
 
-    /**
-     * Access the current list of favorites as tracked by the auxiliary file
-     */
+    /** Access the current list of favorites as tracked by the auxiliary file */
     var favorites: List<StructureInfo> = emptyList()
         private set
 
@@ -73,18 +73,19 @@
      * exist, it will be initialized to an empty list.
      */
     fun initialize() {
-        favorites = if (persistenceWrapper.fileExists) {
-            persistenceWrapper.readFavorites()
-        } else {
-            emptyList()
-        }
+        favorites =
+            if (persistenceWrapper.fileExists) {
+                persistenceWrapper.readFavorites()
+            } else {
+                emptyList()
+            }
     }
 
     /**
      * Gets the list of favorite controls as persisted in the auxiliary file for a given component.
      *
-     * When the favorites for that application are returned, they will be removed from the
-     * auxiliary file immediately, so they won't be retrieved again.
+     * When the favorites for that application are returned, they will be removed from the auxiliary
+     * file immediately, so they won't be retrieved again.
      * @param componentName the name of the service that provided the controls
      * @return a list of structures with favorites
      */
@@ -103,20 +104,20 @@
         }
     }
 
-    /**
-     * [JobService] to delete the auxiliary file after a week.
-     */
+    /** [JobService] to delete the auxiliary file after a week. */
     class DeletionJobService : JobService() {
         companion object {
-            @VisibleForTesting
-            internal val DELETE_FILE_JOB_ID = 1000
+            @VisibleForTesting internal val DELETE_FILE_JOB_ID = 1000
+            @VisibleForTesting internal val USER = "USER"
             private val WEEK_IN_MILLIS = TimeUnit.DAYS.toMillis(7)
-            fun getJobForContext(context: Context): JobInfo {
+            fun getJobForContext(context: Context, targetUserId: Int): JobInfo {
                 val jobId = DELETE_FILE_JOB_ID + context.userId
                 val componentName = ComponentName(context, DeletionJobService::class.java)
+                val bundle = PersistableBundle().also { it.putInt(USER, targetUserId) }
                 return JobInfo.Builder(jobId, componentName)
                     .setMinimumLatency(WEEK_IN_MILLIS)
                     .setPersisted(true)
+                    .setExtras(bundle)
                     .build()
             }
         }
@@ -127,8 +128,14 @@
         }
 
         override fun onStartJob(params: JobParameters): Boolean {
+            val userId = params.getExtras()?.getInt(USER, 0) ?: 0
             synchronized(BackupHelper.controlsDataLock) {
-                baseContext.deleteFile(AUXILIARY_FILE_NAME)
+                val file =
+                    UserFileManagerImpl.createFile(
+                        userId = userId,
+                        fileName = AUXILIARY_FILE_NAME,
+                    )
+                baseContext.deleteFile(file.getPath())
             }
             return false
         }
@@ -137,4 +144,4 @@
             return true // reschedule and try again if the job was stopped without completing
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index ad5ad13..9921b1f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.dreams.AssistantAttentionMonitor
 import com.android.systemui.dreams.DreamMonitor
 import com.android.systemui.globalactions.GlobalActionsComponent
+import com.android.systemui.keyboard.PhysicalKeyboardCoreStartable
 import com.android.systemui.keyboard.KeyboardUI
 import com.android.systemui.keyguard.KeyguardViewMediator
 import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable
@@ -294,6 +295,11 @@
     @ClassKey(StylusUsiPowerStartable::class)
     abstract fun bindStylusUsiPowerStartable(sysui: StylusUsiPowerStartable): CoreStartable
 
+    @Binds
+    @IntoMap
+    @ClassKey(PhysicalKeyboardCoreStartable::class)
+    abstract fun bindKeyboardCoreStartable(listener: PhysicalKeyboardCoreStartable): CoreStartable
+
     /** Inject into MuteQuickAffordanceCoreStartable*/
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index a1050ec..f6bb85f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,6 +48,7 @@
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.FlagsModule;
 import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyboard.KeyboardModule;
 import com.android.systemui.keyguard.data.BouncerViewModule;
 import com.android.systemui.log.dagger.LogModule;
 import com.android.systemui.mediaprojection.appselector.MediaProjectionModule;
@@ -151,6 +152,7 @@
             SystemPropertiesFlagsModule.class,
             FooterActionsModule.class,
             GarbageMonitorModule.class,
+            KeyboardModule.class,
             LogModule.class,
             MediaProjectionModule.class,
             MotionToolModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
index dc7fc28..06ca0ad 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.util.InitializationChecker
+import com.android.systemui.util.concurrency.DelayableExecutor
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -36,7 +37,9 @@
     private val flagCommand: FlagCommand,
     private val featureFlags: FeatureFlagsDebug,
     private val broadcastSender: BroadcastSender,
-    private val initializationChecker: InitializationChecker
+    private val initializationChecker: InitializationChecker,
+    private val restartDozeListener: RestartDozeListener,
+    private val delayableExecutor: DelayableExecutor
 ) : CoreStartable {
 
     init {
@@ -52,6 +55,9 @@
             // protected broadcast should only be sent for the main process
             val intent = Intent(FlagManager.ACTION_SYSUI_STARTED)
             broadcastSender.sendBroadcast(intent)
+
+            restartDozeListener.init()
+            delayableExecutor.executeDelayed({ restartDozeListener.maybeRestartSleep() }, 1000)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt
index d088d74..133e67f 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsReleaseStartable.kt
@@ -18,6 +18,8 @@
 
 import com.android.systemui.CoreStartable
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.InitializationChecker
+import com.android.systemui.util.concurrency.DelayableExecutor
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -26,7 +28,13 @@
 
 class FeatureFlagsReleaseStartable
 @Inject
-constructor(dumpManager: DumpManager, featureFlags: FeatureFlags) : CoreStartable {
+constructor(
+    dumpManager: DumpManager,
+    featureFlags: FeatureFlags,
+    private val initializationChecker: InitializationChecker,
+    private val restartDozeListener: RestartDozeListener,
+    private val delayableExecutor: DelayableExecutor
+) : CoreStartable {
 
     init {
         dumpManager.registerCriticalDumpable(FeatureFlagsRelease.TAG) { pw, args ->
@@ -35,7 +43,10 @@
     }
 
     override fun start() {
-        // no-op
+        if (initializationChecker.initializeComponents()) {
+            restartDozeListener.init()
+            delayableExecutor.executeDelayed({ restartDozeListener.maybeRestartSleep() }, 1000)
+        }
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index d328f87..da59996 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -260,6 +260,11 @@
     // TODO(b/244064524): Tracking Bug
     @JvmField val QS_SECONDARY_DATA_SUB_INFO = releasedFlag(508, "qs_secondary_data_sub_info")
 
+    /** Enables Font Scaling Quick Settings tile */
+    // TODO(b/269341316): Tracking Bug
+    @JvmField
+    val ENABLE_FONT_SCALING_TILE = unreleasedFlag(509, "enable_font_scaling_tile", teamfood = false)
+
     // 600- status bar
 
     // TODO(b/256614753): Tracking Bug
diff --git a/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt b/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt
new file mode 100644
index 0000000..bd74f4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/RestartDozeListener.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.flags
+
+import android.os.PowerManager
+import android.util.Log
+import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.time.SystemClock
+import javax.inject.Inject
+
+@SysUISingleton
+class RestartDozeListener
+@Inject
+constructor(
+    private val settings: SecureSettings,
+    private val statusBarStateController: StatusBarStateController,
+    private val powerManager: PowerManager,
+    private val systemClock: SystemClock,
+) {
+
+    companion object {
+        @VisibleForTesting val RESTART_NAP_KEY = "restart_nap_after_start"
+    }
+
+    private var inited = false
+
+    val listener =
+        object : StatusBarStateController.StateListener {
+            override fun onDreamingChanged(isDreaming: Boolean) {
+                settings.putBool(RESTART_NAP_KEY, isDreaming)
+            }
+        }
+
+    fun init() {
+        if (inited) {
+            return
+        }
+        inited = true
+
+        statusBarStateController.addCallback(listener)
+    }
+
+    fun destroy() {
+        statusBarStateController.removeCallback(listener)
+    }
+
+    fun maybeRestartSleep() {
+        if (settings.getBool(RESTART_NAP_KEY, false)) {
+            Log.d("RestartDozeListener", "Restarting sleep state")
+            powerManager.wakeUp(systemClock.uptimeMillis())
+            powerManager.goToSleep(systemClock.uptimeMillis())
+            settings.putBool(RESTART_NAP_KEY, false)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
index e225b10..7acd3f3 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -62,11 +62,10 @@
                 return
             }
 
-
             for ((listener, flags) in listeners) {
                 propLoop@ for (propName in properties.keyset) {
                     for (flag in flags) {
-                        if (propName == getServerOverrideName(flag.id) || propName == flag.name) {
+                        if (propName == flag.name) {
                             listener.onChange(flag)
                             break@propLoop
                         }
@@ -103,10 +102,6 @@
         }
         listeners.add(Pair(listener, flags))
     }
-
-    private fun getServerOverrideName(flagId: Int): String {
-        return "flag_override_$flagId"
-    }
 }
 
 @Module
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
new file mode 100644
index 0000000..e9b8908
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -0,0 +1,22 @@
+/*
+ *  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.keyboard
+
+import dagger.Module
+
+@Module abstract class KeyboardModule
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
new file mode 100644
index 0000000..b0f9c4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt
@@ -0,0 +1,38 @@
+/*
+ *  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.keyboard
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+
+/** A [CoreStartable] that launches components interested in physical keyboard interaction. */
+@SysUISingleton
+class PhysicalKeyboardCoreStartable
+@Inject
+constructor(
+    private val featureFlags: FeatureFlags,
+) : CoreStartable {
+    override fun start() {
+        if (featureFlags.isEnabled(Flags.KEYBOARD_BACKLIGHT_INDICATOR)) {
+            // TODO(b/268645743) start listening for keyboard backlight brightness
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 2fb53f1..0ca9115 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -928,7 +928,7 @@
         }
 
         // The smartspace is not visible if the bouncer is showing, so don't shared element it.
-        if (keyguardStateController.isBouncerShowing) {
+        if (keyguardStateController.isPrimaryBouncerShowing) {
             return false
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c5ea241..54fc5b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1150,12 +1150,12 @@
     private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
             new KeyguardStateController.Callback() {
         @Override
-        public void onBouncerShowingChanged() {
+        public void onPrimaryBouncerShowingChanged() {
             synchronized (KeyguardViewMediator.this) {
-                if (mKeyguardStateController.isBouncerShowing()) {
+                if (mKeyguardStateController.isPrimaryBouncerShowing()) {
                     mPendingPinLock = false;
                 }
-                adjustStatusBarLocked(mKeyguardStateController.isBouncerShowing(), false);
+                adjustStatusBarLocked(mKeyguardStateController.isPrimaryBouncerShowing(), false);
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 091acad..4331fe6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -68,8 +68,8 @@
     val resourceUpdateRequests: StateFlow<Boolean>
     val bouncerPromptReason: Int
     val bouncerErrorMessage: CharSequence?
-    val isAlternateBouncerVisible: StateFlow<Boolean>
-    val isAlternateBouncerUIAvailable: StateFlow<Boolean>
+    val alternateBouncerVisible: StateFlow<Boolean>
+    val alternateBouncerUIAvailable: StateFlow<Boolean>
     var lastAlternateBouncerVisibleTime: Long
 
     fun setPrimaryScrimmed(isScrimmed: Boolean)
@@ -159,12 +159,12 @@
         get() = viewMediatorCallback.consumeCustomMessage()
 
     /** Values associated with the AlternateBouncer */
-    private val _isAlternateBouncerVisible = MutableStateFlow(false)
-    override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
+    private val _alternateBouncerVisible = MutableStateFlow(false)
+    override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow()
     override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
-    private val _isAlternateBouncerUIAvailable = MutableStateFlow(false)
-    override val isAlternateBouncerUIAvailable: StateFlow<Boolean> =
-        _isAlternateBouncerUIAvailable.asStateFlow()
+    private val _alternateBouncerUIAvailable = MutableStateFlow(false)
+    override val alternateBouncerUIAvailable: StateFlow<Boolean> =
+        _alternateBouncerUIAvailable.asStateFlow()
 
     init {
         setUpLogging()
@@ -179,16 +179,16 @@
     }
 
     override fun setAlternateVisible(isVisible: Boolean) {
-        if (isVisible && !_isAlternateBouncerVisible.value) {
+        if (isVisible && !_alternateBouncerVisible.value) {
             lastAlternateBouncerVisibleTime = clock.uptimeMillis()
         } else if (!isVisible) {
             lastAlternateBouncerVisibleTime = NOT_VISIBLE
         }
-        _isAlternateBouncerVisible.value = isVisible
+        _alternateBouncerVisible.value = isVisible
     }
 
     override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
-        _isAlternateBouncerUIAvailable.value = isAvailable
+        _alternateBouncerUIAvailable.value = isAvailable
     }
 
     override fun setPrimaryShow(keyguardBouncerModel: KeyguardBouncerModel?) {
@@ -290,7 +290,7 @@
         resourceUpdateRequests
             .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
             .launchIn(applicationScope)
-        isAlternateBouncerUIAvailable
+        alternateBouncerUIAvailable
             .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
             .launchIn(applicationScope)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
new file mode 100644
index 0000000..2069891
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
@@ -0,0 +1,342 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.hardware.face.FaceManager
+import android.os.CancellationSignal
+import com.android.internal.logging.InstanceId
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.FaceAuthUiEvent
+import com.android.systemui.Dumpable
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.AuthenticationStatus
+import com.android.systemui.keyguard.shared.model.DetectionStatus
+import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus
+import com.android.systemui.log.FaceAuthenticationLogger
+import com.android.systemui.log.SessionTracker
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.user.data.repository.UserRepository
+import java.io.PrintWriter
+import java.util.Arrays
+import java.util.stream.Collectors
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * API to run face authentication and detection for device entry / on keyguard (as opposed to the
+ * biometric prompt).
+ */
+interface KeyguardFaceAuthManager {
+    /**
+     * Trigger face authentication.
+     *
+     * [uiEvent] provided should be logged whenever face authentication runs. Invocation should be
+     * ignored if face authentication is already running. Results should be propagated through
+     * [authenticationStatus]
+     */
+    suspend fun authenticate(uiEvent: FaceAuthUiEvent)
+
+    /**
+     * Trigger face detection.
+     *
+     * Invocation should be ignored if face authentication is currently running.
+     */
+    suspend fun detect()
+
+    /** Stop currently running face authentication or detection. */
+    fun cancel()
+
+    /** Provide the current status of face authentication. */
+    val authenticationStatus: Flow<AuthenticationStatus>
+
+    /** Provide the current status of face detection. */
+    val detectionStatus: Flow<DetectionStatus>
+
+    /** Current state of whether face authentication is locked out or not. */
+    val isLockedOut: Flow<Boolean>
+
+    /** Current state of whether face authentication is running. */
+    val isAuthRunning: Flow<Boolean>
+
+    /** Is face detection supported. */
+    val isDetectionSupported: Boolean
+}
+
+@SysUISingleton
+class KeyguardFaceAuthManagerImpl
+@Inject
+constructor(
+    context: Context,
+    private val faceManager: FaceManager? = null,
+    private val userRepository: UserRepository,
+    private val keyguardBypassController: KeyguardBypassController? = null,
+    @Application private val applicationScope: CoroutineScope,
+    @Main private val mainDispatcher: CoroutineDispatcher,
+    private val sessionTracker: SessionTracker,
+    private val uiEventsLogger: UiEventLogger,
+    private val faceAuthLogger: FaceAuthenticationLogger,
+    dumpManager: DumpManager,
+) : KeyguardFaceAuthManager, Dumpable {
+    private var cancellationSignal: CancellationSignal? = null
+    private val lockscreenBypassEnabled: Boolean
+        get() = keyguardBypassController?.bypassEnabled ?: false
+    private var faceAcquiredInfoIgnoreList: Set<Int>
+
+    private val faceLockoutResetCallback =
+        object : FaceManager.LockoutResetCallback() {
+            override fun onLockoutReset(sensorId: Int) {
+                _isLockedOut.value = false
+            }
+        }
+
+    init {
+        faceManager?.addLockoutResetCallback(faceLockoutResetCallback)
+        faceAcquiredInfoIgnoreList =
+            Arrays.stream(
+                    context.resources.getIntArray(
+                        R.array.config_face_acquire_device_entry_ignorelist
+                    )
+                )
+                .boxed()
+                .collect(Collectors.toSet())
+        dumpManager.registerCriticalDumpable("KeyguardFaceAuthManagerImpl", this)
+    }
+
+    private val faceAuthCallback =
+        object : FaceManager.AuthenticationCallback() {
+            override fun onAuthenticationFailed() {
+                _authenticationStatus.value = FailedAuthenticationStatus
+                faceAuthLogger.authenticationFailed()
+                onFaceAuthRequestCompleted()
+            }
+
+            override fun onAuthenticationAcquired(acquireInfo: Int) {
+                _authenticationStatus.value = AcquiredAuthenticationStatus(acquireInfo)
+                faceAuthLogger.authenticationAcquired(acquireInfo)
+            }
+
+            override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
+                val errorStatus = ErrorAuthenticationStatus(errorCode, errString.toString())
+                if (errorStatus.isLockoutError()) {
+                    _isLockedOut.value = true
+                }
+                _authenticationStatus.value = errorStatus
+                if (errorStatus.isCancellationError()) {
+                    cancelNotReceivedHandlerJob?.cancel()
+                    applicationScope.launch {
+                        faceAuthLogger.launchingQueuedFaceAuthRequest(
+                            faceAuthRequestedWhileCancellation
+                        )
+                        faceAuthRequestedWhileCancellation?.let { authenticate(it) }
+                        faceAuthRequestedWhileCancellation = null
+                    }
+                }
+                faceAuthLogger.authenticationError(
+                    errorCode,
+                    errString,
+                    errorStatus.isLockoutError(),
+                    errorStatus.isCancellationError()
+                )
+                onFaceAuthRequestCompleted()
+            }
+
+            override fun onAuthenticationHelp(code: Int, helpStr: CharSequence?) {
+                if (faceAcquiredInfoIgnoreList.contains(code)) {
+                    return
+                }
+                _authenticationStatus.value = HelpAuthenticationStatus(code, helpStr.toString())
+            }
+
+            override fun onAuthenticationSucceeded(result: FaceManager.AuthenticationResult) {
+                _authenticationStatus.value = SuccessAuthenticationStatus(result)
+                faceAuthLogger.faceAuthSuccess(result)
+                onFaceAuthRequestCompleted()
+            }
+        }
+
+    private fun onFaceAuthRequestCompleted() {
+        cancellationInProgress = false
+        _isAuthRunning.value = false
+        cancellationSignal = null
+    }
+
+    private val detectionCallback =
+        FaceManager.FaceDetectionCallback { sensorId, userId, isStrong ->
+            faceAuthLogger.faceDetected()
+            _detectionStatus.value = DetectionStatus(sensorId, userId, isStrong)
+        }
+
+    private var cancellationInProgress = false
+    private var faceAuthRequestedWhileCancellation: FaceAuthUiEvent? = null
+
+    override suspend fun authenticate(uiEvent: FaceAuthUiEvent) {
+        if (_isAuthRunning.value) {
+            faceAuthLogger.ignoredFaceAuthTrigger(uiEvent)
+            return
+        }
+
+        if (cancellationInProgress) {
+            faceAuthLogger.queuingRequestWhileCancelling(
+                faceAuthRequestedWhileCancellation,
+                uiEvent
+            )
+            faceAuthRequestedWhileCancellation = uiEvent
+            return
+        } else {
+            faceAuthRequestedWhileCancellation = null
+        }
+
+        withContext(mainDispatcher) {
+            // We always want to invoke face auth in the main thread.
+            cancellationSignal = CancellationSignal()
+            _isAuthRunning.value = true
+            uiEventsLogger.logWithInstanceIdAndPosition(
+                uiEvent,
+                0,
+                null,
+                keyguardSessionId,
+                uiEvent.extraInfo
+            )
+            faceAuthLogger.authenticating(uiEvent)
+            faceManager?.authenticate(
+                null,
+                cancellationSignal,
+                faceAuthCallback,
+                null,
+                currentUserId,
+                lockscreenBypassEnabled
+            )
+        }
+    }
+
+    override suspend fun detect() {
+        if (!isDetectionSupported) {
+            faceAuthLogger.detectionNotSupported(faceManager, faceManager?.sensorPropertiesInternal)
+            return
+        }
+        if (_isAuthRunning.value) {
+            faceAuthLogger.skippingBecauseAlreadyRunning("detection")
+            return
+        }
+
+        cancellationSignal = CancellationSignal()
+        withContext(mainDispatcher) {
+            // We always want to invoke face detect in the main thread.
+            faceAuthLogger.faceDetectionStarted()
+            faceManager?.detectFace(cancellationSignal, detectionCallback, currentUserId)
+        }
+    }
+
+    private val currentUserId: Int
+        get() = userRepository.getSelectedUserInfo().id
+
+    override fun cancel() {
+        if (cancellationSignal == null) return
+
+        cancellationSignal?.cancel()
+        cancelNotReceivedHandlerJob =
+            applicationScope.launch {
+                delay(DEFAULT_CANCEL_SIGNAL_TIMEOUT)
+                faceAuthLogger.cancelSignalNotReceived(
+                    _isAuthRunning.value,
+                    _isLockedOut.value,
+                    cancellationInProgress,
+                    faceAuthRequestedWhileCancellation
+                )
+                onFaceAuthRequestCompleted()
+            }
+        cancellationInProgress = true
+        _isAuthRunning.value = false
+    }
+
+    private var cancelNotReceivedHandlerJob: Job? = null
+
+    private val _authenticationStatus: MutableStateFlow<AuthenticationStatus?> =
+        MutableStateFlow(null)
+    override val authenticationStatus: Flow<AuthenticationStatus>
+        get() = _authenticationStatus.filterNotNull()
+
+    private val _detectionStatus = MutableStateFlow<DetectionStatus?>(null)
+    override val detectionStatus: Flow<DetectionStatus>
+        get() = _detectionStatus.filterNotNull()
+
+    private val _isLockedOut = MutableStateFlow(false)
+    override val isLockedOut: Flow<Boolean> = _isLockedOut
+
+    override val isDetectionSupported =
+        faceManager?.sensorPropertiesInternal?.firstOrNull()?.supportsFaceDetection ?: false
+
+    private val _isAuthRunning = MutableStateFlow(false)
+    override val isAuthRunning: Flow<Boolean>
+        get() = _isAuthRunning
+
+    private val keyguardSessionId: InstanceId?
+        get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)
+
+    companion object {
+        const val TAG = "KeyguardFaceAuthManager"
+
+        /**
+         * If no cancel signal has been received after this amount of time, assume that it is
+         * cancelled.
+         */
+        const val DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000L
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("KeyguardFaceAuthManagerImpl state:")
+        pw.println("  cancellationInProgress: $cancellationInProgress")
+        pw.println("  _isLockedOut.value: ${_isLockedOut.value}")
+        pw.println("  _isAuthRunning.value: ${_isAuthRunning.value}")
+        pw.println("  isDetectionSupported: $isDetectionSupported")
+        pw.println("  FaceManager state:")
+        pw.println("    faceManager: $faceManager")
+        pw.println("    sensorPropertiesInternal: ${faceManager?.sensorPropertiesInternal}")
+        pw.println(
+            "    supportsFaceDetection: " +
+                "${faceManager?.sensorPropertiesInternal?.firstOrNull()?.supportsFaceDetection}"
+        )
+        pw.println(
+            "  faceAuthRequestedWhileCancellation: ${faceAuthRequestedWhileCancellation?.reason}"
+        )
+        pw.println("  cancellationSignal: $cancellationSignal")
+        pw.println("  faceAcquiredInfoIgnoreList: $faceAcquiredInfoIgnoreList")
+        pw.println("  _authenticationStatus: ${_authenticationStatus.value}")
+        pw.println("  _detectionStatus: ${_detectionStatus.value}")
+        pw.println("  currentUserId: $currentUserId")
+        pw.println("  keyguardSessionId: $keyguardSessionId")
+        pw.println("  lockscreenBypassEnabled: $lockscreenBypassEnabled")
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index db95562..a3b3d0f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -86,9 +86,6 @@
     /** Observable for the signal that keyguard is about to go away. */
     val isKeyguardGoingAway: Flow<Boolean>
 
-    /** Observable for whether the bouncer is showing. */
-    val isBouncerShowing: Flow<Boolean>
-
     /** Is the always-on display available to be used? */
     val isAodAvailable: Flow<Boolean>
 
@@ -304,29 +301,6 @@
         awaitClose { keyguardStateController.removeCallback(callback) }
     }
 
-    override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow {
-        val callback =
-            object : KeyguardStateController.Callback {
-                override fun onBouncerShowingChanged() {
-                    trySendWithFailureLogging(
-                        keyguardStateController.isBouncerShowing,
-                        TAG,
-                        "updated isBouncerShowing"
-                    )
-                }
-            }
-
-        keyguardStateController.addCallback(callback)
-        // Adding the callback does not send an initial update.
-        trySendWithFailureLogging(
-            keyguardStateController.isBouncerShowing,
-            TAG,
-            "initial isBouncerShowing"
-        )
-
-        awaitClose { keyguardStateController.removeCallback(callback) }
-    }
-
     override val isDozing: Flow<Boolean> =
         conflatedCallbackFlow {
                 val callback =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt
index 0e865ce..fa6efa5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/backup/KeyguardQuickAffordanceBackupHelper.kt
@@ -29,16 +29,9 @@
 ) :
     SharedPreferencesBackupHelper(
         context,
-        if (UserFileManagerImpl.isPrimaryUser(userId)) {
-            KeyguardQuickAffordanceSelectionManager.FILE_NAME
-        } else {
-            UserFileManagerImpl.secondaryUserFile(
-                    context = context,
-                    fileName = KeyguardQuickAffordanceSelectionManager.FILE_NAME,
-                    directoryName = UserFileManagerImpl.SHARED_PREFS,
-                    userId = userId,
-                )
-                .also { UserFileManagerImpl.ensureParentDirExists(it) }
-                .toString()
-        }
+        UserFileManagerImpl.createFile(
+                userId = userId,
+                fileName = KeyguardQuickAffordanceSelectionManager.FILE_NAME,
+            )
+            .getPath()
     )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 6452e0e..dfe1038 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -44,7 +44,7 @@
     var legacyAlternateBouncer: LegacyAlternateBouncer? = null
     var legacyAlternateBouncerVisibleTime: Long = NOT_VISIBLE
 
-    val isVisible: Flow<Boolean> = bouncerRepository.isAlternateBouncerVisible
+    val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
 
     /**
      * Sets the correct bouncer states to show the alternate bouncer if it can show.
@@ -86,7 +86,7 @@
 
     fun isVisibleState(): Boolean {
         return if (isModernAlternateBouncerEnabled) {
-            bouncerRepository.isAlternateBouncerVisible.value
+            bouncerRepository.alternateBouncerVisible.value
         } else {
             legacyAlternateBouncer?.isShowingAlternateBouncer ?: false
         }
@@ -98,7 +98,7 @@
 
     fun canShowAlternateBouncerForFingerprint(): Boolean {
         return if (isModernAlternateBouncerEnabled) {
-            bouncerRepository.isAlternateBouncerUIAvailable.value &&
+            bouncerRepository.alternateBouncerUIAvailable.value &&
                 biometricSettingsRepository.isFingerprintEnrolled.value &&
                 biometricSettingsRepository.isStrongBiometricAllowed.value &&
                 biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
new file mode 100644
index 0000000..310f44d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -0,0 +1,158 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.keyguard.shared.model.WakefulnessState
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class FromAlternateBouncerTransitionInteractor
+@Inject
+constructor(
+    @Application private val scope: CoroutineScope,
+    private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardTransitionRepository: KeyguardTransitionRepository,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : TransitionInteractor(FromAlternateBouncerTransitionInteractor::class.simpleName!!) {
+
+    override fun start() {
+        listenForAlternateBouncerToGone()
+        listenForAlternateBouncerToLockscreenAodOrDozing()
+        listenForAlternateBouncerToPrimaryBouncer()
+    }
+
+    private fun listenForAlternateBouncerToLockscreenAodOrDozing() {
+        scope.launch {
+            keyguardInteractor.alternateBouncerShowing
+                // Add a slight delay, as alternateBouncer and primaryBouncer showing event changes
+                // will arrive with a small gap in time. This prevents a transition to LOCKSCREEN
+                // happening prematurely.
+                .onEach { delay(50) }
+                .sample(
+                    combine(
+                        keyguardInteractor.primaryBouncerShowing,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
+                        keyguardInteractor.wakefulnessModel,
+                        keyguardInteractor.isAodAvailable,
+                        ::toQuad
+                    ),
+                    ::toQuint
+                )
+                .collect {
+                    (
+                        isAlternateBouncerShowing,
+                        isPrimaryBouncerShowing,
+                        lastStartedTransitionStep,
+                        wakefulnessState,
+                        isAodAvailable
+                    ) ->
+                    if (
+                        !isAlternateBouncerShowing &&
+                            !isPrimaryBouncerShowing &&
+                            lastStartedTransitionStep.to == KeyguardState.ALTERNATE_BOUNCER
+                    ) {
+                        val to =
+                            if (
+                                wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
+                                    wakefulnessState.state == WakefulnessState.ASLEEP
+                            ) {
+                                if (isAodAvailable) {
+                                    KeyguardState.AOD
+                                } else {
+                                    KeyguardState.DOZING
+                                }
+                            } else {
+                                KeyguardState.LOCKSCREEN
+                            }
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                ownerName = name,
+                                from = KeyguardState.ALTERNATE_BOUNCER,
+                                to = to,
+                                animator = getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun listenForAlternateBouncerToGone() {
+        scope.launch {
+            keyguardInteractor.isKeyguardGoingAway
+                .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
+                .collect { (isKeyguardGoingAway, keyguardState) ->
+                    if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                ownerName = name,
+                                from = KeyguardState.ALTERNATE_BOUNCER,
+                                to = KeyguardState.GONE,
+                                animator = getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun listenForAlternateBouncerToPrimaryBouncer() {
+        scope.launch {
+            keyguardInteractor.primaryBouncerShowing
+                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+                .collect { (isPrimaryBouncerShowing, startedKeyguardState) ->
+                    if (
+                        isPrimaryBouncerShowing &&
+                            startedKeyguardState.to == KeyguardState.ALTERNATE_BOUNCER
+                    ) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                ownerName = name,
+                                from = KeyguardState.ALTERNATE_BOUNCER,
+                                to = KeyguardState.PRIMARY_BOUNCER,
+                                animator = getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun getAnimator(): ValueAnimator {
+        return ValueAnimator().apply {
+            interpolator = Interpolators.LINEAR
+            duration = TRANSITION_DURATION_MS
+        }
+    }
+
+    companion object {
+        private const val TRANSITION_DURATION_MS = 300L
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 5674e2a..d01f489 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -33,7 +33,6 @@
 import kotlin.time.Duration
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
@@ -53,9 +52,10 @@
         listenForLockscreenToOccluded()
         listenForLockscreenToCamera()
         listenForLockscreenToAodOrDozing()
-        listenForLockscreenToBouncer()
+        listenForLockscreenToPrimaryBouncer()
         listenForLockscreenToDreaming()
-        listenForLockscreenToBouncerDragging()
+        listenForLockscreenToPrimaryBouncerDragging()
+        listenForLockscreenToAlternateBouncer()
     }
 
     private fun listenForLockscreenToDreaming() {
@@ -78,9 +78,9 @@
         }
     }
 
-    private fun listenForLockscreenToBouncer() {
+    private fun listenForLockscreenToPrimaryBouncer() {
         scope.launch {
-            keyguardInteractor.isBouncerShowing
+            keyguardInteractor.primaryBouncerShowing
                 .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
                 .collect { pair ->
                     val (isBouncerShowing, lastStartedTransitionStep) = pair
@@ -91,7 +91,30 @@
                             TransitionInfo(
                                 ownerName = name,
                                 from = KeyguardState.LOCKSCREEN,
-                                to = KeyguardState.BOUNCER,
+                                to = KeyguardState.PRIMARY_BOUNCER,
+                                animator = getAnimator(),
+                            )
+                        )
+                    }
+                }
+        }
+    }
+
+    private fun listenForLockscreenToAlternateBouncer() {
+        scope.launch {
+            keyguardInteractor.alternateBouncerShowing
+                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+                .collect { pair ->
+                    val (isAlternateBouncerShowing, lastStartedTransitionStep) = pair
+                    if (
+                        isAlternateBouncerShowing &&
+                            lastStartedTransitionStep.to == KeyguardState.LOCKSCREEN
+                    ) {
+                        keyguardTransitionRepository.startTransition(
+                            TransitionInfo(
+                                ownerName = name,
+                                from = KeyguardState.LOCKSCREEN,
+                                to = KeyguardState.ALTERNATE_BOUNCER,
                                 animator = getAnimator(),
                             )
                         )
@@ -101,7 +124,7 @@
     }
 
     /* Starts transitions when manually dragging up the bouncer from the lockscreen. */
-    private fun listenForLockscreenToBouncerDragging() {
+    private fun listenForLockscreenToPrimaryBouncerDragging() {
         var transitionId: UUID? = null
         scope.launch {
             shadeRepository.shadeModel
@@ -144,7 +167,7 @@
                             keyguardTransitionRepository.startTransition(
                                 TransitionInfo(
                                     ownerName = name,
-                                    from = KeyguardState.BOUNCER,
+                                    from = KeyguardState.PRIMARY_BOUNCER,
                                     to = KeyguardState.LOCKSCREEN,
                                     animator = getAnimator(0.milliseconds)
                                 )
@@ -163,7 +186,7 @@
                                     TransitionInfo(
                                         ownerName = name,
                                         from = KeyguardState.LOCKSCREEN,
-                                        to = KeyguardState.BOUNCER,
+                                        to = KeyguardState.PRIMARY_BOUNCER,
                                         animator = null,
                                     )
                                 )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
similarity index 75%
rename from packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromBouncerTransitionInteractor.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index 0e9c447..b59b413 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -24,62 +24,63 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionInfo
 import com.android.systemui.keyguard.shared.model.WakefulnessState
-import com.android.systemui.shade.data.repository.ShadeRepository
 import com.android.systemui.util.kotlin.sample
-import java.util.UUID
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
 @SysUISingleton
-class FromBouncerTransitionInteractor
+class FromPrimaryBouncerTransitionInteractor
 @Inject
 constructor(
     @Application private val scope: CoroutineScope,
     private val keyguardInteractor: KeyguardInteractor,
-    private val shadeRepository: ShadeRepository,
     private val keyguardTransitionRepository: KeyguardTransitionRepository,
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor
-) : TransitionInteractor(FromBouncerTransitionInteractor::class.simpleName!!) {
-
-    private var transitionId: UUID? = null
+) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
 
     override fun start() {
-        listenForBouncerToGone()
-        listenForBouncerToLockscreenOrAod()
+        listenForPrimaryBouncerToGone()
+        listenForPrimaryBouncerToLockscreenAodOrDozing()
     }
 
-    private fun listenForBouncerToLockscreenOrAod() {
+    private fun listenForPrimaryBouncerToLockscreenAodOrDozing() {
         scope.launch {
-            keyguardInteractor.isBouncerShowing
+            keyguardInteractor.primaryBouncerShowing
                 .sample(
                     combine(
                         keyguardInteractor.wakefulnessModel,
                         keyguardTransitionInteractor.startedKeyguardTransitionStep,
-                        ::Pair
+                        keyguardInteractor.isAodAvailable,
+                        ::toTriple
                     ),
-                    ::toTriple
+                    ::toQuad
                 )
-                .collect { triple ->
-                    val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple
+                .collect {
+                    (isBouncerShowing, wakefulnessState, lastStartedTransitionStep, isAodAvailable)
+                    ->
                     if (
-                        !isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER
+                        !isBouncerShowing &&
+                            lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
                     ) {
                         val to =
                             if (
                                 wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
                                     wakefulnessState.state == WakefulnessState.ASLEEP
                             ) {
-                                KeyguardState.AOD
+                                if (isAodAvailable) {
+                                    KeyguardState.AOD
+                                } else {
+                                    KeyguardState.DOZING
+                                }
                             } else {
                                 KeyguardState.LOCKSCREEN
                             }
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 ownerName = name,
-                                from = KeyguardState.BOUNCER,
+                                from = KeyguardState.PRIMARY_BOUNCER,
                                 to = to,
                                 animator = getAnimator(),
                             )
@@ -89,17 +90,17 @@
         }
     }
 
-    private fun listenForBouncerToGone() {
+    private fun listenForPrimaryBouncerToGone() {
         scope.launch {
             keyguardInteractor.isKeyguardGoingAway
-                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+                .sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) }
                 .collect { pair ->
                     val (isKeyguardGoingAway, keyguardState) = pair
-                    if (isKeyguardGoingAway && keyguardState == KeyguardState.BOUNCER) {
+                    if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) {
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 ownerName = name,
-                                from = KeyguardState.BOUNCER,
+                                from = KeyguardState.PRIMARY_BOUNCER,
                                 to = KeyguardState.GONE,
                                 animator = getAnimator(),
                             )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 7e86a5d..d25aff0a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -56,6 +57,7 @@
     private val repository: KeyguardRepository,
     private val commandQueue: CommandQueue,
     featureFlags: FeatureFlags,
+    bouncerRepository: KeyguardBouncerRepository,
 ) {
     /**
      * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at
@@ -121,8 +123,10 @@
     val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
     /** Whether the keyguard is going away. */
     val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
-    /** Whether the bouncer is showing or not. */
-    val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
+    /** Whether the primary bouncer is showing or not. */
+    val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
+    /** Whether the alternate bouncer is showing or not. */
+    val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
     /** The device wake/sleep state */
     val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
     /** Observable for the [StatusBarState] */
@@ -142,12 +146,12 @@
         if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
             combine(
                     isKeyguardVisible,
-                    repository.isBouncerShowing,
+                    bouncerRepository.primaryBouncerVisible,
                     onCameraLaunchDetected,
-                ) { isKeyguardVisible, isBouncerShowing, cameraLaunchEvent ->
+                ) { isKeyguardVisible, isPrimaryBouncerShowing, cameraLaunchEvent ->
                     when {
                         isKeyguardVisible -> false
-                        isBouncerShowing -> false
+                        isPrimaryBouncerShowing -> false
                         else -> cameraLaunchEvent == CameraLaunchSourceModel.POWER_DOUBLE_TAP
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index d4e23499..51b0277 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.plugins.log.LogLevel.VERBOSE
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 
 private val TAG = KeyguardTransitionAuditLogger::class.simpleName!!
@@ -46,8 +45,14 @@
         }
 
         scope.launch {
-            keyguardInteractor.isBouncerShowing.collect {
-                logger.log(TAG, VERBOSE, "Bouncer showing", it)
+            keyguardInteractor.primaryBouncerShowing.collect {
+                logger.log(TAG, VERBOSE, "Primary bouncer showing", it)
+            }
+        }
+
+        scope.launch {
+            keyguardInteractor.alternateBouncerShowing.collect {
+                logger.log(TAG, VERBOSE, "Alternate bouncer showing", it)
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index fbed446..efc1bd0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -37,13 +37,14 @@
             // exhaustive
             val ret =
                 when (it) {
-                    is FromBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
+                    is FromPrimaryBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromAodTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromGoneTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromDreamingTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromOccludedTransitionInteractor -> Log.d(TAG, "Started $it")
                     is FromDozingTransitionInteractor -> Log.d(TAG, "Started $it")
+                    is FromAlternateBouncerTransitionInteractor -> Log.d(TAG, "Started $it")
                 }
             it.start()
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 84bcdf9..1b7da5b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -21,13 +21,12 @@
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
-import com.android.systemui.keyguard.shared.model.KeyguardState.BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
+import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.shared.model.TransitionState
-import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
@@ -63,9 +62,9 @@
     /** LOCKSCREEN->AOD transition information. */
     val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
 
-    /** LOCKSCREEN->BOUNCER transition information. */
-    val lockscreenToBouncerTransition: Flow<TransitionStep> =
-        repository.transition(LOCKSCREEN, BOUNCER)
+    /** LOCKSCREEN->PRIMARY_BOUNCER transition information. */
+    val mLockscreenToPrimaryBouncerTransition: Flow<TransitionStep> =
+        repository.transition(LOCKSCREEN, PRIMARY_BOUNCER)
 
     /** LOCKSCREEN->DREAMING transition information. */
     val lockscreenToDreamingTransition: Flow<TransitionStep> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
index a59c407..833eda7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
@@ -86,7 +86,8 @@
                 KeyguardState.DOZING -> false
                 KeyguardState.AOD -> false
                 KeyguardState.DREAMING -> true
-                KeyguardState.BOUNCER -> true
+                KeyguardState.ALTERNATE_BOUNCER -> true
+                KeyguardState.PRIMARY_BOUNCER -> true
                 KeyguardState.LOCKSCREEN -> true
                 KeyguardState.GONE -> true
                 KeyguardState.OCCLUDED -> true
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index 4579e37..e819da9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -156,7 +156,7 @@
         } else {
             DejankUtils.postAfterTraversal(showRunnable)
         }
-        keyguardStateController.notifyBouncerShowing(true)
+        keyguardStateController.notifyPrimaryBouncerShowing(true)
         primaryBouncerCallbackInteractor.dispatchStartingToShow()
         Trace.endSection()
     }
@@ -173,7 +173,7 @@
         }
 
         falsingCollector.onBouncerHidden()
-        keyguardStateController.notifyBouncerShowing(false /* showing */)
+        keyguardStateController.notifyPrimaryBouncerShowing(false /* showing */)
         cancelShowRunnable()
         repository.setPrimaryShowingSoon(false)
         repository.setPrimaryVisible(false)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
index 81fa233..d9690b7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
@@ -32,7 +32,9 @@
 
     @Binds
     @IntoSet
-    abstract fun fromBouncer(impl: FromBouncerTransitionInteractor): TransitionInteractor
+    abstract fun fromPrimaryBouncer(
+        impl: FromPrimaryBouncerTransitionInteractor
+    ): TransitionInteractor
 
     @Binds
     @IntoSet
@@ -53,4 +55,10 @@
     @Binds
     @IntoSet
     abstract fun fromDozing(impl: FromDozingTransitionInteractor): TransitionInteractor
+
+    @Binds
+    @IntoSet
+    abstract fun fromAlternateBouncer(
+        impl: FromAlternateBouncerTransitionInteractor
+    ): TransitionInteractor
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
index 4d24c14..e3e3527 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -30,7 +30,26 @@
 
     abstract fun start()
 
+    fun <A, B, C> toTriple(a: A, b: B, c: C) = Triple(a, b, c)
+
     fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second)
 
     fun <A, B, C> toTriple(ab: Pair<A, B>, c: C) = Triple(ab.first, ab.second, c)
+
+    fun <A, B, C, D> toQuad(a: A, b: B, c: C, d: D) = Quad(a, b, c, d)
+
+    fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) = Quad(a, bcd.first, bcd.second, bcd.third)
+
+    fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) =
+        Quint(a, bcde.first, bcde.second, bcde.third, bcde.fourth)
 }
+
+data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)
+
+data class Quint<A, B, C, D, E>(
+    val first: A,
+    val second: B,
+    val third: C,
+    val fourth: D,
+    val fifth: E
+)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
new file mode 100644
index 0000000..b1c5f8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.keyguard.shared.model
+
+import android.hardware.face.FaceManager
+
+/** Authentication status provided by [com.android.keyguard.faceauth.KeyguardFaceAuthManager] */
+sealed class AuthenticationStatus
+
+/** Success authentication status. */
+data class SuccessAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) :
+    AuthenticationStatus()
+
+/** Face authentication help message. */
+data class HelpAuthenticationStatus(val msgId: Int, val msg: String?) : AuthenticationStatus()
+
+/** Face acquired message. */
+data class AcquiredAuthenticationStatus(val acquiredInfo: Int) : AuthenticationStatus()
+
+/** Face authentication failed message. */
+object FailedAuthenticationStatus : AuthenticationStatus()
+
+/** Face authentication error message */
+data class ErrorAuthenticationStatus(val msgId: Int, val msg: String?) : AuthenticationStatus() {
+    /**
+     * Method that checks if [msgId] is a lockout error. A lockout error means that face
+     * authentication is locked out.
+     */
+    fun isLockoutError() = msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT
+
+    /**
+     * Method that checks if [msgId] is a cancellation error. This means that face authentication
+     * was cancelled before it completed.
+     */
+    fun isCancellationError() = msgId == FaceManager.FACE_ERROR_CANCELED
+}
+
+/** Face detection success message. */
+data class DetectionStatus(val sensorId: Int, val userId: Int, val isStrongBiometric: Boolean)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
index c757986..87b4321 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -42,10 +42,15 @@
      */
     AOD,
     /*
-     * The security screen prompt UI, containing PIN, Password, Pattern, and all FPS
-     * (Fingerprint Sensor) variations, for the user to verify their credentials
+     * The security screen prompt containing UI to prompt the user to use a biometric credential
+     * (ie: fingerprint). When supported, this may show before showing the primary bouncer.
      */
-    BOUNCER,
+    ALTERNATE_BOUNCER,
+    /*
+     * The security screen prompt UI, containing PIN, Password, Pattern for the user to verify their
+     * credentials.
+     */
+    PRIMARY_BOUNCER,
     /*
      * Device is actively displaying keyguard UI and is not in low-power mode. Device may be
      * unlocked if SWIPE security method is used, or if face lockscreen bypass is false.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index b0c0dd7..56f911f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -22,10 +22,12 @@
 import android.window.OnBackAnimationCallback
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
-import com.android.keyguard.KeyguardHostViewController
+import com.android.keyguard.KeyguardSecurityContainerController
 import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityView
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.dagger.KeyguardBouncerComponent
+import com.android.settingslib.Utils
 import com.android.systemui.keyguard.data.BouncerViewDelegate
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
@@ -43,52 +45,54 @@
         viewModel: KeyguardBouncerViewModel,
         componentFactory: KeyguardBouncerComponent.Factory
     ) {
-        // Builds the KeyguardHostViewController from bouncer view group.
-        val hostViewController: KeyguardHostViewController =
-            componentFactory.create(view).keyguardHostViewController
-        hostViewController.init()
+        // Builds the KeyguardSecurityContainerController from bouncer view group.
+        val securityContainerController: KeyguardSecurityContainerController =
+            componentFactory.create(view).securityContainerController
+        securityContainerController.init()
         val delegate =
             object : BouncerViewDelegate {
                 override fun isFullScreenBouncer(): Boolean {
-                    val mode = hostViewController.currentSecurityMode
+                    val mode = securityContainerController.currentSecurityMode
                     return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
                         mode == KeyguardSecurityModel.SecurityMode.SimPuk
                 }
 
                 override fun getBackCallback(): OnBackAnimationCallback {
-                    return hostViewController.backCallback
+                    return securityContainerController.backCallback
                 }
 
                 override fun shouldDismissOnMenuPressed(): Boolean {
-                    return hostViewController.shouldEnableMenuKey()
+                    return securityContainerController.shouldEnableMenuKey()
                 }
 
                 override fun interceptMediaKey(event: KeyEvent?): Boolean {
-                    return hostViewController.interceptMediaKey(event)
+                    return securityContainerController.interceptMediaKey(event)
                 }
 
                 override fun dispatchBackKeyEventPreIme(): Boolean {
-                    return hostViewController.dispatchBackKeyEventPreIme()
+                    return securityContainerController.dispatchBackKeyEventPreIme()
                 }
 
                 override fun showNextSecurityScreenOrFinish(): Boolean {
-                    return hostViewController.dismiss(KeyguardUpdateMonitor.getCurrentUser())
+                    return securityContainerController.dismiss(
+                        KeyguardUpdateMonitor.getCurrentUser()
+                    )
                 }
 
                 override fun resume() {
-                    hostViewController.showPrimarySecurityScreen()
-                    hostViewController.onResume()
+                    securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
+                    securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
                 }
 
                 override fun setDismissAction(
                     onDismissAction: ActivityStarter.OnDismissAction?,
                     cancelAction: Runnable?
                 ) {
-                    hostViewController.setOnDismissAction(onDismissAction, cancelAction)
+                    securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
                 }
 
                 override fun willDismissWithActions(): Boolean {
-                    return hostViewController.hasDismissActions()
+                    return securityContainerController.hasDismissActions()
                 }
             }
         view.repeatWhenAttached {
@@ -98,38 +102,45 @@
                     launch {
                         viewModel.show.collect {
                             // Reset Security Container entirely.
-                            hostViewController.reinflateViewFlipper()
-                            hostViewController.showPromptReason(it.promptReason)
+                            securityContainerController.reinflateViewFlipper()
+                            securityContainerController.showPromptReason(it.promptReason)
                             it.errorMessage?.let { errorMessage ->
-                                hostViewController.showErrorMessage(errorMessage)
+                                securityContainerController.showMessage(
+                                    errorMessage,
+                                    Utils.getColorError(view.context)
+                                )
                             }
-                            hostViewController.showPrimarySecurityScreen()
-                            hostViewController.appear()
-                            hostViewController.onResume()
+                            securityContainerController.showPrimarySecurityScreen(
+                                /* turningOff= */ false
+                            )
+                            securityContainerController.appear()
+                            securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
                         }
                     }
 
                     launch {
                         viewModel.hide.collect {
-                            hostViewController.cancelDismissAction()
-                            hostViewController.cleanUp()
-                            hostViewController.resetSecurityContainer()
+                            securityContainerController.cancelDismissAction()
+                            securityContainerController.onPause()
+                            securityContainerController.reset()
                         }
                     }
 
                     launch {
-                        viewModel.startingToHide.collect { hostViewController.onStartingToHide() }
+                        viewModel.startingToHide.collect {
+                            securityContainerController.onStartingToHide()
+                        }
                     }
 
                     launch {
                         viewModel.startDisappearAnimation.collect {
-                            hostViewController.startDisappearAnimation(it)
+                            securityContainerController.startDisappearAnimation(it)
                         }
                     }
 
                     launch {
                         viewModel.bouncerExpansionAmount.collect { expansion ->
-                            hostViewController.setExpansion(expansion)
+                            securityContainerController.setExpansion(expansion)
                         }
                     }
 
@@ -137,10 +148,8 @@
                         viewModel.bouncerExpansionAmount
                             .filter { it == EXPANSION_VISIBLE }
                             .collect {
-                                hostViewController.onResume()
-                                view.announceForAccessibility(
-                                    hostViewController.accessibilityTitleForCurrentMode
-                                )
+                                securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
+                                view.announceForAccessibility(securityContainerController.title)
                             }
                     }
 
@@ -148,39 +157,42 @@
                         viewModel.isBouncerVisible.collect { isVisible ->
                             val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
                             view.visibility = visibility
-                            hostViewController.onBouncerVisibilityChanged(visibility)
+                            securityContainerController.onBouncerVisibilityChanged(visibility)
                         }
                     }
 
                     launch {
                         viewModel.isInteractable.collect { isInteractable ->
-                            hostViewController.setInteractable(isInteractable)
+                            securityContainerController.setInteractable(isInteractable)
                         }
                     }
 
                     launch {
                         viewModel.keyguardPosition.collect { position ->
-                            hostViewController.updateKeyguardPosition(position)
+                            securityContainerController.updateKeyguardPosition(position)
                         }
                     }
 
                     launch {
                         viewModel.updateResources.collect {
-                            hostViewController.updateResources()
+                            securityContainerController.updateResources()
                             viewModel.notifyUpdateResources()
                         }
                     }
 
                     launch {
                         viewModel.bouncerShowMessage.collect {
-                            hostViewController.showMessage(it.message, it.colorStateList)
+                            securityContainerController.showMessage(it.message, it.colorStateList)
                             viewModel.onMessageShown()
                         }
                     }
 
                     launch {
                         viewModel.keyguardAuthenticated.collect {
-                            hostViewController.finish(it, KeyguardUpdateMonitor.getCurrentUser())
+                            securityContainerController.finish(
+                                it,
+                                KeyguardUpdateMonitor.getCurrentUser()
+                            )
                             viewModel.notifyKeyguardAuthenticated()
                         }
                     }
@@ -194,7 +206,7 @@
                     launch {
                         viewModel.screenTurnedOff.collect {
                             if (view.visibility == View.VISIBLE) {
-                                hostViewController.onPause()
+                                securityContainerController.onPause()
                             }
                         }
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index d977f91..9aecb5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -171,7 +171,12 @@
     }
 
     private fun setUpClock(parentView: ViewGroup) {
-        val clockChangeListener = ClockRegistry.ClockChangeListener { onClockChanged(parentView) }
+        val clockChangeListener =
+            object : ClockRegistry.ClockChangeListener {
+                override fun onCurrentClockChanged() {
+                    onClockChanged(parentView)
+                }
+            }
         clockRegistry.registerClockChangeListener(clockChangeListener)
         disposables.add(
             DisposableHandle { clockRegistry.unregisterClockChangeListener(clockChangeListener) }
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
new file mode 100644
index 0000000..f7349a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -0,0 +1,181 @@
+package com.android.systemui.log
+
+import android.hardware.face.FaceManager
+import android.hardware.face.FaceSensorPropertiesInternal
+import com.android.keyguard.FaceAuthUiEvent
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.dagger.FaceAuthLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel.DEBUG
+import com.google.errorprone.annotations.CompileTimeConstant
+import javax.inject.Inject
+
+private const val TAG = "KeyguardFaceAuthManagerLog"
+
+/**
+ * Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
+ *
+ * To enable logcat echoing for an entire buffer:
+ *
+ * ```
+ *   adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
+ *
+ * ```
+ */
+@SysUISingleton
+class FaceAuthenticationLogger
+@Inject
+constructor(
+    @FaceAuthLog private val logBuffer: LogBuffer,
+) {
+    fun ignoredFaceAuthTrigger(uiEvent: FaceAuthUiEvent) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { str1 = uiEvent.reason },
+            {
+                "Ignoring trigger because face auth is currently running. " +
+                    "Trigger reason: $str1"
+            }
+        )
+    }
+
+    fun queuingRequestWhileCancelling(
+        alreadyQueuedRequest: FaceAuthUiEvent?,
+        newRequest: FaceAuthUiEvent
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                str1 = alreadyQueuedRequest?.reason
+                str2 = newRequest.reason
+            },
+            {
+                "Face auth requested while previous request is being cancelled, " +
+                    "already queued request: $str1 queueing the new request: $str2"
+            }
+        )
+    }
+
+    fun authenticating(uiEvent: FaceAuthUiEvent) {
+        logBuffer.log(TAG, DEBUG, { str1 = uiEvent.reason }, { "Running authenticate for $str1" })
+    }
+
+    fun detectionNotSupported(
+        faceManager: FaceManager?,
+        sensorPropertiesInternal: MutableList<FaceSensorPropertiesInternal>?
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = faceManager == null
+                bool2 = sensorPropertiesInternal.isNullOrEmpty()
+                bool2 = sensorPropertiesInternal?.firstOrNull()?.supportsFaceDetection ?: false
+            },
+            {
+                "skipping detection request because it is not supported, " +
+                    "faceManager isNull: $bool1, " +
+                    "sensorPropertiesInternal isNullOrEmpty: $bool2, " +
+                    "supportsFaceDetection: $bool3"
+            }
+        )
+    }
+
+    fun skippingBecauseAlreadyRunning(@CompileTimeConstant operation: String) {
+        logBuffer.log(TAG, DEBUG, "isAuthRunning is true, skipping $operation")
+    }
+
+    fun faceDetectionStarted() {
+        logBuffer.log(TAG, DEBUG, "Face detection started.")
+    }
+
+    fun faceDetected() {
+        logBuffer.log(TAG, DEBUG, "Face detected")
+    }
+
+    fun cancelSignalNotReceived(
+        isAuthRunning: Boolean,
+        isLockedOut: Boolean,
+        cancellationInProgress: Boolean,
+        faceAuthRequestedWhileCancellation: FaceAuthUiEvent?
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                bool1 = isAuthRunning
+                bool2 = isLockedOut
+                bool3 = cancellationInProgress
+                str1 = "${faceAuthRequestedWhileCancellation?.reason}"
+            },
+            {
+                "Cancel signal was not received, running timeout handler to reset state. " +
+                    "State before reset: " +
+                    "isAuthRunning: $bool1, " +
+                    "isLockedOut: $bool2, " +
+                    "cancellationInProgress: $bool3, " +
+                    "faceAuthRequestedWhileCancellation: $str1"
+            }
+        )
+    }
+
+    fun authenticationFailed() {
+        logBuffer.log(TAG, DEBUG, "Face authentication failed")
+    }
+
+    fun authenticationAcquired(acquireInfo: Int) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { int1 = acquireInfo },
+            { "Face acquired during face authentication: acquireInfo: $int1 " }
+        )
+    }
+
+    fun authenticationError(
+        errorCode: Int,
+        errString: CharSequence?,
+        lockoutError: Boolean,
+        cancellationError: Boolean
+    ) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = errorCode
+                str1 = "$errString"
+                bool1 = lockoutError
+                bool2 = cancellationError
+            },
+            {
+                "Received authentication error: errorCode: $int1, " +
+                    "errString: $str1, " +
+                    "isLockoutError: $bool1, " +
+                    "isCancellationError: $bool2"
+            }
+        )
+    }
+
+    fun launchingQueuedFaceAuthRequest(faceAuthRequestedWhileCancellation: FaceAuthUiEvent?) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            { str1 = "${faceAuthRequestedWhileCancellation?.reason}" },
+            { "Received cancellation error and starting queued face auth request: $str1" }
+        )
+    }
+
+    fun faceAuthSuccess(result: FaceManager.AuthenticationResult) {
+        logBuffer.log(
+            TAG,
+            DEBUG,
+            {
+                int1 = result.userId
+                bool1 = result.isStrongBiometric
+            },
+            { "Face authenticated successfully: userId: $int1, isStrongBiometric: $bool1" }
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/FaceAuthLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/FaceAuthLog.kt
new file mode 100644
index 0000000..b97e3a7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/FaceAuthLog.kt
@@ -0,0 +1,6 @@
+package com.android.systemui.log.dagger
+
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for Face authentication triggered by SysUI. */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class FaceAuthLog()
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index c02fd9c..220993f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -265,16 +265,6 @@
         return factory.create("MediaCarouselCtlrLog", 20);
     }
 
-    /**
-     * Provides a {@link LogBuffer} for use in the status bar connectivity pipeline
-     */
-    @Provides
-    @SysUISingleton
-    @StatusBarConnectivityLog
-    public static LogBuffer provideStatusBarConnectivityBuffer(LogBufferFactory factory) {
-        return factory.create("SbConnectivity", 64);
-    }
-
     /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
     @Provides
     @SysUISingleton
@@ -360,6 +350,17 @@
     }
 
     /**
+     * Provides a {@link LogBuffer} for use by
+     *  {@link com.android.keyguard.faceauth.KeyguardFaceAuthManagerImpl}.
+     */
+    @Provides
+    @SysUISingleton
+    @FaceAuthLog
+    public static LogBuffer provideFaceAuthLog(LogBufferFactory factory) {
+        return factory.create("KeyguardFaceAuthManagerLog", 300);
+    }
+
+    /**
      * Provides a {@link LogBuffer} for bluetooth-related logs.
      */
     @Provides
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java
deleted file mode 100644
index 67cdb72..0000000
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.log.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import com.android.systemui.plugins.log.LogBuffer;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-/**
- * A {@link LogBuffer} for status bar connectivity events.
- */
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface StatusBarConnectivityLog {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
index 146633d..95f1419 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
@@ -121,6 +121,6 @@
     @Provides
     @Named(PLUGIN_PRIVILEGED)
     static List<String> providesPrivilegedPlugins(Context context) {
-        return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginWhitelist));
+        return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginAllowlist));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
index bfba6df..bb637dc 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
@@ -32,74 +32,62 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.util.concurrency.DelayableExecutor
 import java.io.File
+import java.io.FilenameFilter
 import javax.inject.Inject
 
 /**
- * Implementation for retrieving file paths for file storage of system and secondary users. Files
- * lie in {File Directory}/UserFileManager/{User Id} for secondary user. For system user, we use the
- * conventional {File Directory}
+ * Implementation for retrieving file paths for file storage of system and secondary users. For
+ * non-system users, files will be prepended by a special prefix containing the user id.
  */
 @SysUISingleton
 class UserFileManagerImpl
 @Inject
 constructor(
-    // Context of system process and system user.
     private val context: Context,
     val userManager: UserManager,
     val broadcastDispatcher: BroadcastDispatcher,
     @Background val backgroundExecutor: DelayableExecutor
 ) : UserFileManager, CoreStartable {
     companion object {
-        private const val FILES = "files"
+        private const val PREFIX = "__USER_"
+        private const val TAG = "UserFileManagerImpl"
+        const val ROOT_DIR = "UserFileManager"
+        const val FILES = "files"
         const val SHARED_PREFS = "shared_prefs"
-        @VisibleForTesting internal const val ID = "UserFileManager"
-
-        /** Returns `true` if the given user ID is that for the primary/system user. */
-        fun isPrimaryUser(userId: Int): Boolean {
-            return UserHandle(userId).isSystem
-        }
 
         /**
-         * Returns a [File] pointing to the correct path for a secondary user ID.
-         *
-         * Note that there is no check for the type of user. This should only be called for
-         * secondary users, never for the system user. For that, make sure to call [isPrimaryUser].
-         *
-         * Note also that there is no guarantee that the parent directory structure for the file
-         * exists on disk. For that, call [ensureParentDirExists].
-         *
-         * @param context The context
-         * @param fileName The name of the file
-         * @param directoryName The name of the directory that would contain the file
-         * @param userId The ID of the user to build a file path for
+         * Returns a File object with a relative path, built from the userId for non-system users
          */
-        fun secondaryUserFile(
-            context: Context,
-            fileName: String,
-            directoryName: String,
-            userId: Int,
-        ): File {
-            return Environment.buildPath(
-                context.filesDir,
-                ID,
-                userId.toString(),
-                directoryName,
-                fileName,
-            )
-        }
-
-        /**
-         * Checks to see if parent dir of the file exists. If it does not, we create the parent dirs
-         * recursively.
-         */
-        fun ensureParentDirExists(file: File) {
-            val parent = file.parentFile
-            if (!parent.exists()) {
-                if (!parent.mkdirs()) {
-                    Log.e(ID, "Could not create parent directory for file: ${file.absolutePath}")
-                }
+        fun createFile(fileName: String, userId: Int): File {
+            return if (isSystemUser(userId)) {
+                File(fileName)
+            } else {
+                File(getFilePrefix(userId) + fileName)
             }
         }
+
+        fun createLegacyFile(context: Context, dir: String, fileName: String, userId: Int): File? {
+            return if (isSystemUser(userId)) {
+                null
+            } else {
+                return Environment.buildPath(
+                    context.filesDir,
+                    ROOT_DIR,
+                    userId.toString(),
+                    dir,
+                    fileName
+                )
+            }
+        }
+
+        fun getFilePrefix(userId: Int): String {
+            return PREFIX + userId.toString() + "_"
+        }
+
+        /** Returns `true` if the given user ID is that for the system user. */
+        private fun isSystemUser(userId: Int): Boolean {
+            return UserHandle(userId).isSystem
+        }
     }
 
     private val broadcastReceiver =
@@ -119,64 +107,87 @@
         broadcastDispatcher.registerReceiver(broadcastReceiver, filter, backgroundExecutor)
     }
 
-    /** Return the file based on current user. */
+    /**
+     * Return the file based on current user. Files for all users will exist in [context.filesDir],
+     * but non system user files will be prepended with [getFilePrefix].
+     */
     override fun getFile(fileName: String, userId: Int): File {
-        return if (isPrimaryUser(userId)) {
-            Environment.buildPath(context.filesDir, fileName)
-        } else {
-            val secondaryFile =
-                secondaryUserFile(
-                    context = context,
-                    userId = userId,
-                    directoryName = FILES,
-                    fileName = fileName,
-                )
-            ensureParentDirExists(secondaryFile)
-            secondaryFile
-        }
+        val file = File(context.filesDir, createFile(fileName, userId).path)
+        createLegacyFile(context, FILES, fileName, userId)?.run { migrate(file, this) }
+        return file
     }
 
-    /** Get shared preferences from user. */
+    /**
+     * Get shared preferences from user. Files for all users will exist in the shared_prefs dir, but
+     * non system user files will be prepended with [getFilePrefix].
+     */
     override fun getSharedPreferences(
         fileName: String,
         @Context.PreferencesMode mode: Int,
         userId: Int
     ): SharedPreferences {
-        if (isPrimaryUser(userId)) {
-            return context.getSharedPreferences(fileName, mode)
+        val file = createFile(fileName, userId)
+        createLegacyFile(context, SHARED_PREFS, "$fileName.xml", userId)?.run {
+            val path = Environment.buildPath(context.dataDir, SHARED_PREFS, "${file.path}.xml")
+            migrate(path, this)
         }
-
-        val secondaryUserDir =
-            secondaryUserFile(
-                context = context,
-                fileName = fileName,
-                directoryName = SHARED_PREFS,
-                userId = userId,
-            )
-
-        ensureParentDirExists(secondaryUserDir)
-        return context.getSharedPreferences(secondaryUserDir, mode)
+        return context.getSharedPreferences(file.path, mode)
     }
 
-    /** Remove dirs for deleted users. */
+    /** Remove files for deleted users. */
     @VisibleForTesting
     internal fun clearDeletedUserData() {
         backgroundExecutor.execute {
-            val file = Environment.buildPath(context.filesDir, ID)
-            if (!file.exists()) return@execute
-            val aliveUsers = userManager.aliveUsers.map { it.id.toString() }
-            val dirsToDelete = file.list().filter { !aliveUsers.contains(it) }
+            deleteFiles(context.filesDir)
+            deleteFiles(File(context.dataDir, SHARED_PREFS))
+        }
+    }
 
-            dirsToDelete.forEach { dir ->
+    private fun migrate(dest: File, source: File) {
+        if (source.exists()) {
+            try {
+                val parent = source.getParentFile()
+                source.renameTo(dest)
+
+                deleteParentDirsIfEmpty(parent)
+            } catch (e: Exception) {
+                Log.e(TAG, "Failed to rename and delete ${source.path}", e)
+            }
+        }
+    }
+
+    private fun deleteParentDirsIfEmpty(dir: File?) {
+        if (dir != null && dir.listFiles().size == 0) {
+            val priorParent = dir.parentFile
+            val isRoot = dir.name == ROOT_DIR
+            dir.delete()
+
+            if (!isRoot) {
+                deleteParentDirsIfEmpty(priorParent)
+            }
+        }
+    }
+
+    private fun deleteFiles(parent: File) {
+        val aliveUserFilePrefix = userManager.aliveUsers.map { getFilePrefix(it.id) }
+        val filesToDelete =
+            parent.listFiles(
+                FilenameFilter { _, name ->
+                    name.startsWith(PREFIX) &&
+                        aliveUserFilePrefix.filter { name.startsWith(it) }.isEmpty()
+                }
+            )
+
+        // This can happen in test environments
+        if (filesToDelete == null) {
+            Log.i(TAG, "Empty directory: ${parent.path}")
+        } else {
+            filesToDelete.forEach { file ->
+                Log.i(TAG, "Deleting file: ${file.path}")
                 try {
-                    val dirToDelete =
-                        Environment.buildPath(
-                            file,
-                            dir,
-                        )
-                    dirToDelete.deleteRecursively()
+                    file.delete()
                 } catch (e: Exception) {
-                    Log.e(ID, "Deletion failed.", e)
+                    Log.e(TAG, "Deletion failed.", e)
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index a72b7f1..1e4f5bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -49,6 +49,7 @@
     }
 
     protected int mMinimumDisplayTime;
+    protected int mStickyDisplayTime;
     protected int mAutoDismissNotificationDecay;
     @VisibleForTesting
     public Handler mHandler;
@@ -198,7 +199,7 @@
         if (entry != null && entry.isExpandAnimationRunning()) {
             return;
         }
-
+        entry.demoteStickyHun();
         mAlertEntries.remove(key);
         onAlertEntryRemoved(alertEntry);
         entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
@@ -255,6 +256,15 @@
         return 0;
     }
 
+    @VisibleForTesting
+    public long getCalculatedEarliestRemovalTime(String key) {
+        AlertEntry alerting = mAlertEntries.get(key);
+        if (alerting != null) {
+            return alerting.mEarliestRemovaltime;
+        }
+        return 0;
+    }
+
     protected class AlertEntry implements Comparable<AlertEntry> {
         @Nullable public NotificationEntry mEntry;
         public long mPostTime;
@@ -275,6 +285,11 @@
             updateEntry(true /* updatePostTime */);
         }
 
+        @VisibleForTesting
+        long getEarliestRemovaltime() {
+            return mEarliestRemovaltime;
+        }
+
         /**
          * Updates an entry's removal time.
          * @param updatePostTime whether or not to refresh the post time
@@ -282,18 +297,22 @@
         public void updateEntry(boolean updatePostTime) {
             mLogger.logUpdateEntry(mEntry, updatePostTime);
 
-            long currentTime = mClock.currentTimeMillis();
-            mEarliestRemovaltime = currentTime + mMinimumDisplayTime;
+            final long now = mClock.currentTimeMillis();
+            mEarliestRemovaltime = isSticky()
+                    ? mEntry.mCreationElapsedRealTime + mStickyDisplayTime
+                    : now + mMinimumDisplayTime;
+
             if (updatePostTime) {
-                mPostTime = Math.max(mPostTime, currentTime);
+                mPostTime = Math.max(mPostTime, now);
             }
             removeAutoRemovalCallbacks();
 
-            if (!isSticky()) {
-                long finishTime = calculateFinishTime();
-                long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime);
-                mHandler.postDelayed(mRemoveAlertRunnable, removeDelay);
-            }
+            final long finishTime = calculateFinishTime();
+            final long timeRemaining = isSticky()
+                    ? finishTime - mClock.currentTimeMillis()
+                    : Math.max(finishTime - now, mMinimumDisplayTime);
+
+            mHandler.postDelayed(mRemoveAlertRunnable, timeRemaining);
         }
 
         /**
@@ -302,11 +321,13 @@
          * @return true if the notification is sticky
          */
         public boolean isSticky() {
-            return false;
+            // This implementation is overridden by HeadsUpManager HeadsUpEntry #isSticky
+            // but we keep this here for use by unit tests.
+            return mEntry.isStickyAndNotDemoted();
         }
 
         /**
-         * Whether the notification has been on screen long enough and can be removed.
+         * Whether the notification has befen on screen long enough and can be removed.
          * @return true if the notification has been on screen long enough
          */
         public boolean wasShownLongEnough() {
@@ -355,11 +376,12 @@
         }
 
         /**
-         * Calculate when the notification should auto-dismiss itself.
-         * @return the finish time
+         * @return When the notification should auto-dismiss itself, based on
+         * {@link SystemClock#elapsedRealTime()}
          */
         protected long calculateFinishTime() {
-            return mPostTime + mAutoDismissNotificationDecay;
+            // Overridden by HeadsUpManager HeadsUpEntry #calculateFinishTime
+            return 0;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f565f3d..afa60fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -262,7 +262,6 @@
 
     fun setStackScroller(nsslController: NotificationStackScrollLayoutController) {
         this.nsslController = nsslController
-        touchHelper.host = nsslController.view
         touchHelper.expandCallback = nsslController.expandHelperCallback
     }
 
@@ -736,14 +735,12 @@
 
     private var dragDownAmountOnStart = 0.0f
     lateinit var expandCallback: ExpandHelper.Callback
-    lateinit var host: View
 
     private var minDragDistance = 0
     private var initialTouchX = 0f
     private var initialTouchY = 0f
     private var touchSlop = 0f
     private var slopMultiplier = 0f
-    private val temp2 = IntArray(2)
     private var draggedFarEnough = false
     private var startingChild: ExpandableView? = null
     private var lastHeight = 0f
@@ -923,7 +920,6 @@
     }
 
     private fun findView(x: Float, y: Float): ExpandableView? {
-        host.getLocationOnScreen(temp2)
-        return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1])
+        return expandCallback.getChildAtRawPosition(x, y)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index e34096e..4e9e88d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -181,6 +181,44 @@
     private boolean mBlockable;
 
     /**
+     * The {@link SystemClock#elapsedRealtime()} when this notification entry was created.
+     */
+    public long mCreationElapsedRealTime;
+
+    /**
+     * Whether this notification has ever been a non-sticky HUN.
+     */
+    private boolean mIsDemoted = false;
+
+    /**
+     * True if both
+     *  1) app provided full screen intent but does not have the permission to send it
+     *  2) this notification has never been demoted before
+     */
+    public boolean isStickyAndNotDemoted() {
+
+        final boolean fsiRequestedButDenied =  (getSbn().getNotification().flags
+                & Notification.FLAG_FSI_REQUESTED_BUT_DENIED) != 0;
+
+        if (!fsiRequestedButDenied && !mIsDemoted) {
+            demoteStickyHun();
+        }
+        return fsiRequestedButDenied && !mIsDemoted;
+    }
+
+    @VisibleForTesting
+    public boolean isDemoted() {
+        return mIsDemoted;
+    }
+
+    /**
+     * Make sticky HUN not sticky.
+     */
+    public void demoteStickyHun() {
+        mIsDemoted = true;
+    }
+
+    /**
      * @param sbn the StatusBarNotification from system server
      * @param ranking also from system server
      * @param creationTime SystemClock.uptimeMillis of when we were created
@@ -197,8 +235,13 @@
         mKey = sbn.getKey();
         setSbn(sbn);
         setRanking(ranking);
+        mCreationElapsedRealTime = SystemClock.elapsedRealtime();
     }
 
+    @VisibleForTesting
+    public void setCreationElapsedRealTime(long time) {
+        mCreationElapsedRealTime = time;
+    }
     @Override
     public NotificationEntry getRepresentativeEntry() {
         return this;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index bc881ce..ae19feb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -33,6 +33,10 @@
         /**
          * Full screen intents are disabled.
          */
+        NO_FSI_SHOW_STICKY_HUN(false),
+        /**
+         * Full screen intents are disabled.
+         */
         NO_FSI_DISABLED(false),
         /**
          * No full screen intent included, so there is nothing to show.
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 afeb72f..0163dbe 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
@@ -29,6 +29,7 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.provider.Settings;
 import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
@@ -246,7 +247,11 @@
         if (mFlags.disableFsi()) {
             return FullScreenIntentDecision.NO_FSI_DISABLED;
         }
+
         if (entry.getSbn().getNotification().fullScreenIntent == null) {
+            if (entry.isStickyAndNotDemoted()) {
+                return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN;
+            }
             return FullScreenIntentDecision.NO_FULL_SCREEN_INTENT;
         }
 
@@ -335,6 +340,9 @@
         final int uid = entry.getSbn().getUid();
         final String packageName = entry.getSbn().getPackageName();
         switch (decision) {
+            case NO_FSI_SHOW_STICKY_HUN:
+                mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN");
+                return;
             case NO_FSI_DISABLED:
                 mLogger.logNoFullscreen(entry, "Disabled");
                 return;
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 79e9ff2a..7c6efe4 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
@@ -1198,6 +1198,22 @@
         return getShowingLayout().getVisibleWrapper();
     }
 
+    /**
+     * @return whether the notification row is long clickable or not.
+     */
+    public boolean isNotificationRowLongClickable() {
+        if (mLongPressListener == null) {
+            return false;
+        }
+
+        if (!areGutsExposed()) { // guts is not opened
+            return true;
+        }
+
+        // if it is leave behind, it shouldn't be long clickable.
+        return !isGutsLeaveBehind();
+    }
+
     public void setLongPressListener(LongPressListener longPressListener) {
         mLongPressListener = longPressListener;
     }
@@ -2954,6 +2970,10 @@
         return (mGuts != null && mGuts.isExposed());
     }
 
+    private boolean isGutsLeaveBehind() {
+        return (mGuts != null && mGuts.isLeavebehind());
+    }
+
     @Override
     public boolean isContentExpandable() {
         if (mIsSummaryWithChildren && !shouldShowPublic()) {
@@ -3401,7 +3421,12 @@
     @Override
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
-        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+        final boolean isLongClickable = isNotificationRowLongClickable();
+        if (isLongClickable) {
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+        }
+        info.setLongClickable(isLongClickable);
+
         if (canViewBeDismissed() && !mIsSnoozed) {
             info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 37ff11d..06d4080 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -586,7 +586,9 @@
         }
 
         final ExpandableNotificationRow row = (ExpandableNotificationRow) view;
-        view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        if (row.isNotificationRowLongClickable()) {
+            view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        }
         if (row.areGutsExposed()) {
             closeAndSaveGuts(false /* removeLeavebehind */, false /* force */,
                     true /* removeControls */, -1 /* x */, -1 /* y */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 51125b1..46bc887 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -870,7 +870,8 @@
         }
 
         for (int i = childCount - 1; i >= 0; i--) {
-            updateChildZValue(i, algorithmState, ambientState, i == topHunIndex);
+            childrenOnTop = updateChildZValue(i, childrenOnTop,
+                    algorithmState, ambientState, i == topHunIndex);
         }
     }
 
@@ -880,11 +881,15 @@
      *
      * @param isTopHun      Whether the child is a top HUN. A top HUN means a HUN that shows on the
      *                      vertically top of screen. Top HUNs should have drop shadows
+     * @param childrenOnTop It is greater than 0 when there's an existing HUN that is elevated
+     * @return childrenOnTop The decimal part represents the fraction of the elevated HUN's height
+     *                      that overlaps with QQS Panel. The integer part represents the count of
+     *                      previous HUNs whose Z positions are greater than 0.
      */
-    protected void updateChildZValue(int i,
-                                     StackScrollAlgorithmState algorithmState,
-                                     AmbientState ambientState,
-                                     boolean isTopHun) {
+    protected float updateChildZValue(int i, float childrenOnTop,
+                                      StackScrollAlgorithmState algorithmState,
+                                      AmbientState ambientState,
+                                      boolean isTopHun) {
         ExpandableView child = algorithmState.visibleChildren.get(i);
         ExpandableViewState childViewState = child.getViewState();
         float baseZ = ambientState.getBaseZHeight();
@@ -898,16 +903,22 @@
             // Handles HUN shadow when Shade is opened, and AmbientState.mScrollY > 0
             // Calculate the HUN's z-value based on its overlapping fraction with QQS Panel.
             // When scrolling down shade to make HUN back to in-position in Notification Panel,
-            // the overlapFraction goes to 0, and the pinned HUN's shadows hides gradually.
-            float overlap = ambientState.getTopPadding()
-                    + ambientState.getStackTranslation() - childViewState.getYTranslation();
-
-            if (childViewState.height > 0) { // To avoid 0/0 problems
-                // To prevent over-shadow
-                float overlapFraction = MathUtils.saturate(overlap / childViewState.height);
-                childViewState.setZTranslation(baseZ
-                        + overlapFraction * mPinnedZTranslationExtra);
+            // The over-lapping fraction goes to 0, and shadows hides gradually.
+            if (childrenOnTop != 0.0f) {
+                // To elevate the later HUN over previous HUN
+                childrenOnTop++;
+            } else {
+                float overlap = ambientState.getTopPadding()
+                        + ambientState.getStackTranslation() - childViewState.getYTranslation();
+                // To prevent over-shadow during HUN entry
+                childrenOnTop += Math.min(
+                        1.0f,
+                        overlap / childViewState.height
+                );
+                MathUtils.saturate(childrenOnTop);
             }
+            childViewState.setZTranslation(baseZ
+                    + childrenOnTop * mPinnedZTranslationExtra);
         } else if (isTopHun) {
             // In case this is a new view that has never been measured before, we don't want to
             // elevate if we are currently expanded more than the notification
@@ -935,14 +946,15 @@
         }
 
         // Handles HUN shadow when shade is closed.
-        // While shade is closed, and during HUN's entry: headerVisibleAmount stays 0, shadow stays.
-        // While shade is closed, and HUN is showing: headerVisibleAmount stays 0, shadow stays.
+        // While HUN is showing and Shade is closed: headerVisibleAmount stays 0, shadow stays.
         // During HUN-to-Shade (eg. dragging down HUN to open Shade): headerVisibleAmount goes
         // gradually from 0 to 1, shadow hides gradually.
         // Header visibility is a deprecated concept, we are using headerVisibleAmount only because
         // this value nicely goes from 0 to 1 during the HUN-to-Shade process.
+
         childViewState.setZTranslation(childViewState.getZTranslation()
                 + (1.0f - child.getHeaderVisibleAmount()) * mPinnedZTranslationExtra);
+        return childrenOnTop;
     }
 
     public void setIsExpanded(boolean isExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 078a00d..3471a46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -27,6 +27,7 @@
 import android.app.TaskStackBuilder;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
@@ -45,6 +46,7 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ActivityIntentHelper;
 import com.android.systemui.EventLogTags;
@@ -74,12 +76,14 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.wmshell.BubblesManager;
 
+import dagger.Lazy;
+
+import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
 
 /**
  * Status bar implementation of {@link NotificationActivityStarter}.
@@ -572,16 +576,29 @@
         });
 
         // not immersive & a fullscreen alert should be shown
-        final PendingIntent fullscreenIntent =
+        final PendingIntent fullScreenIntent =
                 entry.getSbn().getNotification().fullScreenIntent;
-        mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
+        mLogger.logSendingFullScreenIntent(entry, fullScreenIntent);
         try {
             EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                     entry.getKey());
             mCentralSurfaces.wakeUpForFullScreenIntent();
-            fullscreenIntent.send();
+            fullScreenIntent.send();
             entry.notifyFullScreenIntentLaunched();
             mMetricsLogger.count("note_fullscreen", 1);
+
+            String activityName;
+            List<ResolveInfo> resolveInfos = fullScreenIntent.queryIntentComponents(0);
+            if (resolveInfos.size() > 0 && resolveInfos.get(0) != null
+                    && resolveInfos.get(0).activityInfo != null
+                    && resolveInfos.get(0).activityInfo.name != null) {
+                activityName = resolveInfos.get(0).activityInfo.name;
+            } else {
+                activityName = "";
+            }
+            FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
+                    fullScreenIntent.getCreatorUid(),
+                    activityName);
         } catch (PendingIntent.CanceledException e) {
             // ignore
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
index 4a5342e..5d5d562 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
@@ -18,9 +18,10 @@
 
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
+import com.android.systemui.statusbar.pipeline.dagger.AirplaneTableLog
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
@@ -46,7 +47,7 @@
 @Inject
 constructor(
     interactor: AirplaneModeInteractor,
-    logger: ConnectivityPipelineLogger,
+    @AirplaneTableLog logger: TableLogBuffer,
     @Application private val scope: CoroutineScope,
 ) : AirplaneModeViewModel {
     override val isAirplaneModeIconVisible: StateFlow<Boolean> =
@@ -56,6 +57,11 @@
                 isAirplaneMode && !isAirplaneIconForceHidden
             }
             .distinctUntilChanged()
-            .logOutputChange(logger, "isAirplaneModeIconVisible")
+            .logDiffsForTable(
+                logger,
+                columnPrefix = "",
+                columnName = "isAirplaneModeIconVisible",
+                initialValue = false,
+            )
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
 }
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileInputLog.kt
similarity index 65%
copy from telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileInputLog.kt
index 2a498f0..d1aa79e 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/MobileInputLog.kt
@@ -14,14 +14,12 @@
  * limitations under the License.
  */
 
-package android.telephony.satellite.stub;
+package com.android.systemui.statusbar.pipeline.dagger
 
-import android.telephony.satellite.stub.SatelliteModemState;
+import javax.inject.Qualifier
 
-/**
- * Consumer pattern for a request that receives a SatelliteModemState from the SatelliteService.
- * @hide
- */
-oneway interface ISatelliteModemStateConsumer {
-    void accept(in SatelliteModemState result);
-}
+/** Logs for inputs into the mobile pipeline. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class MobileInputLog
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt
similarity index 65%
rename from telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
rename to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt
index 2a498f0..5face22 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/SharedConnectivityInputLog.kt
@@ -14,14 +14,12 @@
  * limitations under the License.
  */
 
-package android.telephony.satellite.stub;
+package com.android.systemui.statusbar.pipeline.dagger
 
-import android.telephony.satellite.stub.SatelliteModemState;
+import javax.inject.Qualifier
 
-/**
- * Consumer pattern for a request that receives a SatelliteModemState from the SatelliteService.
- * @hide
- */
-oneway interface ISatelliteModemStateConsumer {
-    void accept(in SatelliteModemState result);
-}
+/** Logs for connectivity-related inputs that are shared across wifi, mobile, etc. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class SharedConnectivityInputLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 60de1a3..4464751 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -19,8 +19,10 @@
 import android.net.wifi.WifiManager
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBufferFactory
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
@@ -107,6 +109,13 @@
 
         @Provides
         @SysUISingleton
+        @WifiInputLog
+        fun provideWifiInputLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("WifiInputLog", 50)
+        }
+
+        @Provides
+        @SysUISingleton
         @WifiTableLog
         fun provideWifiTableLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
             return factory.create("WifiTableLog", 100)
@@ -121,9 +130,23 @@
 
         @Provides
         @SysUISingleton
+        @SharedConnectivityInputLog
+        fun provideSharedConnectivityTableLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("SharedConnectivityInputLog", 30)
+        }
+
+        @Provides
+        @SysUISingleton
         @MobileSummaryLog
         fun provideMobileSummaryLogBuffer(factory: TableLogBufferFactory): TableLogBuffer {
             return factory.create("MobileSummaryLog", 100)
         }
+
+        @Provides
+        @SysUISingleton
+        @MobileInputLog
+        fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer {
+            return factory.create("MobileInputLog", 100)
+        }
     }
 }
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
similarity index 65%
copy from telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
index 2a498f0..6db69447 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteModemStateConsumer.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/WifiInputLog.kt
@@ -14,14 +14,12 @@
  * limitations under the License.
  */
 
-package android.telephony.satellite.stub;
+package com.android.systemui.statusbar.pipeline.dagger
 
-import android.telephony.satellite.stub.SatelliteModemState;
+import javax.inject.Qualifier
 
-/**
- * Consumer pattern for a request that receives a SatelliteModemState from the SatelliteService.
- * @hide
- */
-oneway interface ISatelliteModemStateConsumer {
-    void accept(in SatelliteModemState result);
-}
+/** Wifi logs for inputs into the wifi pipeline. */
+@Qualifier
+@MustBeDocumented
+@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
+annotation class WifiInputLog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
index 5769f90..bb3b9b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -57,7 +57,7 @@
     broadcastDispatcher: BroadcastDispatcher,
     private val carrierConfigManager: CarrierConfigManager,
     dumpManager: DumpManager,
-    logger: ConnectivityPipelineLogger,
+    logger: MobileInputLogger,
     @Application scope: CoroutineScope,
 ) : Dumpable {
     private var isListening = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index dcce0ea..96b96f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -47,8 +47,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -85,7 +85,7 @@
     broadcastDispatcher: BroadcastDispatcher,
     private val mobileMappingsProxy: MobileMappingsProxy,
     bgDispatcher: CoroutineDispatcher,
-    logger: ConnectivityPipelineLogger,
+    logger: MobileInputLogger,
     override val tableLogBuffer: TableLogBuffer,
     scope: CoroutineScope,
 ) : MobileConnectionRepository {
@@ -291,7 +291,7 @@
         private val broadcastDispatcher: BroadcastDispatcher,
         private val context: Context,
         private val telephonyManager: TelephonyManager,
-        private val logger: ConnectivityPipelineLogger,
+        private val logger: MobileInputLogger,
         private val carrierConfigRepository: CarrierConfigRepository,
         private val mobileMappingsProxy: MobileMappingsProxy,
         @Background private val bgDispatcher: CoroutineDispatcher,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index 73ce5e6..b3d5b1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -49,9 +49,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.util.kotlin.pairwise
@@ -84,7 +83,7 @@
     private val connectivityManager: ConnectivityManager,
     private val subscriptionManager: SubscriptionManager,
     private val telephonyManager: TelephonyManager,
-    private val logger: ConnectivityPipelineLogger,
+    private val logger: MobileInputLogger,
     @MobileSummaryLog private val tableLogger: TableLogBuffer,
     mobileMappingsProxy: MobileMappingsProxy,
     broadcastDispatcher: BroadcastDispatcher,
@@ -222,13 +221,13 @@
     private val carrierConfigChangedEvent =
         broadcastDispatcher
             .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED))
-            .logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED")
+            .onEach { logger.logActionCarrierConfigChanged() }
 
     override val defaultDataSubRatConfig: StateFlow<Config> =
         merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
             .mapLatest { Config.readConfig(context) }
             .distinctUntilChanged()
-            .logInputChange(logger, "defaultDataSubRatConfig")
+            .onEach { logger.logDefaultDataSubRatConfig(it) }
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
@@ -239,13 +238,13 @@
         defaultDataSubRatConfig
             .map { mobileMappingsProxy.mapIconSets(it) }
             .distinctUntilChanged()
-            .logInputChange(logger, "defaultMobileIconMapping")
+            .onEach { logger.logDefaultMobileIconMapping(it) }
 
     override val defaultMobileIconGroup: Flow<MobileIconGroup> =
         defaultDataSubRatConfig
             .map { mobileMappingsProxy.getDefaultIcons(it) }
             .distinctUntilChanged()
-            .logInputChange(logger, "defaultMobileIconGroup")
+            .onEach { logger.logDefaultMobileIconGroup(it) }
 
     override fun getRepoForSubId(subId: Int): FullMobileConnectionRepository {
         if (!isValidSubId(subId)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index 5a2e11e..142c372 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
 import com.android.systemui.util.CarrierConfigTracker
@@ -111,7 +110,6 @@
 constructor(
     private val mobileConnectionsRepo: MobileConnectionsRepository,
     private val carrierConfigTracker: CarrierConfigTracker,
-    private val logger: ConnectivityPipelineLogger,
     @MobileSummaryLog private val tableLogger: TableLogBuffer,
     connectivityRepository: ConnectivityRepository,
     userSetupRepo: UserSetupRepository,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt
new file mode 100644
index 0000000..3cbd2b7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLogger.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.shared
+
+import android.net.Network
+import android.net.NetworkCapabilities
+import android.telephony.ServiceState
+import android.telephony.SignalStrength
+import android.telephony.TelephonyDisplayInfo
+import com.android.settingslib.SignalIcon
+import com.android.settingslib.mobile.MobileMappings
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.MobileInputLog
+import com.android.systemui.statusbar.pipeline.shared.LoggerHelper
+import javax.inject.Inject
+
+/** Logs for inputs into the mobile pipeline. */
+@SysUISingleton
+class MobileInputLogger
+@Inject
+constructor(
+    @MobileInputLog private val buffer: LogBuffer,
+) {
+    fun logOnCapabilitiesChanged(
+        network: Network,
+        networkCapabilities: NetworkCapabilities,
+        isDefaultNetworkCallback: Boolean,
+    ) {
+        LoggerHelper.logOnCapabilitiesChanged(
+            buffer,
+            TAG,
+            network,
+            networkCapabilities,
+            isDefaultNetworkCallback,
+        )
+    }
+
+    fun logOnLost(network: Network) {
+        LoggerHelper.logOnLost(buffer, TAG, network)
+    }
+
+    fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                bool1 = serviceState.isEmergencyOnly
+                bool2 = serviceState.roaming
+                str1 = serviceState.operatorAlphaShort
+            },
+            {
+                "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
+                    " operator=$str1"
+            }
+        )
+    }
+
+    fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                str1 = signalStrength.toString()
+            },
+            { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" }
+        )
+    }
+
+    fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                int2 = dataState
+                str1 = networkType.toString()
+            },
+            { "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" },
+        )
+    }
+
+    fun logOnDataActivity(direction: Int, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                int2 = direction
+            },
+            { "onDataActivity: subId=$int1 direction=$int2" },
+        )
+    }
+
+    fun logOnCarrierNetworkChange(active: Boolean, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                bool1 = active
+            },
+            { "onCarrierNetworkChange: subId=$int1 active=$bool1" },
+        )
+    }
+
+    fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                str1 = displayInfo.toString()
+            },
+            { "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" },
+        )
+    }
+
+    fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter updated internally: $str1" },
+        )
+    }
+
+    fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = subs.toString() },
+            { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
+        )
+    }
+
+    fun logCarrierConfigChanged(subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { int1 = subId },
+            { "onCarrierConfigChanged: subId=$int1" },
+        )
+    }
+
+    fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            {
+                int1 = subId
+                bool1 = enabled
+            },
+            { "onDataEnabledChanged: subId=$int1 enabled=$bool1" },
+        )
+    }
+
+    fun logActionCarrierConfigChanged() {
+        buffer.log(TAG, LogLevel.INFO, {}, { "Intent received: ACTION_CARRIER_CONFIG_CHANGED" })
+    }
+
+    fun logDefaultDataSubRatConfig(config: MobileMappings.Config) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = config.toString() },
+            { "defaultDataSubRatConfig: $str1" }
+        )
+    }
+
+    fun logDefaultMobileIconMapping(mapping: Map<String, SignalIcon.MobileIconGroup>) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { str1 = mapping.toString() },
+            { "defaultMobileIconMapping: $str1" }
+        )
+    }
+
+    fun logDefaultMobileIconGroup(group: SignalIcon.MobileIconGroup) {
+        buffer.log(TAG, LogLevel.INFO, { str1 = group.name }, { "defaultMobileIconGroup: $str1" })
+    }
+}
+
+private const val TAG = "MobileInputLog"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
index ef75713..da63ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
@@ -22,8 +22,8 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -55,7 +55,7 @@
     interactor: MobileIconsInteractor,
     private val iconController: StatusBarIconController,
     private val iconsViewModelFactory: MobileIconsViewModel.Factory,
-    private val logger: ConnectivityPipelineLogger,
+    private val logger: MobileInputLogger,
     @Application private val scope: CoroutineScope,
     private val statusBarPipelineFlags: StatusBarPipelineFlags,
 ) : CoreStartable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 185b668..8cb52af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.StateFlow
@@ -42,7 +41,6 @@
     val subscriptionIdsFlow: StateFlow<List<Int>>,
     private val interactor: MobileIconsInteractor,
     private val airplaneModeInteractor: AirplaneModeInteractor,
-    private val logger: ConnectivityPipelineLogger,
     private val constants: ConnectivityConstants,
     @Application private val scope: CoroutineScope,
     private val statusBarPipelineFlags: StatusBarPipelineFlags,
@@ -83,7 +81,6 @@
     constructor(
         private val interactor: MobileIconsInteractor,
         private val airplaneModeInteractor: AirplaneModeInteractor,
-        private val logger: ConnectivityPipelineLogger,
         private val constants: ConnectivityConstants,
         @Application private val scope: CoroutineScope,
         private val statusBarPipelineFlags: StatusBarPipelineFlags,
@@ -93,7 +90,6 @@
                 subscriptionIdsFlow,
                 interactor,
                 airplaneModeInteractor,
-                logger,
                 constants,
                 scope,
                 statusBarPipelineFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
index 0c9b86c..0fe5329 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
 import java.io.PrintWriter
 import javax.inject.Inject
 
@@ -40,7 +39,7 @@
     telephonyManager: TelephonyManager,
 ) : Dumpable {
     init {
-        dumpManager.registerNormalDumpable("${SB_LOGGING_TAG}Constants", this)
+        dumpManager.registerNormalDumpable("ConnectivityConstants", this)
     }
 
     /** True if this device has the capability for data connections and false otherwise. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
new file mode 100644
index 0000000..95548b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.statusbar.pipeline.shared
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.SharedConnectivityInputLog
+import javax.inject.Inject
+
+/** Logs for connectivity-related inputs that are shared across wifi, mobile, etc. */
+@SysUISingleton
+class ConnectivityInputLogger
+@Inject
+constructor(
+    @SharedConnectivityInputLog private val buffer: LogBuffer,
+) {
+    fun logTuningChanged(tuningList: String?) {
+        buffer.log(TAG, LogLevel.DEBUG, { str1 = tuningList }, { "onTuningChanged: $str1" })
+    }
+}
+
+private const val TAG = "ConnectivityInputLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
deleted file mode 100644
index 45036969..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.shared
-
-import android.net.Network
-import android.net.NetworkCapabilities
-import android.telephony.ServiceState
-import android.telephony.SignalStrength
-import android.telephony.TelephonyDisplayInfo
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.log.dagger.StatusBarConnectivityLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.onEach
-
-@SysUISingleton
-class ConnectivityPipelineLogger
-@Inject
-constructor(
-    @StatusBarConnectivityLog private val buffer: LogBuffer,
-) {
-    /**
-     * Logs a change in one of the **raw inputs** to the connectivity pipeline.
-     *
-     * Use this method for inputs that don't have any extra information besides their callback name.
-     */
-    fun logInputChange(callbackName: String) {
-        buffer.log(SB_LOGGING_TAG, LogLevel.INFO, { str1 = callbackName }, { "Input: $str1" })
-    }
-
-    /** Logs a change in one of the **raw inputs** to the connectivity pipeline. */
-    fun logInputChange(callbackName: String, changeInfo: String?) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                str1 = callbackName
-                str2 = changeInfo
-            },
-            { "Input: $str1: $str2" }
-        )
-    }
-
-    /** Logs a **data transformation** that we performed within the connectivity pipeline. */
-    fun logTransformation(transformationName: String, oldValue: Any?, newValue: Any?) {
-        if (oldValue == newValue) {
-            buffer.log(
-                SB_LOGGING_TAG,
-                LogLevel.INFO,
-                {
-                    str1 = transformationName
-                    str2 = oldValue.toString()
-                },
-                { "Transform: $str1: $str2 (transformation didn't change it)" }
-            )
-        } else {
-            buffer.log(
-                SB_LOGGING_TAG,
-                LogLevel.INFO,
-                {
-                    str1 = transformationName
-                    str2 = oldValue.toString()
-                    str3 = newValue.toString()
-                },
-                { "Transform: $str1: $str2 -> $str3" }
-            )
-        }
-    }
-
-    /** Logs a change in one of the **outputs** to the connectivity pipeline. */
-    fun logOutputChange(outputParamName: String, changeInfo: String) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                str1 = outputParamName
-                str2 = changeInfo
-            },
-            { "Output: $str1: $str2" }
-        )
-    }
-
-    fun logOnCapabilitiesChanged(
-        network: Network,
-        networkCapabilities: NetworkCapabilities,
-        isDefaultNetworkCallback: Boolean,
-    ) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                bool1 = isDefaultNetworkCallback
-                int1 = network.getNetId()
-                str1 = networkCapabilities.toString()
-            },
-            { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" }
-        )
-    }
-
-    fun logOnLost(network: Network) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            { int1 = network.getNetId() },
-            { "onLost: net=$int1" }
-        )
-    }
-
-    fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                bool1 = serviceState.isEmergencyOnly
-                bool2 = serviceState.roaming
-                str1 = serviceState.operatorAlphaShort
-            },
-            {
-                "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
-                    " operator=$str1"
-            }
-        )
-    }
-
-    fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                str1 = signalStrength.toString()
-            },
-            { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" }
-        )
-    }
-
-    fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                int2 = dataState
-                str1 = networkType.toString()
-            },
-            { "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" },
-        )
-    }
-
-    fun logOnDataActivity(direction: Int, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                int2 = direction
-            },
-            { "onDataActivity: subId=$int1 direction=$int2" },
-        )
-    }
-
-    fun logOnCarrierNetworkChange(active: Boolean, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                bool1 = active
-            },
-            { "onCarrierNetworkChange: subId=$int1 active=$bool1" },
-        )
-    }
-
-    fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                str1 = displayInfo.toString()
-            },
-            { "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" },
-        )
-    }
-
-    // TODO(b/238425913): We should split this class into mobile-specific and wifi-specific loggers.
-
-    fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            { str1 = subs.toString() },
-            { "Sub IDs in MobileUiAdapter updated internally: $str1" },
-        )
-    }
-
-    fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            { str1 = subs.toString() },
-            { "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
-        )
-    }
-
-    fun logCarrierConfigChanged(subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            { int1 = subId },
-            { "onCarrierConfigChanged: subId=$int1" },
-        )
-    }
-
-    fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) {
-        buffer.log(
-            SB_LOGGING_TAG,
-            LogLevel.INFO,
-            {
-                int1 = subId
-                bool1 = enabled
-            },
-            { "onDataEnabledChanged: subId=$int1 enabled=$bool1" },
-        )
-    }
-
-    companion object {
-        const val SB_LOGGING_TAG = "SbConnectivity"
-
-        /** Log a change in one of the **inputs** to the connectivity pipeline. */
-        fun Flow<Unit>.logInputChange(
-            logger: ConnectivityPipelineLogger,
-            inputParamName: String,
-        ): Flow<Unit> {
-            return this.onEach { logger.logInputChange(inputParamName) }
-        }
-
-        /**
-         * Log a change in one of the **inputs** to the connectivity pipeline.
-         *
-         * @param prettyPrint an optional function to transform the value into a readable string.
-         * [toString] is used if no custom function is provided.
-         */
-        fun <T> Flow<T>.logInputChange(
-            logger: ConnectivityPipelineLogger,
-            inputParamName: String,
-            prettyPrint: (T) -> String = { it.toString() }
-        ): Flow<T> {
-            return this.onEach { logger.logInputChange(inputParamName, prettyPrint(it)) }
-        }
-
-        /**
-         * Log a change in one of the **outputs** to the connectivity pipeline.
-         *
-         * @param prettyPrint an optional function to transform the value into a readable string.
-         * [toString] is used if no custom function is provided.
-         */
-        fun <T> Flow<T>.logOutputChange(
-            logger: ConnectivityPipelineLogger,
-            outputParamName: String,
-            prettyPrint: (T) -> String = { it.toString() }
-        ): Flow<T> {
-            return this.onEach { logger.logOutputChange(outputParamName, prettyPrint(it)) }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
new file mode 100644
index 0000000..6f29e33
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.statusbar.pipeline.shared
+
+import android.net.Network
+import android.net.NetworkCapabilities
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+
+/** Helper object for logs that are shared between wifi and mobile. */
+object LoggerHelper {
+    fun logOnCapabilitiesChanged(
+        buffer: LogBuffer,
+        tag: String,
+        network: Network,
+        networkCapabilities: NetworkCapabilities,
+        isDefaultNetworkCallback: Boolean,
+    ) {
+        buffer.log(
+            tag,
+            LogLevel.INFO,
+            {
+                bool1 = isDefaultNetworkCallback
+                int1 = network.getNetId()
+                str1 = networkCapabilities.toString()
+            },
+            { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" }
+        )
+    }
+
+    fun logOnLost(buffer: LogBuffer, tag: String, network: Network) {
+        buffer.log(tag, LogLevel.INFO, { int1 = network.getNetId() }, { "onLost: net=$int1" })
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
index 45c6d46..5d9ba018 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
@@ -26,8 +26,7 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
 import com.android.systemui.tuner.TunerService
@@ -45,59 +44,61 @@
  * types of connectivity (wifi, mobile, ethernet, etc.)
  */
 interface ConnectivityRepository {
-    /**
-     * Observable for the current set of connectivity icons that should be force-hidden.
-     */
+    /** Observable for the current set of connectivity icons that should be force-hidden. */
     val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>>
 }
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
-class ConnectivityRepositoryImpl @Inject constructor(
+class ConnectivityRepositoryImpl
+@Inject
+constructor(
     private val connectivitySlots: ConnectivitySlots,
     context: Context,
     dumpManager: DumpManager,
-    logger: ConnectivityPipelineLogger,
+    logger: ConnectivityInputLogger,
     @Application scope: CoroutineScope,
     tunerService: TunerService,
 ) : ConnectivityRepository, Dumpable {
     init {
-        dumpManager.registerDumpable("${SB_LOGGING_TAG}Repository", this)
+        dumpManager.registerDumpable("ConnectivityRepository", this)
     }
 
     // The default set of hidden icons to use if we don't get any from [TunerService].
     private val defaultHiddenIcons: Set<ConnectivitySlot> =
-            context.resources.getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE)
-                .asList()
-                .toSlotSet(connectivitySlots)
+        context.resources
+            .getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE)
+            .asList()
+            .toSlotSet(connectivitySlots)
 
-    override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = conflatedCallbackFlow {
-        val callback = object : TunerService.Tunable {
-            override fun onTuningChanged(key: String, newHideList: String?) {
-                if (key != HIDDEN_ICONS_TUNABLE_KEY) {
-                    return
-                }
-                logger.logInputChange("onTuningChanged", newHideList)
+    override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> =
+        conflatedCallbackFlow {
+                val callback =
+                    object : TunerService.Tunable {
+                        override fun onTuningChanged(key: String, newHideList: String?) {
+                            if (key != HIDDEN_ICONS_TUNABLE_KEY) {
+                                return
+                            }
+                            logger.logTuningChanged(newHideList)
 
-                val outputList = newHideList?.split(",")?.toSlotSet(connectivitySlots)
-                    ?: defaultHiddenIcons
-                trySend(outputList)
+                            val outputList =
+                                newHideList?.split(",")?.toSlotSet(connectivitySlots)
+                                    ?: defaultHiddenIcons
+                            trySend(outputList)
+                        }
+                    }
+                tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY)
+
+                awaitClose { tunerService.removeTunable(callback) }
             }
-        }
-        tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY)
-
-        awaitClose { tunerService.removeTunable(callback) }
-    }
-        .stateIn(
-            scope,
-            started = SharingStarted.WhileSubscribed(),
-            initialValue = defaultHiddenIcons
-        )
+            .stateIn(
+                scope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = defaultHiddenIcons
+            )
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.apply {
-            println("defaultHiddenIcons=$defaultHiddenIcons")
-        }
+        pw.apply { println("defaultHiddenIcons=$defaultHiddenIcons") }
     }
 
     companion object {
@@ -111,8 +112,7 @@
         private fun List<String>.toSlotSet(
             connectivitySlots: ConnectivitySlots
         ): Set<ConnectivitySlot> {
-            return this
-                .filter { it.isNotBlank() }
+            return this.filter { it.isNotBlank() }
                 .mapNotNull { connectivitySlots.getSlotFromName(it) }
                 .toSet()
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 7b486c1..ee58160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -39,12 +39,11 @@
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
+import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -58,6 +57,7 @@
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 
 /** Real implementation of [WifiRepository]. */
@@ -70,7 +70,7 @@
 constructor(
     broadcastDispatcher: BroadcastDispatcher,
     connectivityManager: ConnectivityManager,
-    logger: ConnectivityPipelineLogger,
+    logger: WifiInputLogger,
     @WifiTableLog wifiTableLogBuffer: TableLogBuffer,
     @Main mainExecutor: Executor,
     @Application scope: CoroutineScope,
@@ -80,7 +80,7 @@
     private val wifiStateChangeEvents: Flow<Unit> =
         broadcastDispatcher
             .broadcastFlow(IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION))
-            .logInputChange(logger, "WIFI_STATE_CHANGED_ACTION intent")
+            .onEach { logger.logIntent("WIFI_STATE_CHANGED_ACTION") }
 
     private val wifiNetworkChangeEvents: MutableSharedFlow<Unit> =
         MutableSharedFlow(extraBufferCapacity = 1)
@@ -173,11 +173,6 @@
                                         networkCapabilities,
                                         wifiManager,
                                     )
-                                logger.logTransformation(
-                                    WIFI_NETWORK_CALLBACK_NAME,
-                                    oldValue = currentWifi,
-                                    newValue = wifiNetworkModel,
-                                )
                                 currentWifi = wifiNetworkModel
                                 trySend(wifiNetworkModel)
                             }
@@ -194,11 +189,6 @@
                                     wifi.networkId == network.getNetId()
                             ) {
                                 val newNetworkModel = WifiNetworkModel.Inactive
-                                logger.logTransformation(
-                                    WIFI_NETWORK_CALLBACK_NAME,
-                                    oldValue = wifi,
-                                    newValue = newNetworkModel,
-                                )
                                 currentWifi = newNetworkModel
                                 trySend(newNetworkModel)
                             }
@@ -228,7 +218,7 @@
     override val wifiActivity: StateFlow<DataActivityModel> =
         conflatedCallbackFlow {
                 val callback = TrafficStateCallback { state ->
-                    logger.logInputChange("onTrafficStateChange", prettyPrintActivity(state))
+                    logger.logActivity(prettyPrintActivity(state))
                     trySend(state.toWifiDataActivityModel())
                 }
                 wifiManager.registerTrafficStateCallback(mainExecutor, callback)
@@ -336,8 +326,6 @@
                 .addTransportType(TRANSPORT_CELLULAR)
                 .build()
 
-        private const val WIFI_NETWORK_CALLBACK_NAME = "wifiNetworkModel"
-
         private const val CARRIER_MERGED_INVALID_SUB_ID_REASON =
             "Wifi network was carrier merged but had invalid sub ID"
     }
@@ -348,7 +336,7 @@
     constructor(
         private val broadcastDispatcher: BroadcastDispatcher,
         private val connectivityManager: ConnectivityManager,
-        private val logger: ConnectivityPipelineLogger,
+        private val logger: WifiInputLogger,
         @WifiTableLog private val wifiTableLogBuffer: TableLogBuffer,
         @Main private val mainExecutor: Executor,
         @Application private val scope: CoroutineScope,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
index 4f7fe28..8bea772 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
 import java.io.PrintWriter
 import javax.inject.Inject
 
@@ -30,12 +29,14 @@
  * logging purposes.
  */
 @SysUISingleton
-class WifiConstants @Inject constructor(
-        context: Context,
-        dumpManager: DumpManager,
+class WifiConstants
+@Inject
+constructor(
+    context: Context,
+    dumpManager: DumpManager,
 ) : Dumpable {
     init {
-        dumpManager.registerDumpable("${SB_LOGGING_TAG}WifiConstants", this)
+        dumpManager.registerNormalDumpable("WifiConstants", this)
     }
 
     /** True if we should always show the wifi icon when wifi is enabled and false otherwise. */
@@ -43,8 +44,6 @@
         context.resources.getBoolean(R.bool.config_showWifiIndicatorWhenEnabled)
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.apply {
-            println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled")
-        }
+        pw.apply { println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled") }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
new file mode 100644
index 0000000..a32e475
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.statusbar.pipeline.wifi.shared
+
+import android.net.Network
+import android.net.NetworkCapabilities
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.statusbar.pipeline.dagger.WifiInputLog
+import com.android.systemui.statusbar.pipeline.shared.LoggerHelper
+import javax.inject.Inject
+
+/**
+ * Logger for all the wifi-related inputs (intents, callbacks, etc.) that the wifi repo receives.
+ */
+@SysUISingleton
+class WifiInputLogger
+@Inject
+constructor(
+    @WifiInputLog val buffer: LogBuffer,
+) {
+    fun logOnCapabilitiesChanged(
+        network: Network,
+        networkCapabilities: NetworkCapabilities,
+        isDefaultNetworkCallback: Boolean,
+    ) {
+        LoggerHelper.logOnCapabilitiesChanged(
+            buffer,
+            TAG,
+            network,
+            networkCapabilities,
+            isDefaultNetworkCallback,
+        )
+    }
+
+    fun logOnLost(network: Network) {
+        LoggerHelper.logOnLost(buffer, TAG, network)
+    }
+
+    fun logIntent(intentName: String) {
+        buffer.log(TAG, LogLevel.DEBUG, { str1 = intentName }, { "Intent received: $str1" })
+    }
+
+    fun logActivity(activity: String) {
+        buffer.log(TAG, LogLevel.DEBUG, { str1 = activity }, { "Activity: $str1" })
+    }
+}
+
+private const val TAG = "WifiInputLog"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 0f5ff91..1057231 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -34,8 +34,6 @@
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
 import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
@@ -69,7 +67,6 @@
     airplaneModeViewModel: AirplaneModeViewModel,
     connectivityConstants: ConnectivityConstants,
     private val context: Context,
-    logger: ConnectivityPipelineLogger,
     @WifiTableLog wifiTableLogBuffer: TableLogBuffer,
     interactor: WifiInteractor,
     @Application private val scope: CoroutineScope,
@@ -143,29 +140,35 @@
             )
 
     /** The wifi activity status. Null if we shouldn't display the activity status. */
-    private val activity: Flow<DataActivityModel?> =
+    private val activity: Flow<DataActivityModel> = run {
+        val default = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
         if (!connectivityConstants.shouldShowActivityConfig) {
-                flowOf(null)
+                flowOf(default)
             } else {
                 combine(interactor.activity, interactor.ssid) { activity, ssid ->
                     when (ssid) {
-                        null -> null
+                        null -> default
                         else -> activity
                     }
                 }
             }
             .distinctUntilChanged()
-            .logOutputChange(logger, "activity")
-            .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = null)
+            .logDiffsForTable(
+                wifiTableLogBuffer,
+                columnPrefix = "VM.activity",
+                initialValue = default,
+            )
+            .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = default)
+    }
 
     private val isActivityInViewVisible: Flow<Boolean> =
         activity
-            .map { it?.hasActivityIn == true }
+            .map { it.hasActivityIn }
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
 
     private val isActivityOutViewVisible: Flow<Boolean> =
         activity
-            .map { it?.hasActivityOut == true }
+            .map { it.hasActivityOut }
             .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
 
     private val isActivityContainerVisible: Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index e4e59a0..3263c4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -25,6 +25,7 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.view.accessibility.AccessibilityManager;
@@ -91,6 +92,7 @@
         mUiEventLogger = uiEventLogger;
         Resources resources = context.getResources();
         mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time);
+        mStickyDisplayTime = resources.getInteger(R.integer.sticky_heads_up_notification_time);
         mAutoDismissNotificationDecay = resources.getInteger(R.integer.heads_up_notification_decay);
         mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
         mSnoozedPackages = new ArrayMap<>();
@@ -408,8 +410,11 @@
 
         @Override
         public boolean isSticky() {
-            return (mEntry.isRowPinned() && expanded)
-                    || remoteInputActive || hasFullScreenIntent(mEntry);
+            final boolean isSticky = (mEntry.isRowPinned() && expanded)
+                    || remoteInputActive
+                    || hasFullScreenIntent(mEntry)
+                    || mEntry.isStickyAndNotDemoted();
+            return isSticky;
         }
 
         @Override
@@ -465,8 +470,15 @@
             return super.calculatePostTime() + mTouchAcceptanceDelay;
         }
 
+        /**
+         * @return When the notification should auto-dismiss itself, based on
+         * {@link SystemClock#elapsedRealTime()}
+         */
         @Override
         protected long calculateFinishTime() {
+            if (isSticky()) {
+                return mEntry.mCreationElapsedRealTime + mStickyDisplayTime;
+            }
             return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
index 1ae1eae..8929e02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -56,7 +56,7 @@
     /**
      * Whether the bouncer (PIN/password entry) is currently visible.
      */
-    boolean isBouncerShowing();
+    boolean isPrimaryBouncerShowing();
 
     /**
      * If swiping up will unlock without asking for a password.
@@ -196,7 +196,7 @@
     /** **/
     default void notifyKeyguardState(boolean showing, boolean occluded) {}
     /** **/
-    default void notifyBouncerShowing(boolean showing) {}
+    default void notifyPrimaryBouncerShowing(boolean showing) {}
 
     /**
      * Updates the keyguard state to reflect that it's in the process of being dismissed, either by
@@ -244,7 +244,7 @@
         /**
          * Called when the bouncer (PIN/password entry) is shown or hidden.
          */
-        default void onBouncerShowingChanged() {}
+        default void onPrimaryBouncerShowingChanged() {}
 
         /**
          * Triggered when the device was just unlocked and the lock screen is being dismissed.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 9ad36fd5..805368c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -65,7 +65,7 @@
 
     private boolean mCanDismissLockScreen;
     private boolean mShowing;
-    private boolean mBouncerShowing;
+    private boolean mPrimaryBouncerShowing;
     private boolean mSecure;
     private boolean mOccluded;
 
@@ -157,8 +157,8 @@
     }
 
     @Override
-    public boolean isBouncerShowing() {
-        return mBouncerShowing;
+    public boolean isPrimaryBouncerShowing() {
+        return mPrimaryBouncerShowing;
     }
 
     @Override
@@ -339,11 +339,11 @@
     }
 
     @Override
-    public void notifyBouncerShowing(boolean showing) {
-        if (mBouncerShowing != showing) {
-            mBouncerShowing = showing;
+    public void notifyPrimaryBouncerShowing(boolean showing) {
+        if (mPrimaryBouncerShowing != showing) {
+            mPrimaryBouncerShowing = showing;
 
-            new ArrayList<>(mCallbacks).forEach(Callback::onBouncerShowingChanged);
+            new ArrayList<>(mCallbacks).forEach(Callback::onPrimaryBouncerShowingChanged);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index c0cbd62..462504e 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -26,6 +26,9 @@
 import android.util.ArrayMap
 import android.util.Log
 import android.view.InputDevice
+import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.logging.InstanceId
+import com.android.internal.logging.InstanceIdSequence
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
@@ -33,7 +36,6 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.shared.hardware.hasInputDevice
 import com.android.systemui.shared.hardware.isInternalStylusSource
-import com.android.systemui.statusbar.notification.collection.listbuilder.DEBUG
 import java.util.concurrent.CopyOnWriteArrayList
 import java.util.concurrent.Executor
 import javax.inject.Inject
@@ -61,12 +63,17 @@
     private val stylusCallbacks: CopyOnWriteArrayList<StylusCallback> = CopyOnWriteArrayList()
     private val stylusBatteryCallbacks: CopyOnWriteArrayList<StylusBatteryCallback> =
         CopyOnWriteArrayList()
+
     // This map should only be accessed on the handler
     private val inputDeviceAddressMap: MutableMap<Int, String?> = ArrayMap()
+    private val inputDeviceBtSessionIdMap: MutableMap<Int, InstanceId> = ArrayMap()
 
     // These variables should only be accessed on the handler
     private var hasStarted: Boolean = false
     private var isInUsiSession: Boolean = false
+    private var usiSessionId: InstanceId? = null
+
+    @VisibleForTesting var instanceIdSequence = InstanceIdSequence(1 shl 13)
 
     /**
      * Starts listening to InputManager InputDevice events. Will also load the InputManager snapshot
@@ -120,7 +127,7 @@
 
         if (btAddress != null) {
             onStylusUsed()
-            onStylusBluetoothConnected(btAddress)
+            onStylusBluetoothConnected(deviceId, btAddress)
             executeStylusCallbacks { cb -> cb.onStylusBluetoothConnected(deviceId, btAddress) }
         }
     }
@@ -136,12 +143,12 @@
         inputDeviceAddressMap[deviceId] = currAddress
 
         if (prevAddress == null && currAddress != null) {
-            onStylusBluetoothConnected(currAddress)
+            onStylusBluetoothConnected(deviceId, currAddress)
             executeStylusCallbacks { cb -> cb.onStylusBluetoothConnected(deviceId, currAddress) }
         }
 
         if (prevAddress != null && currAddress == null) {
-            onStylusBluetoothDisconnected(prevAddress)
+            onStylusBluetoothDisconnected(deviceId, prevAddress)
             executeStylusCallbacks { cb -> cb.onStylusBluetoothDisconnected(deviceId, prevAddress) }
         }
     }
@@ -155,7 +162,7 @@
         val btAddress: String? = inputDeviceAddressMap[deviceId]
         inputDeviceAddressMap.remove(deviceId)
         if (btAddress != null) {
-            onStylusBluetoothDisconnected(btAddress)
+            onStylusBluetoothDisconnected(deviceId, btAddress)
             executeStylusCallbacks { cb -> cb.onStylusBluetoothDisconnected(deviceId, btAddress) }
         }
         executeStylusCallbacks { cb -> cb.onStylusRemoved(deviceId) }
@@ -208,8 +215,8 @@
         }
     }
 
-    private fun onStylusBluetoothConnected(btAddress: String) {
-        uiEventLogger.log(StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED)
+    private fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
+        trackAndLogBluetoothSession(deviceId, true)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.addOnMetadataChangedListener(device, executor, this)
@@ -218,8 +225,8 @@
         }
     }
 
-    private fun onStylusBluetoothDisconnected(btAddress: String) {
-        uiEventLogger.log(StylusUiEvent.BLUETOOTH_STYLUS_DISCONNECTED)
+    private fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {
+        trackAndLogBluetoothSession(deviceId, false)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.removeOnMetadataChangedListener(device, this)
@@ -251,21 +258,51 @@
     private fun trackAndLogUsiSession(deviceId: Int, batteryStateValid: Boolean) {
         // TODO(b/268618918) handle cases where an invalid battery callback from a previous stylus
         //  is sent after the actual valid callback
-        if (batteryStateValid && !isInUsiSession) {
+        if (batteryStateValid && usiSessionId == null) {
             if (DEBUG) {
                 Log.d(
                     TAG,
                     "USI battery newly present, entering new USI session. Device ID: $deviceId"
                 )
             }
-            isInUsiSession = true
-            uiEventLogger.log(StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED)
-        } else if (!batteryStateValid && isInUsiSession) {
+            usiSessionId = instanceIdSequence.newInstanceId()
+            uiEventLogger.logWithInstanceId(
+                StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
+                0,
+                null,
+                usiSessionId
+            )
+        } else if (!batteryStateValid && usiSessionId != null) {
             if (DEBUG) {
                 Log.d(TAG, "USI battery newly absent, exiting USI session Device ID: $deviceId")
             }
-            isInUsiSession = false
-            uiEventLogger.log(StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED)
+            uiEventLogger.logWithInstanceId(
+                StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED,
+                0,
+                null,
+                usiSessionId
+            )
+            usiSessionId = null
+        }
+    }
+
+    private fun trackAndLogBluetoothSession(deviceId: Int, bluetoothConnected: Boolean) {
+        if (bluetoothConnected) {
+            inputDeviceBtSessionIdMap[deviceId] = instanceIdSequence.newInstanceId()
+            uiEventLogger.logWithInstanceId(
+                StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED,
+                0,
+                null,
+                inputDeviceBtSessionIdMap[deviceId]
+            )
+        } else {
+            uiEventLogger.logWithInstanceId(
+                StylusUiEvent.BLUETOOTH_STYLUS_DISCONNECTED,
+                0,
+                null,
+                inputDeviceBtSessionIdMap[deviceId]
+            )
+            inputDeviceBtSessionIdMap.remove(deviceId)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index 89453ad..ec0a6e7 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -33,6 +33,8 @@
 import androidx.core.app.NotificationCompat
 import androidx.core.app.NotificationManagerCompat
 import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.logging.InstanceId
+import com.android.internal.logging.InstanceIdSequence
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
@@ -62,6 +64,9 @@
     private var batteryCapacity = 1.0f
     private var suppressed = false
     private var inputDeviceId: Int? = null
+    private var instanceId: InstanceId? = null
+
+    @VisibleForTesting var instanceIdSequence = InstanceIdSequence(1 shl 13)
 
     fun init() {
         val filter =
@@ -126,6 +131,7 @@
     }
 
     private fun hideNotification() {
+        instanceId = null
         notificationManager.cancel(USI_NOTIFICATION_ID)
     }
 
@@ -204,15 +210,28 @@
             }
         }
 
+    /**
+     * Logs a stylus USI battery event with instance ID and battery level. The instance ID
+     * represents the notification instance, and is reset when a notification is cancelled.
+     */
     private fun logUiEvent(metricId: StylusUiEvent) {
-        uiEventLogger.logWithPosition(
+        uiEventLogger.logWithInstanceIdAndPosition(
             metricId,
             ActivityManager.getCurrentUser(),
             context.packageName,
+            getInstanceId(),
             (batteryCapacity * 100.0).toInt()
         )
     }
 
+    @VisibleForTesting
+    fun getInstanceId(): InstanceId? {
+        if (instanceId == null) {
+            instanceId = instanceId ?: instanceIdSequence.newInstanceId()
+        }
+        return instanceId
+    }
+
     companion object {
         // Low battery threshold matches CrOS, see:
         // https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
diff --git a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
index c1f0c58..39dda8c 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
+++ b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
@@ -55,15 +55,15 @@
                 Pair.create("error_container", MDC.errorContainer),
                 Pair.create("on_error_container", MDC.onErrorContainer),
                 Pair.create("primary_fixed", MDC.primaryFixed),
-                Pair.create("primary_fixed_darker", MDC.primaryFixedDarker),
+                Pair.create("primary_fixed_dim", MDC.primaryFixedDim),
                 Pair.create("on_primary_fixed", MDC.onPrimaryFixed),
                 Pair.create("on_primary_fixed_variant", MDC.onPrimaryFixedVariant),
                 Pair.create("secondary_fixed", MDC.secondaryFixed),
-                Pair.create("secondary_fixed_darker", MDC.secondaryFixedDarker),
+                Pair.create("secondary_fixed_dim", MDC.secondaryFixedDim),
                 Pair.create("on_secondary_fixed", MDC.onSecondaryFixed),
                 Pair.create("on_secondary_fixed_variant", MDC.onSecondaryFixedVariant),
                 Pair.create("tertiary_fixed", MDC.tertiaryFixed),
-                Pair.create("tertiary_fixed_darker", MDC.tertiaryFixedDarker),
+                Pair.create("tertiary_fixed_dim", MDC.tertiaryFixedDim),
                 Pair.create("on_tertiary_fixed", MDC.onTertiaryFixed),
                 Pair.create("on_tertiary_fixed_variant", MDC.onTertiaryFixedVariant),
                 Pair.create("control_activated", MDC.controlActivated),
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
index badeb27..81fef7a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
@@ -31,6 +31,7 @@
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE
 import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS
+import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
@@ -338,6 +339,70 @@
     }
 
     @Test
+    fun isWakeupForceDismissKeyguard_singleValue() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift is considered an unlock intent
+        secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
+            PowerManager.WAKE_REASON_LIFT.toString(), currentUser)
+        updateSetting(secureSettings.getUriFor(
+            ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD
+        ))
+
+        // THEN only WAKE_REASON_LIFT is considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            if (wakeReason == PowerManager.WAKE_REASON_LIFT) {
+                assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason))
+            } else {
+                assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason))
+            }
+        }
+    }
+
+    @Test
+    fun isWakeupForceDismissKeyguard_emptyValues() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift and tap are considered an unlock intent
+        secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
+            " ", currentUser)
+        updateSetting(secureSettings.getUriFor(
+            ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD
+        ))
+
+        // THEN no wake up gestures are considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason))
+        }
+    }
+
+    @Test
+    fun isWakeupForceDismissKeyguard_multiValue() {
+        verifyRegisterSettingObserver()
+
+        // GIVEN lift and tap are considered an unlock intent
+        secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD,
+            PowerManager.WAKE_REASON_LIFT.toString() +
+                    "|" +
+                    PowerManager.WAKE_REASON_TAP.toString(),
+            currentUser
+        )
+        updateSetting(secureSettings.getUriFor(
+            ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD
+        ))
+
+        // THEN WAKE_REASON_LIFT and WAKE_REASON TAP are considered an unlock intent
+        for (wakeReason in 0..WAKE_REASON_BIOMETRIC) {
+            if (wakeReason == PowerManager.WAKE_REASON_LIFT ||
+                wakeReason == PowerManager.WAKE_REASON_TAP) {
+                assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason))
+            } else {
+                assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason))
+            }
+        }
+    }
+
+    @Test
     fun dump_onUnlockIntentWhenBiometricEnrolled_invalidNum_noArrayOutOfBoundsException() {
         // GIVEN an invalid input (-1)
         secureSettings.putStringForUser(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index f7fec80..480b8f9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -85,6 +86,7 @@
     @Mock private lateinit var transitionRepository: KeyguardTransitionRepository
     @Mock private lateinit var commandQueue: CommandQueue
     private lateinit var repository: FakeKeyguardRepository
+    private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
     @Mock private lateinit var smallLogBuffer: LogBuffer
     @Mock private lateinit var largeLogBuffer: LogBuffer
     private lateinit var underTest: ClockEventController
@@ -103,11 +105,15 @@
         whenever(largeClockEvents.tickRate).thenReturn(ClockTickRate.PER_MINUTE)
 
         repository = FakeKeyguardRepository()
+        bouncerRepository = FakeKeyguardBouncerRepository()
 
         underTest = ClockEventController(
-            KeyguardInteractor(repository = repository,
-                    commandQueue = commandQueue,
-                    featureFlags = featureFlags),
+            KeyguardInteractor(
+                repository = repository,
+                commandQueue = commandQueue,
+                featureFlags = featureFlags,
+                bouncerRepository = bouncerRepository,
+            ),
             KeyguardTransitionInteractor(repository = transitionRepository),
             broadcastDispatcher,
             batteryController,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index ccc4e4a..a5f90f8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -241,7 +241,7 @@
         mController.init();
         verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture());
 
-        listenerArgumentCaptor.getValue().onClockChanged();
+        listenerArgumentCaptor.getValue().onCurrentClockChanged();
         verify(mView, times(2)).setClock(mClockController, StatusBarState.SHADE);
         verify(mClockEventController, times(2)).setClock(mClockController);
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
deleted file mode 100644
index 4021652..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2018 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.keyguard;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.media.AudioManager;
-import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableResources;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class KeyguardHostViewControllerTest extends SysuiTestCase {
-    @Mock
-    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-
-    private KeyguardHostView mKeyguardHostView;
-    @Mock
-    private AudioManager mAudioManager;
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private ViewMediatorCallback mViewMediatorCallback;
-    @Mock
-    KeyguardSecurityContainerController.Factory mKeyguardSecurityContainerControllerFactory;
-    @Mock
-    private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
-
-    @Rule
-    public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    private TestableResources mTestableResources;
-    private KeyguardHostViewController mKeyguardHostViewController;
-
-    @Before
-    public void setup() {
-        mTestableResources = mContext.getOrCreateTestableResources();
-
-        mKeyguardHostView = new KeyguardHostView(mContext);
-
-        // Explicitly disable one handed keyguard.
-        mTestableResources.addOverride(
-                R.bool.can_use_one_handed_bouncer, false);
-
-        when(mKeyguardSecurityContainerControllerFactory.create(any(
-                KeyguardSecurityContainer.SecurityCallback.class)))
-                .thenReturn(mKeyguardSecurityContainerController);
-        mKeyguardHostViewController = new KeyguardHostViewController(
-                mKeyguardHostView, mKeyguardUpdateMonitor, mAudioManager, mTelephonyManager,
-                mViewMediatorCallback, mKeyguardSecurityContainerControllerFactory);
-    }
-
-    @Test
-    public void testHasDismissActions() {
-        assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions());
-        mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class),
-                null /* cancelAction */);
-        assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions());
-    }
-
-    @Test
-    public void testOnStartingToHide() {
-        mKeyguardHostViewController.onStartingToHide();
-        verify(mKeyguardSecurityContainerController).onStartingToHide();
-    }
-
-    @Test
-    public void onBouncerVisible_propagatesToKeyguardSecurityContainerController() {
-        mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.VISIBLE);
-        mKeyguardHostViewController.onBouncerVisibilityChanged(ViewGroup.INVISIBLE);
-
-        InOrder order = inOrder(mKeyguardSecurityContainerController);
-        order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(View.VISIBLE);
-        order.verify(mKeyguardSecurityContainerController).onBouncerVisibilityChanged(
-                View.INVISIBLE);
-    }
-
-    @Test
-    public void testGravityReappliedOnConfigurationChange() {
-        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT);
-        mKeyguardHostView.setLayoutParams(lp);
-
-        // Set initial gravity
-        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER);
-
-        // Kick off the initial pass...
-        mKeyguardHostViewController.init();
-        assertEquals(
-                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
-                Gravity.CENTER);
-
-        // Now simulate a config change
-        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-
-        mKeyguardHostViewController.updateResources();
-        assertEquals(
-                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-    }
-
-    @Test
-    public void testGravityUsesOneHandGravityWhenApplicable() {
-        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT);
-        mKeyguardHostView.setLayoutParams(lp);
-
-        mTestableResources.addOverride(
-                R.integer.keyguard_host_view_gravity,
-                Gravity.CENTER);
-        mTestableResources.addOverride(
-                R.integer.keyguard_host_view_one_handed_gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-
-        // Start disabled.
-        mTestableResources.addOverride(
-                R.bool.can_use_one_handed_bouncer, false);
-
-        mKeyguardHostViewController.init();
-        assertEquals(
-                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
-                Gravity.CENTER);
-
-        // And enable
-        mTestableResources.addOverride(
-                R.bool.can_use_one_handed_bouncer, true);
-
-        mKeyguardHostViewController.updateResources();
-        assertEquals(
-                ((FrameLayout.LayoutParams) mKeyguardHostView.getLayoutParams()).gravity,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-    }
-
-    @Test
-    public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
-        mKeyguardHostViewController.updateKeyguardPosition(1.0f);
-
-        verify(mKeyguardSecurityContainerController).updateKeyguardPosition(1.0f);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index e1982ad..568e8d2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -23,12 +23,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -40,12 +45,17 @@
 import android.content.res.Resources;
 import android.hardware.biometrics.BiometricOverlayConstants;
 import android.hardware.biometrics.BiometricSourceType;
+import android.media.AudioManager;
+import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowInsetsController;
+import android.widget.FrameLayout;
 
 import androidx.test.filters.SmallTest;
 
@@ -61,6 +71,7 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.log.SessionTracker;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -72,6 +83,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
@@ -109,8 +121,6 @@
     @Mock
     private KeyguardInputViewController mInputViewController;
     @Mock
-    private KeyguardSecurityContainer.SecurityCallback mSecurityCallback;
-    @Mock
     private WindowInsetsController mWindowInsetsController;
     @Mock
     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@@ -127,8 +137,6 @@
     @Mock
     private EmergencyButtonController mEmergencyButtonController;
     @Mock
-    private Resources mResources;
-    @Mock
     private FalsingCollector mFalsingCollector;
     @Mock
     private FalsingManager mFalsingManager;
@@ -148,6 +156,12 @@
     private KeyguardPasswordViewController mKeyguardPasswordViewControllerMock;
     @Mock
     private FalsingA11yDelegate mFalsingA11yDelegate;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ViewMediatorCallback mViewMediatorCallback;
+    @Mock
+    private AudioManager mAudioManager;
 
     @Captor
     private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
@@ -159,18 +173,25 @@
     private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
     private KeyguardPasswordViewController mKeyguardPasswordViewController;
     private KeyguardPasswordView mKeyguardPasswordView;
+    private TestableResources mTestableResources;
 
     @Before
     public void setup() {
         mConfiguration = new Configuration();
         mConfiguration.setToDefaults(); // Defaults to ORIENTATION_UNDEFINED.
+        mTestableResources = mContext.getOrCreateTestableResources();
 
-        when(mResources.getConfiguration()).thenReturn(mConfiguration);
         when(mView.getContext()).thenReturn(mContext);
-        when(mView.getResources()).thenReturn(mResources);
+        when(mView.getResources()).thenReturn(mContext.getResources());
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(/* width=  */ 0, /* height= */
+                0);
+        lp.gravity = 0;
+        when(mView.getLayoutParams()).thenReturn(lp);
         when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class)))
                 .thenReturn(mAdminSecondaryLockScreenController);
         when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
+        when(mKeyguardSecurityViewFlipperController.getSecurityView(any(SecurityMode.class),
+                any(KeyguardSecurityCallback.class))).thenReturn(mInputViewController);
         mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate(
                 R.layout.keyguard_password_view, null));
         when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper);
@@ -179,20 +200,21 @@
         when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
                 .thenReturn(mKeyguardMessageAreaController);
         when(mKeyguardPasswordView.getWindowInsetsController()).thenReturn(mWindowInsetsController);
+        when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(SecurityMode.PIN);
         mKeyguardPasswordViewController = new KeyguardPasswordViewController(
                 (KeyguardPasswordView) mKeyguardPasswordView, mKeyguardUpdateMonitor,
                 SecurityMode.Password, mLockPatternUtils, null,
                 mKeyguardMessageAreaControllerFactory, null, null, mEmergencyButtonController,
                 null, mock(Resources.class), null, mKeyguardViewController);
 
-        mKeyguardSecurityContainerController = new KeyguardSecurityContainerController.Factory(
+        mKeyguardSecurityContainerController = new KeyguardSecurityContainerController(
                 mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
                 mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
                 mKeyguardStateController, mKeyguardSecurityViewFlipperController,
                 mConfigurationController, mFalsingCollector, mFalsingManager,
                 mUserSwitcherController, mFeatureFlags, mGlobalSettings,
-                mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate).create(
-                mSecurityCallback);
+                mSessionTracker, Optional.of(mSideFpsController), mFalsingA11yDelegate,
+                mTelephonyManager, mViewMediatorCallback, mAudioManager);
     }
 
     @Test
@@ -244,7 +266,8 @@
                 eq(mFalsingA11yDelegate));
 
         // Update rotation. Should trigger update
-        mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        mTestableResources.getResources().getConfiguration().orientation =
+                Configuration.ORIENTATION_LANDSCAPE;
 
         mKeyguardSecurityContainerController.updateResources();
         verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
@@ -278,7 +301,7 @@
 
     @Test
     public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
-        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(false);
+        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, false);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
@@ -292,7 +315,7 @@
 
     @Test
     public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
-        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
+        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
@@ -306,7 +329,7 @@
 
     @Test
     public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
-        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
+        mTestableResources.addOverride(R.bool.can_use_one_handed_bouncer, true);
         setupGetSecurityView();
 
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
@@ -488,7 +511,9 @@
                 SecurityMode.SimPin);
 
         // THEN the next security method of PIN is set, and the keyguard is not marked as done
-        verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
+
+        verify(mViewMediatorCallback, never()).keyguardDonePending(anyBoolean(), anyInt());
+        verify(mViewMediatorCallback, never()).keyguardDone(anyBoolean(), anyInt());
         assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
                 .isEqualTo(SecurityMode.PIN);
     }
@@ -562,17 +587,19 @@
     }
 
     @Test
-    public void onDensityorFontScaleChanged() {
+    public void onDensityOrFontScaleChanged() {
         ArgumentCaptor<ConfigurationController.ConfigurationListener>
                 configurationListenerArgumentCaptor = ArgumentCaptor.forClass(
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
+        clearInvocations(mKeyguardSecurityViewFlipperController);
+
         configurationListenerArgumentCaptor.getValue().onDensityOrFontScaleChanged();
 
         verify(mView).onDensityOrFontScaleChanged();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
                 any(KeyguardSecurityCallback.class));
     }
 
@@ -583,11 +610,13 @@
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
+        clearInvocations(mKeyguardSecurityViewFlipperController);
+
         configurationListenerArgumentCaptor.getValue().onThemeChanged();
 
         verify(mView).reloadColors();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
                 any(KeyguardSecurityCallback.class));
         verify(mView).reset();
         verify(mKeyguardSecurityViewFlipperController).reset();
@@ -600,15 +629,91 @@
                 ConfigurationController.ConfigurationListener.class);
         mKeyguardSecurityContainerController.onViewAttached();
         verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
+        clearInvocations(mKeyguardSecurityViewFlipperController);
+
         configurationListenerArgumentCaptor.getValue().onUiModeChanged();
 
         verify(mView).reloadColors();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
-        verify(mKeyguardSecurityViewFlipperController).getSecurityView(any(SecurityMode.class),
+        verify(mKeyguardSecurityViewFlipperController).getSecurityView(eq(SecurityMode.PIN),
                 any(KeyguardSecurityCallback.class));
     }
 
     @Test
+    public void testHasDismissActions() {
+        assertFalse("Action not set yet", mKeyguardSecurityContainerController.hasDismissActions());
+        mKeyguardSecurityContainerController.setOnDismissAction(mock(
+                        ActivityStarter.OnDismissAction.class),
+                null /* cancelAction */);
+        assertTrue("Action should exist", mKeyguardSecurityContainerController.hasDismissActions());
+    }
+
+    @Test
+    public void testOnStartingToHide() {
+        mKeyguardSecurityContainerController.onStartingToHide();
+        verify(mInputViewController).onStartingToHide();
+    }
+
+    @Test
+    public void testGravityReappliedOnConfigurationChange() {
+        // Set initial gravity
+        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER);
+
+        // Kick off the initial pass...
+        mKeyguardSecurityContainerController.onInit();
+        verify(mView).setLayoutParams(argThat(
+                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
+                        argument.gravity == Gravity.CENTER));
+        clearInvocations(mView);
+
+        // Now simulate a config change
+        mTestableResources.addOverride(R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+
+        mKeyguardSecurityContainerController.updateResources();
+        verify(mView).setLayoutParams(argThat(
+                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
+                        argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
+    }
+
+    @Test
+    public void testGravityUsesOneHandGravityWhenApplicable() {
+        mTestableResources.addOverride(
+                R.integer.keyguard_host_view_gravity,
+                Gravity.CENTER);
+        mTestableResources.addOverride(
+                R.integer.keyguard_host_view_one_handed_gravity,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+
+        // Start disabled.
+        mTestableResources.addOverride(
+                R.bool.can_use_one_handed_bouncer, false);
+
+        mKeyguardSecurityContainerController.onInit();
+        verify(mView).setLayoutParams(argThat(
+                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
+                        argument.gravity == Gravity.CENTER));
+        clearInvocations(mView);
+
+        // And enable
+        mTestableResources.addOverride(
+                R.bool.can_use_one_handed_bouncer, true);
+
+        mKeyguardSecurityContainerController.updateResources();
+        verify(mView).setLayoutParams(argThat(
+                (ArgumentMatcher<FrameLayout.LayoutParams>) argument ->
+                        argument.gravity == (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)));
+    }
+
+    @Test
+    public void testUpdateKeyguardPositionDelegatesToSecurityContainer() {
+        mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f);
+        verify(mView).updatePositionByTouchX(1.0f);
+    }
+
+
+    @Test
     public void testReinflateViewFlipper() {
         mKeyguardSecurityContainerController.reinflateViewFlipper();
         verify(mKeyguardSecurityViewFlipperController).clearViews();
@@ -641,7 +746,7 @@
     }
 
     private void setSideFpsHintEnabledFromResources(boolean enabled) {
-        when(mResources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)).thenReturn(
+        mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
                 enabled);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 841ec4b..9fe7506 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -909,6 +909,25 @@
     }
 
     @Test
+    public void noFpListeningWhenKeyguardIsOccluded_unlessAlternateBouncerShowing() {
+        // GIVEN device is awake but occluded
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(false, true);
+
+        // THEN fingerprint shouldn't listen
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse();
+        verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+                anyInt(), anyInt());
+
+        // WHEN alternate bouncer is shown
+        mKeyguardUpdateMonitor.setAlternateBouncerShowing(true);
+
+        // THEN make sure FP listening begins
+        verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+                anyInt());
+    }
+
+    @Test
     public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() {
         mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
         mTestableLooper.processAllMessages();
@@ -2006,7 +2025,6 @@
         verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
     }
 
-
     @Test
     public void testOnTrustGrantedForCurrentUser_dismissKeyguardRequested_deviceInteractive() {
         // GIVEN device is interactive
@@ -2432,6 +2450,56 @@
         assertThat(mKeyguardUpdateMonitor.mIncompatibleCharger).isFalse();
     }
 
+    @Test
+    public void unfoldWakeup_requestActiveUnlock_forceDismissKeyguard()
+            throws RemoteException {
+        // GIVEN shouldTriggerActiveUnlock
+        keyguardIsVisible();
+        when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true);
+
+        // GIVEN active unlock triggers on wakeup
+        when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE))
+                .thenReturn(true);
+
+        // GIVEN an unfold should force dismiss the keyguard
+        when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard(
+                PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(true);
+
+        // WHEN device wakes up from an unfold
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE);
+        mTestableLooper.processAllMessages();
+
+        // THEN request unlock with a keyguard dismissal
+        verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()),
+                eq(true));
+    }
+
+    @Test
+    public void unfoldWakeup_requestActiveUnlock_noDismissKeyguard()
+            throws RemoteException {
+        // GIVEN shouldTriggerActiveUnlock on wake from UNFOLD_DEVICE
+        keyguardIsVisible();
+        when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true);
+
+        // GIVEN active unlock triggers on wakeup
+        when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin(
+                ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE))
+                .thenReturn(true);
+
+        // GIVEN an unfold should NOT force dismiss the keyguard
+        when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard(
+                PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(false);
+
+        // WHEN device wakes up from an unfold
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE);
+        mTestableLooper.processAllMessages();
+
+        // THEN request unlock WITHOUT a keyguard dismissal
+        verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()),
+                eq(false));
+    }
+
     private void userDeviceLockDown() {
         when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
         when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 3d0d036..456702b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.doze.util.BurnInHelperKt;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
@@ -159,9 +160,12 @@
                 mAuthRippleController,
                 mResources,
                 new KeyguardTransitionInteractor(mTransitionRepository),
-                new KeyguardInteractor(new FakeKeyguardRepository(),
+                new KeyguardInteractor(
+                        new FakeKeyguardRepository(),
                         mCommandQueue,
-                        mFeatureFlags),
+                        mFeatureFlags,
+                        new FakeKeyguardBouncerRepository()
+                ),
                 mFeatureFlags
         );
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index 472d207..f370ad6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -286,4 +286,26 @@
         // THEN the lock icon is shown
         verify(mLockIconView).setContentDescription(LOCKED_LABEL);
     }
+
+    @Test
+    public void lockIconShows_afterUnlockStateChanges() {
+        // GIVEN lock icon controller is initialized and view is attached
+        init(/* useMigrationFlag= */false);
+        captureKeyguardStateCallback();
+        captureKeyguardUpdateMonitorCallback();
+
+        // GIVEN user has unlocked with a biometric auth (ie: face auth)
+        // and biometric running state changes
+        when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(true);
+        mKeyguardUpdateMonitorCallback.onBiometricRunningStateChanged(false,
+                BiometricSourceType.FACE);
+        reset(mLockIconView);
+
+        // WHEN the unlocked state changes
+        when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(anyInt())).thenReturn(false);
+        mKeyguardStateCallback.onUnlockedChanged();
+
+        // THEN the lock icon is shown
+        verify(mLockIconView).setContentDescription(LOCKED_LABEL);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 0d00e8a..e1c7417 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -24,6 +24,7 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotSame;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
@@ -33,6 +34,8 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -48,6 +51,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
@@ -177,6 +181,8 @@
     private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor;
     @Captor
     private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
+    @Mock
+    private Resources mResources;
 
     private TestableContext mContextSpy;
     private Execution mExecution;
@@ -905,6 +911,25 @@
         );
     }
 
+    @Test
+    public void testUpdateFingerprintLocation_defaultPointChanges_whenConfigChanges() {
+        when(mContextSpy.getResources()).thenReturn(mResources);
+
+        doReturn(500).when(mResources)
+                .getDimensionPixelSize(eq(com.android.systemui.R.dimen
+                        .physical_fingerprint_sensor_center_screen_location_y));
+        mAuthController.onConfigurationChanged(null /* newConfig */);
+
+        final Point firstFpLocation = mAuthController.getFingerprintSensorLocation();
+
+        doReturn(1000).when(mResources)
+                .getDimensionPixelSize(eq(com.android.systemui.R.dimen
+                        .physical_fingerprint_sensor_center_screen_location_y));
+        mAuthController.onConfigurationChanged(null /* newConfig */);
+
+        assertNotSame(firstFpLocation, mAuthController.getFingerprintSensorLocation());
+    }
+
     private void showDialog(int[] sensorIds, boolean credentialAllowed) {
         mAuthController.showAuthenticationDialog(createTestPromptInfo(),
                 mReceiver /* receiver */,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
index 4439586..2283746 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
@@ -18,9 +18,13 @@
 
 import android.app.job.JobParameters
 import android.content.Context
+import android.os.PersistableBundle
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapper.DeletionJobService.Companion.USER
+import com.android.systemui.util.mockito.whenever
+import java.util.concurrent.TimeUnit
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
@@ -28,18 +32,15 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import java.util.concurrent.TimeUnit
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 class DeletionJobServiceTest : SysuiTestCase() {
 
-    @Mock
-    private lateinit var context: Context
+    @Mock private lateinit var context: Context
 
     private lateinit var service: AuxiliaryPersistenceWrapper.DeletionJobService
 
@@ -53,6 +54,10 @@
 
     @Test
     fun testOnStartJob() {
+        val bundle = PersistableBundle().also { it.putInt(USER, 0) }
+        val params = mock(JobParameters::class.java)
+        whenever(params.getExtras()).thenReturn(bundle)
+
         // false means job is terminated
         assertFalse(service.onStartJob(mock(JobParameters::class.java)))
         verify(context).deleteFile(AuxiliaryPersistenceWrapper.AUXILIARY_FILE_NAME)
@@ -67,13 +72,17 @@
     @Test
     fun testJobHasRightParameters() {
         val userId = 10
-        `when`(context.userId).thenReturn(userId)
-        `when`(context.packageName).thenReturn(mContext.packageName)
+        whenever(context.userId).thenReturn(userId)
+        whenever(context.packageName).thenReturn(mContext.packageName)
 
-        val jobInfo = AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context)
+        val jobInfo =
+            AuxiliaryPersistenceWrapper.DeletionJobService.getJobForContext(context, userId)
         assertEquals(
-            AuxiliaryPersistenceWrapper.DeletionJobService.DELETE_FILE_JOB_ID + userId, jobInfo.id)
+            AuxiliaryPersistenceWrapper.DeletionJobService.DELETE_FILE_JOB_ID + userId,
+            jobInfo.id
+        )
         assertTrue(jobInfo.isPersisted)
+        assertEquals(userId, jobInfo.getExtras().getInt(USER))
         assertEquals(TimeUnit.DAYS.toMillis(7), jobInfo.minLatencyMillis)
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
new file mode 100644
index 0000000..de0e511
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/RestartDozeListenerTest.kt
@@ -0,0 +1,85 @@
+/*
+ * 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.flags
+
+import android.os.PowerManager
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class RestartDozeListenerTest : SysuiTestCase() {
+
+    lateinit var restartDozeListener: RestartDozeListener
+
+    val settings = FakeSettings()
+    @Mock lateinit var statusBarStateController: StatusBarStateController
+    @Mock lateinit var powerManager: PowerManager
+    val clock = FakeSystemClock()
+    lateinit var listener: StatusBarStateController.StateListener
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        restartDozeListener =
+            RestartDozeListener(settings, statusBarStateController, powerManager, clock)
+
+        val captor = ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java)
+        restartDozeListener.init()
+        verify(statusBarStateController).addCallback(captor.capture())
+        listener = captor.value
+    }
+
+    @Test
+    fun testStoreDreamState_onDreamingStarted() {
+        listener.onDreamingChanged(true)
+        assertThat(settings.getBool(RestartDozeListener.RESTART_NAP_KEY)).isTrue()
+    }
+
+    @Test
+    fun testStoreDreamState_onDreamingStopped() {
+        listener.onDreamingChanged(false)
+        assertThat(settings.getBool(RestartDozeListener.RESTART_NAP_KEY)).isFalse()
+    }
+
+    @Test
+    fun testRestoreDreamState_dreamingShouldStart() {
+        settings.putBool(RestartDozeListener.RESTART_NAP_KEY, true)
+        restartDozeListener.maybeRestartSleep()
+        verify(powerManager).wakeUp(clock.uptimeMillis())
+        verify(powerManager).goToSleep(clock.uptimeMillis())
+    }
+
+    @Test
+    fun testRestoreDreamState_dreamingShouldNot() {
+        settings.putBool(RestartDozeListener.RESTART_NAP_KEY, false)
+        restartDozeListener.maybeRestartSleep()
+        verify(powerManager, never()).wakeUp(anyLong())
+        verify(powerManager, never()).goToSleep(anyLong())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
index 4ebf974..a12315b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
@@ -50,10 +50,10 @@
 
     @Test
     fun testChange_alertsListener() {
-        val flag = ReleasedFlag(1, "1", "test")
+        val flag = ReleasedFlag(1, "flag_1", "test")
         serverFlagReader.listenForChanges(listOf(flag), changeListener)
 
-        deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false)
+        deviceConfig.setProperty(NAMESPACE, "flag_1", "1", false)
         executor.runAllReady()
 
         verify(changeListener).onChange(flag)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 4415033..15a454b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -172,6 +173,7 @@
                         repository = FakeKeyguardRepository(),
                         commandQueue = commandQueue,
                         featureFlags = featureFlags,
+                        bouncerRepository = FakeKeyguardBouncerRepository(),
                     ),
                 registry = mock(),
                 lockPatternUtils = lockPatternUtils,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
new file mode 100644
index 0000000..7c604f7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
@@ -0,0 +1,428 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.app.StatusBarManager.SESSION_KEYGUARD
+import android.content.pm.UserInfo
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
+import android.hardware.biometrics.ComponentInfoInternal
+import android.hardware.face.FaceManager
+import android.hardware.face.FaceSensorProperties
+import android.hardware.face.FaceSensorPropertiesInternal
+import android.os.CancellationSignal
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId.fakeInstanceId
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.FaceAuthUiEvent
+import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.FlowValue
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.dump.logcatLogBuffer
+import com.android.systemui.keyguard.shared.model.AuthenticationStatus
+import com.android.systemui.keyguard.shared.model.DetectionStatus
+import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus
+import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus
+import com.android.systemui.log.FaceAuthenticationLogger
+import com.android.systemui.log.SessionTracker
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.isNull
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardFaceAuthManagerTest : SysuiTestCase() {
+    private lateinit var underTest: KeyguardFaceAuthManagerImpl
+
+    @Mock private lateinit var faceManager: FaceManager
+    @Mock private lateinit var bypassController: KeyguardBypassController
+    @Mock private lateinit var sessionTracker: SessionTracker
+    @Mock private lateinit var uiEventLogger: UiEventLogger
+    @Mock private lateinit var dumpManager: DumpManager
+
+    @Captor
+    private lateinit var authenticationCallback: ArgumentCaptor<FaceManager.AuthenticationCallback>
+    @Captor
+    private lateinit var detectionCallback: ArgumentCaptor<FaceManager.FaceDetectionCallback>
+    @Captor private lateinit var cancellationSignal: ArgumentCaptor<CancellationSignal>
+    @Captor
+    private lateinit var faceLockoutResetCallback: ArgumentCaptor<FaceManager.LockoutResetCallback>
+    private lateinit var testDispatcher: TestDispatcher
+
+    private lateinit var testScope: TestScope
+    private lateinit var fakeUserRepository: FakeUserRepository
+    private lateinit var authStatus: FlowValue<AuthenticationStatus?>
+    private lateinit var detectStatus: FlowValue<DetectionStatus?>
+    private lateinit var authRunning: FlowValue<Boolean?>
+    private lateinit var lockedOut: FlowValue<Boolean?>
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        fakeUserRepository = FakeUserRepository()
+        fakeUserRepository.setUserInfos(listOf(currentUser))
+        testDispatcher = StandardTestDispatcher()
+        testScope = TestScope(testDispatcher)
+        whenever(sessionTracker.getSessionId(SESSION_KEYGUARD)).thenReturn(keyguardSessionId)
+        whenever(bypassController.bypassEnabled).thenReturn(true)
+        underTest = createFaceAuthManagerImpl(faceManager)
+    }
+
+    private fun createFaceAuthManagerImpl(
+        fmOverride: FaceManager? = faceManager,
+        bypassControllerOverride: KeyguardBypassController? = bypassController
+    ) =
+        KeyguardFaceAuthManagerImpl(
+            mContext,
+            fmOverride,
+            fakeUserRepository,
+            bypassControllerOverride,
+            testScope.backgroundScope,
+            testDispatcher,
+            sessionTracker,
+            uiEventLogger,
+            FaceAuthenticationLogger(logcatLogBuffer("KeyguardFaceAuthManagerLog")),
+            dumpManager,
+        )
+
+    @Test
+    fun faceAuthRunsAndProvidesAuthStatusUpdates() =
+        testScope.runTest {
+            testSetup(this)
+
+            FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER.extraInfo = 10
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+            uiEventIsLogged(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+
+            assertThat(authRunning()).isTrue()
+
+            val successResult = successResult()
+            authenticationCallback.value.onAuthenticationSucceeded(successResult)
+
+            assertThat(authStatus()).isEqualTo(SuccessAuthenticationStatus(successResult))
+
+            assertThat(authRunning()).isFalse()
+        }
+
+    private fun uiEventIsLogged(faceAuthUiEvent: FaceAuthUiEvent) {
+        verify(uiEventLogger)
+            .logWithInstanceIdAndPosition(
+                faceAuthUiEvent,
+                0,
+                null,
+                keyguardSessionId,
+                faceAuthUiEvent.extraInfo
+            )
+    }
+
+    @Test
+    fun faceAuthDoesNotRunWhileItIsAlreadyRunning() =
+        testScope.runTest {
+            testSetup(this)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+            clearInvocations(faceManager)
+            clearInvocations(uiEventLogger)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            verifyNoMoreInteractions(faceManager)
+            verifyNoMoreInteractions(uiEventLogger)
+        }
+
+    @Test
+    fun faceLockoutStatusIsPropagated() =
+        testScope.runTest {
+            testSetup(this)
+            verify(faceManager).addLockoutResetCallback(faceLockoutResetCallback.capture())
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+
+            authenticationCallback.value.onAuthenticationError(
+                FACE_ERROR_LOCKOUT_PERMANENT,
+                "face locked out"
+            )
+
+            assertThat(lockedOut()).isTrue()
+
+            faceLockoutResetCallback.value.onLockoutReset(0)
+            assertThat(lockedOut()).isFalse()
+        }
+
+    @Test
+    fun faceDetectionSupportIsTheCorrectValue() =
+        testScope.runTest {
+            assertThat(createFaceAuthManagerImpl(fmOverride = null).isDetectionSupported).isFalse()
+
+            whenever(faceManager.sensorPropertiesInternal).thenReturn(null)
+            assertThat(createFaceAuthManagerImpl().isDetectionSupported).isFalse()
+
+            whenever(faceManager.sensorPropertiesInternal).thenReturn(listOf())
+            assertThat(createFaceAuthManagerImpl().isDetectionSupported).isFalse()
+
+            whenever(faceManager.sensorPropertiesInternal)
+                .thenReturn(listOf(createFaceSensorProperties(supportsFaceDetection = false)))
+            assertThat(createFaceAuthManagerImpl().isDetectionSupported).isFalse()
+
+            whenever(faceManager.sensorPropertiesInternal)
+                .thenReturn(
+                    listOf(
+                        createFaceSensorProperties(supportsFaceDetection = false),
+                        createFaceSensorProperties(supportsFaceDetection = true)
+                    )
+                )
+            assertThat(createFaceAuthManagerImpl().isDetectionSupported).isFalse()
+
+            whenever(faceManager.sensorPropertiesInternal)
+                .thenReturn(
+                    listOf(
+                        createFaceSensorProperties(supportsFaceDetection = true),
+                        createFaceSensorProperties(supportsFaceDetection = false)
+                    )
+                )
+            assertThat(createFaceAuthManagerImpl().isDetectionSupported).isTrue()
+        }
+
+    @Test
+    fun cancelStopsFaceAuthentication() =
+        testScope.runTest {
+            testSetup(this)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+
+            var wasAuthCancelled = false
+            cancellationSignal.value.setOnCancelListener { wasAuthCancelled = true }
+
+            underTest.cancel()
+            assertThat(wasAuthCancelled).isTrue()
+            assertThat(authRunning()).isFalse()
+        }
+
+    @Test
+    fun cancelInvokedWithoutFaceAuthRunningIsANoop() = testScope.runTest { underTest.cancel() }
+
+    @Test
+    fun faceDetectionRunsAndPropagatesDetectionStatus() =
+        testScope.runTest {
+            whenever(faceManager.sensorPropertiesInternal)
+                .thenReturn(listOf(createFaceSensorProperties(supportsFaceDetection = true)))
+            underTest = createFaceAuthManagerImpl()
+            testSetup(this)
+
+            underTest.detect()
+            faceDetectIsCalled()
+
+            detectionCallback.value.onFaceDetected(1, 1, true)
+
+            assertThat(detectStatus()).isEqualTo(DetectionStatus(1, 1, true))
+        }
+
+    @Test
+    fun faceDetectDoesNotRunIfDetectionIsNotSupported() =
+        testScope.runTest {
+            whenever(faceManager.sensorPropertiesInternal)
+                .thenReturn(listOf(createFaceSensorProperties(supportsFaceDetection = false)))
+            underTest = createFaceAuthManagerImpl()
+            testSetup(this)
+            clearInvocations(faceManager)
+
+            underTest.detect()
+
+            verify(faceManager, never()).detectFace(any(), any(), anyInt())
+        }
+
+    @Test
+    fun faceAuthShouldWaitAndRunIfTriggeredWhileCancelling() =
+        testScope.runTest {
+            testSetup(this)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+
+            // Enter cancelling state
+            underTest.cancel()
+            clearInvocations(faceManager)
+
+            // Auth is while cancelling.
+            underTest.authenticate(FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+            // Auth is not started
+            verifyNoMoreInteractions(faceManager)
+
+            // Auth is done cancelling.
+            authenticationCallback.value.onAuthenticationError(
+                FACE_ERROR_CANCELED,
+                "First auth attempt cancellation completed"
+            )
+            assertThat(authStatus())
+                .isEqualTo(
+                    ErrorAuthenticationStatus(
+                        FACE_ERROR_CANCELED,
+                        "First auth attempt cancellation completed"
+                    )
+                )
+
+            faceAuthenticateIsCalled()
+            uiEventIsLogged(FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+        }
+
+    @Test
+    fun faceAuthAutoCancelsAfterDefaultCancellationTimeout() =
+        testScope.runTest {
+            testSetup(this)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+
+            clearInvocations(faceManager)
+            underTest.cancel()
+            advanceTimeBy(KeyguardFaceAuthManagerImpl.DEFAULT_CANCEL_SIGNAL_TIMEOUT + 1)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+        }
+
+    @Test
+    fun faceHelpMessagesAreIgnoredBasedOnConfig() =
+        testScope.runTest {
+            overrideResource(
+                R.array.config_face_acquire_device_entry_ignorelist,
+                intArrayOf(10, 11)
+            )
+            underTest = createFaceAuthManagerImpl()
+            testSetup(this)
+
+            underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
+            faceAuthenticateIsCalled()
+
+            authenticationCallback.value.onAuthenticationHelp(9, "help msg")
+            authenticationCallback.value.onAuthenticationHelp(10, "Ignored help msg")
+            authenticationCallback.value.onAuthenticationHelp(11, "Ignored help msg")
+
+            assertThat(authStatus()).isEqualTo(HelpAuthenticationStatus(9, "help msg"))
+        }
+
+    @Test
+    fun dumpDoesNotErrorOutWhenFaceManagerOrBypassControllerIsNull() =
+        testScope.runTest {
+            fakeUserRepository.setSelectedUserInfo(currentUser)
+            underTest.dump(PrintWriter(StringWriter()), emptyArray())
+
+            underTest =
+                createFaceAuthManagerImpl(fmOverride = null, bypassControllerOverride = null)
+            fakeUserRepository.setSelectedUserInfo(currentUser)
+
+            underTest.dump(PrintWriter(StringWriter()), emptyArray())
+        }
+
+    private suspend fun testSetup(testScope: TestScope) {
+        with(testScope) {
+            authStatus = collectLastValue(underTest.authenticationStatus)
+            detectStatus = collectLastValue(underTest.detectionStatus)
+            authRunning = collectLastValue(underTest.isAuthRunning)
+            lockedOut = collectLastValue(underTest.isLockedOut)
+            fakeUserRepository.setSelectedUserInfo(currentUser)
+        }
+    }
+
+    private fun successResult() = FaceManager.AuthenticationResult(null, null, currentUserId, false)
+
+    private fun faceDetectIsCalled() {
+        verify(faceManager)
+            .detectFace(
+                cancellationSignal.capture(),
+                detectionCallback.capture(),
+                eq(currentUserId)
+            )
+    }
+
+    private fun faceAuthenticateIsCalled() {
+        verify(faceManager)
+            .authenticate(
+                isNull(),
+                cancellationSignal.capture(),
+                authenticationCallback.capture(),
+                isNull(),
+                eq(currentUserId),
+                eq(true)
+            )
+    }
+
+    private fun createFaceSensorProperties(
+        supportsFaceDetection: Boolean
+    ): FaceSensorPropertiesInternal {
+        val componentInfo =
+            listOf(
+                ComponentInfoInternal(
+                    "faceSensor" /* componentId */,
+                    "vendor/model/revision" /* hardwareVersion */,
+                    "1.01" /* firmwareVersion */,
+                    "00000001" /* serialNumber */,
+                    "" /* softwareVersion */
+                )
+            )
+        return FaceSensorPropertiesInternal(
+            0 /* id */,
+            FaceSensorProperties.STRENGTH_STRONG,
+            1 /* maxTemplatesAllowed */,
+            componentInfo,
+            FaceSensorProperties.TYPE_UNKNOWN,
+            supportsFaceDetection /* supportsFaceDetection */,
+            true /* supportsSelfIllumination */,
+            false /* resetLockoutRequiresChallenge */
+        )
+    }
+
+    companion object {
+        const val currentUserId = 1
+        val keyguardSessionId = fakeInstanceId(10)!!
+        val currentUser = UserInfo(currentUserId, "test user", 0)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 8bb6a85..0469e77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -324,29 +324,6 @@
         }
 
     @Test
-    fun isBouncerShowing() =
-        runTest(UnconfinedTestDispatcher()) {
-            whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
-            var latest: Boolean? = null
-            val job = underTest.isBouncerShowing.onEach { latest = it }.launchIn(this)
-
-            assertThat(latest).isFalse()
-
-            val captor = argumentCaptor<KeyguardStateController.Callback>()
-            verify(keyguardStateController).addCallback(captor.capture())
-
-            whenever(keyguardStateController.isBouncerShowing).thenReturn(true)
-            captor.value.onBouncerShowingChanged()
-            assertThat(latest).isTrue()
-
-            whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
-            captor.value.onBouncerShowingChanged()
-            assertThat(latest).isFalse()
-
-            job.cancel()
-        }
-
-    @Test
     fun isKeyguardGoingAway() =
         runTest(UnconfinedTestDispatcher()) {
             whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index 7ded354..18e80ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -130,7 +130,7 @@
         givenCanShowAlternateBouncer()
 
         assertTrue(underTest.show())
-        assertTrue(bouncerRepository.isAlternateBouncerVisible.value)
+        assertTrue(bouncerRepository.alternateBouncerVisible.value)
     }
 
     @Test
@@ -138,7 +138,7 @@
         givenCannotShowAlternateBouncer()
 
         assertFalse(underTest.show())
-        assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
     }
 
     @Test
@@ -146,7 +146,7 @@
         bouncerRepository.setAlternateVisible(true)
 
         assertTrue(underTest.hide())
-        assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
     }
 
     @Test
@@ -154,7 +154,7 @@
         bouncerRepository.setAlternateVisible(false)
 
         assertFalse(underTest.hide())
-        assertFalse(bouncerRepository.isAlternateBouncerVisible.value)
+        assertFalse(bouncerRepository.alternateBouncerVisible.value)
     }
 
     private fun givenCanShowAlternateBouncer() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 7d4861b..153439e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
 import com.android.systemui.settings.DisplayTracker
@@ -38,7 +39,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
-import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -50,6 +50,7 @@
 
     private lateinit var underTest: KeyguardInteractor
     private lateinit var repository: FakeKeyguardRepository
+    private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
 
     @Before
     fun setUp() {
@@ -58,7 +59,14 @@
         commandQueue = FakeCommandQueue(mock(Context::class.java), mock(DisplayTracker::class.java))
         testScope = TestScope()
         repository = FakeKeyguardRepository()
-        underTest = KeyguardInteractor(repository, commandQueue, featureFlags)
+        bouncerRepository = FakeKeyguardBouncerRepository()
+        underTest =
+            KeyguardInteractor(
+                repository,
+                commandQueue,
+                featureFlags,
+                bouncerRepository,
+            )
     }
 
     @Test
@@ -137,7 +145,7 @@
             repository.setKeyguardOccluded(true)
             assertThat(secureCameraActive()).isTrue()
 
-            repository.setBouncerShowing(true)
+            bouncerRepository.setPrimaryVisible(true)
             assertThat(secureCameraActive()).isFalse()
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 240af7b..23e06ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
@@ -298,6 +299,7 @@
                         repository = FakeKeyguardRepository(),
                         commandQueue = commandQueue,
                         featureFlags = featureFlags,
+                        bouncerRepository = FakeKeyguardBouncerRepository(),
                     ),
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index ec70857..1b8c627 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
@@ -159,7 +160,8 @@
                     KeyguardInteractor(
                         repository = repository,
                         commandQueue = commandQueue,
-                        featureFlags = featureFlags
+                        featureFlags = featureFlags,
+                        bouncerRepository = FakeKeyguardBouncerRepository(),
                     ),
                 registry =
                     FakeKeyguardQuickAffordanceRegistry(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 46e4679..ae7a928 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -22,7 +22,9 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositoryImpl
@@ -65,6 +67,7 @@
     private lateinit var testScope: TestScope
 
     private lateinit var keyguardRepository: FakeKeyguardRepository
+    private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
     private lateinit var shadeRepository: ShadeRepository
 
     // Used to issue real transition steps for test input
@@ -81,6 +84,10 @@
     private lateinit var fromOccludedTransitionInteractor: FromOccludedTransitionInteractor
     private lateinit var fromGoneTransitionInteractor: FromGoneTransitionInteractor
     private lateinit var fromAodTransitionInteractor: FromAodTransitionInteractor
+    private lateinit var fromAlternateBouncerTransitionInteractor:
+        FromAlternateBouncerTransitionInteractor
+    private lateinit var fromPrimaryBouncerTransitionInteractor:
+        FromPrimaryBouncerTransitionInteractor
 
     @Before
     fun setUp() {
@@ -88,6 +95,7 @@
         testScope = TestScope()
 
         keyguardRepository = FakeKeyguardRepository()
+        bouncerRepository = FakeKeyguardBouncerRepository()
         shadeRepository = FakeShadeRepository()
 
         /* Used to issue full transition steps, to better simulate a real device */
@@ -98,8 +106,7 @@
         fromLockscreenTransitionInteractor =
             FromLockscreenTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 shadeRepository = shadeRepository,
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
@@ -109,8 +116,7 @@
         fromDreamingTransitionInteractor =
             FromDreamingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -119,8 +125,7 @@
         fromAodTransitionInteractor =
             FromAodTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -129,8 +134,7 @@
         fromGoneTransitionInteractor =
             FromGoneTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -139,8 +143,7 @@
         fromDozingTransitionInteractor =
             FromDozingTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
@@ -149,12 +152,29 @@
         fromOccludedTransitionInteractor =
             FromOccludedTransitionInteractor(
                 scope = testScope,
-                keyguardInteractor =
-                    KeyguardInteractor(keyguardRepository, commandQueue, featureFlags),
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
             )
         fromOccludedTransitionInteractor.start()
+
+        fromAlternateBouncerTransitionInteractor =
+            FromAlternateBouncerTransitionInteractor(
+                scope = testScope,
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardTransitionRepository = mockTransitionRepository,
+                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+            )
+        fromAlternateBouncerTransitionInteractor.start()
+
+        fromPrimaryBouncerTransitionInteractor =
+            FromPrimaryBouncerTransitionInteractor(
+                scope = testScope,
+                keyguardInteractor = createKeyguardInteractor(featureFlags),
+                keyguardTransitionRepository = mockTransitionRepository,
+                keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+            )
+        fromPrimaryBouncerTransitionInteractor.start()
     }
 
     @Test
@@ -256,7 +276,7 @@
         }
 
     @Test
-    fun `LOCKSCREEN to BOUNCER via bouncer showing call`() =
+    fun `LOCKSCREEN to PRIMARY_BOUNCER via bouncer showing call`() =
         testScope.runTest {
             // GIVEN a device that has at least woken up
             keyguardRepository.setWakefulnessModel(startingToWake())
@@ -278,18 +298,18 @@
             )
             runCurrent()
 
-            // WHEN the bouncer is set to show
-            keyguardRepository.setBouncerShowing(true)
+            // WHEN the primary bouncer is set to show
+            bouncerRepository.setPrimaryVisible(true)
             runCurrent()
 
             val info =
                 withArgCaptor<TransitionInfo> {
                     verify(mockTransitionRepository).startTransition(capture())
                 }
-            // THEN a transition to BOUNCER should occur
+            // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
             assertThat(info.from).isEqualTo(KeyguardState.LOCKSCREEN)
-            assertThat(info.to).isEqualTo(KeyguardState.BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
             assertThat(info.animator).isNotNull()
 
             coroutineContext.cancelChildren()
@@ -695,6 +715,297 @@
             coroutineContext.cancelChildren()
         }
 
+    @Test
+    fun `ALTERNATE_BOUNCER to PRIMARY_BOUNCER`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.ALTERNATE_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // WHEN the alternateBouncer stops showing and then the primary bouncer shows
+            bouncerRepository.setPrimaryVisible(true)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to PRIMARY_BOUNCER should occur
+            assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `ALTERNATE_BOUNCER to AOD`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+            bouncerRepository.setAlternateVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.ALTERNATE_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN the primary bouncer isn't showing, aod available and starting to sleep
+            bouncerRepository.setPrimaryVisible(false)
+            keyguardRepository.setAodAvailable(true)
+            keyguardRepository.setWakefulnessModel(startingToSleep())
+
+            // WHEN the alternateBouncer stops showing
+            bouncerRepository.setAlternateVisible(false)
+            advanceUntilIdle()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to AOD should occur
+            assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.AOD)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `ALTERNATE_BOUNCER to DOZING`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+            bouncerRepository.setAlternateVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.ALTERNATE_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN the primary bouncer isn't showing, aod not available and starting to sleep
+            // to sleep
+            bouncerRepository.setPrimaryVisible(false)
+            keyguardRepository.setAodAvailable(false)
+            keyguardRepository.setWakefulnessModel(startingToSleep())
+
+            // WHEN the alternateBouncer stops showing
+            bouncerRepository.setAlternateVisible(false)
+            advanceUntilIdle()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to DOZING should occur
+            assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.DOZING)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `ALTERNATE_BOUNCER to LOCKSCREEN`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+            bouncerRepository.setAlternateVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.ALTERNATE_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN the primary bouncer isn't showing and device not sleeping
+            bouncerRepository.setPrimaryVisible(false)
+            keyguardRepository.setWakefulnessModel(startingToWake())
+
+            // WHEN the alternateBouncer stops showing
+            bouncerRepository.setAlternateVisible(false)
+            advanceUntilIdle()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to LOCKSCREEN should occur
+            assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `PRIMARY_BOUNCER to AOD`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to PRIMARY_BOUNCER
+            bouncerRepository.setPrimaryVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN aod available and starting to sleep
+            keyguardRepository.setAodAvailable(true)
+            keyguardRepository.setWakefulnessModel(startingToSleep())
+
+            // WHEN the primaryBouncer stops showing
+            bouncerRepository.setPrimaryVisible(false)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to AOD should occur
+            assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.AOD)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `PRIMARY_BOUNCER to DOZING`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to PRIMARY_BOUNCER
+            bouncerRepository.setPrimaryVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN aod not available and starting to sleep to sleep
+            keyguardRepository.setAodAvailable(false)
+            keyguardRepository.setWakefulnessModel(startingToSleep())
+
+            // WHEN the primaryBouncer stops showing
+            bouncerRepository.setPrimaryVisible(false)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to DOZING should occur
+            assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.DOZING)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
+    @Test
+    fun `PRIMARY_BOUNCER to LOCKSCREEN`() =
+        testScope.runTest {
+            // GIVEN a prior transition has run to PRIMARY_BOUNCER
+            bouncerRepository.setPrimaryVisible(true)
+            runner.startTransition(
+                testScope,
+                TransitionInfo(
+                    ownerName = "",
+                    from = KeyguardState.LOCKSCREEN,
+                    to = KeyguardState.PRIMARY_BOUNCER,
+                    animator =
+                        ValueAnimator().apply {
+                            duration = 10
+                            interpolator = Interpolators.LINEAR
+                        },
+                )
+            )
+            runCurrent()
+            reset(mockTransitionRepository)
+
+            // GIVEN device not sleeping
+            keyguardRepository.setWakefulnessModel(startingToWake())
+
+            // WHEN the alternateBouncer stops showing
+            bouncerRepository.setPrimaryVisible(false)
+            runCurrent()
+
+            val info =
+                withArgCaptor<TransitionInfo> {
+                    verify(mockTransitionRepository).startTransition(capture())
+                }
+            // THEN a transition to LOCKSCREEN should occur
+            assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
+            assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER)
+            assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
+            assertThat(info.animator).isNotNull()
+
+            coroutineContext.cancelChildren()
+        }
+
     private fun startingToWake() =
         WakefulnessModel(
             WakefulnessState.STARTING_TO_WAKE,
@@ -710,4 +1021,13 @@
             WakeSleepReason.OTHER,
             WakeSleepReason.OTHER
         )
+
+    private fun createKeyguardInteractor(featureFlags: FeatureFlags): KeyguardInteractor {
+        return KeyguardInteractor(
+            keyguardRepository,
+            commandQueue,
+            featureFlags,
+            bouncerRepository,
+        )
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index c5e0252..46ed829 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -102,7 +102,7 @@
         verify(repository).setPrimaryScrimmed(true)
         verify(repository).setPanelExpansion(EXPANSION_VISIBLE)
         verify(repository).setPrimaryShowingSoon(true)
-        verify(keyguardStateController).notifyBouncerShowing(true)
+        verify(keyguardStateController).notifyPrimaryBouncerShowing(true)
         verify(mPrimaryBouncerCallbackInteractor).dispatchStartingToShow()
         verify(repository).setPrimaryVisible(true)
         verify(repository).setPrimaryShow(any(KeyguardBouncerModel::class.java))
@@ -118,7 +118,7 @@
     @Test
     fun testShow_keyguardIsDone() {
         `when`(bouncerView.delegate?.showNextSecurityScreenOrFinish()).thenReturn(true)
-        verify(keyguardStateController, never()).notifyBouncerShowing(true)
+        verify(keyguardStateController, never()).notifyPrimaryBouncerShowing(true)
         verify(mPrimaryBouncerCallbackInteractor, never()).dispatchStartingToShow()
     }
 
@@ -126,7 +126,7 @@
     fun testHide() {
         underTest.hide()
         verify(falsingCollector).onBouncerHidden()
-        verify(keyguardStateController).notifyBouncerShowing(false)
+        verify(keyguardStateController).notifyPrimaryBouncerShowing(false)
         verify(repository).setPrimaryShowingSoon(false)
         verify(repository).setPrimaryVisible(false)
         verify(repository).setPrimaryHide(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
index 03a347e..6afeddd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
@@ -136,6 +137,7 @@
                 repository = repository,
                 commandQueue = commandQueue,
                 featureFlags = featureFlags,
+                bouncerRepository = FakeKeyguardBouncerRepository(),
             )
         whenever(userTracker.userHandle).thenReturn(mock())
         whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/FontScalingTileTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 57abae0..528978a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.systemui.qs.tiles.dialog
+package com.android.systemui.qs.tiles
 
 import android.os.Handler
 import android.testing.AndroidTestingRunner
@@ -27,7 +27,6 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.qs.QSTileHost
 import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.qs.tiles.FontScalingTile
 import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
index 020a866..3fd19ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
@@ -30,12 +30,14 @@
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.nio.file.Files
 import java.util.concurrent.Executor
-import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.atLeastOnce
 import org.mockito.Mockito.isNull
 import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
@@ -61,36 +63,83 @@
             UserFileManagerImpl(context, userManager, broadcastDispatcher, backgroundExecutor)
     }
 
-    @After
-    fun end() {
-        val dir = Environment.buildPath(context.filesDir, UserFileManagerImpl.ID)
-        dir.deleteRecursively()
-    }
-
     @Test
     fun testGetFile() {
         assertThat(userFileManager.getFile(TEST_FILE_NAME, 0).path)
             .isEqualTo("${context.filesDir}/$TEST_FILE_NAME")
         assertThat(userFileManager.getFile(TEST_FILE_NAME, 11).path)
-            .isEqualTo("${context.filesDir}/${UserFileManagerImpl.ID}/11/files/$TEST_FILE_NAME")
+            .isEqualTo("${context.filesDir}/__USER_11_$TEST_FILE_NAME")
     }
 
     @Test
     fun testGetSharedPreferences() {
+        val primarySharedPref = userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 0)
         val secondarySharedPref = userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 11)
-        val secondaryUserDir =
-            Environment.buildPath(
-                context.filesDir,
-                UserFileManagerImpl.ID,
-                "11",
-                UserFileManagerImpl.SHARED_PREFS,
-                TEST_FILE_NAME
-            )
 
-        assertThat(secondarySharedPref).isNotNull()
-        assertThat(secondaryUserDir.exists())
-        assertThat(userFileManager.getSharedPreferences(TEST_FILE_NAME, 0, 0))
-            .isNotEqualTo(secondarySharedPref)
+        assertThat(primarySharedPref).isNotEqualTo(secondarySharedPref)
+
+        // Make sure these are different files
+        primarySharedPref.edit().putString("TEST", "ABC").commit()
+        assertThat(secondarySharedPref.getString("TEST", null)).isNull()
+
+        context.deleteSharedPreferences("TEST")
+        context.deleteSharedPreferences("__USER_11_TEST")
+    }
+
+    @Test
+    fun testMigrateFile() {
+        val userId = 12
+        val fileName = "myFile.txt"
+        val fileContents = "TestingFile"
+        val legacyFile =
+            UserFileManagerImpl.createLegacyFile(
+                context,
+                UserFileManagerImpl.FILES,
+                fileName,
+                userId
+            )!!
+
+        // Write file to legacy area
+        Files.createDirectories(legacyFile.getParentFile().toPath())
+        Files.write(legacyFile.toPath(), fileContents.toByteArray())
+        assertThat(legacyFile.exists()).isTrue()
+
+        // getFile() should migrate the legacy file to the new location
+        val file = userFileManager.getFile(fileName, userId)
+        val newContents = String(Files.readAllBytes(file.toPath()))
+
+        assertThat(newContents).isEqualTo(fileContents)
+        assertThat(legacyFile.exists()).isFalse()
+        assertThat(File(context.filesDir, UserFileManagerImpl.ROOT_DIR).exists()).isFalse()
+    }
+
+    @Test
+    fun testMigrateSharedPrefs() {
+        val userId = 13
+        val fileName = "myFile"
+        val contents = "TestingSharedPrefs"
+        val legacyFile =
+            UserFileManagerImpl.createLegacyFile(
+                context,
+                UserFileManagerImpl.SHARED_PREFS,
+                "$fileName.xml",
+                userId
+            )!!
+
+        // Write a valid shared prefs xml file to legacy area
+        val tmpPrefs = context.getSharedPreferences("tmp", Context.MODE_PRIVATE)
+        tmpPrefs.edit().putString(contents, contents).commit()
+        Files.createDirectories(legacyFile.getParentFile().toPath())
+        val tmpFile =
+            Environment.buildPath(context.dataDir, UserFileManagerImpl.SHARED_PREFS, "tmp.xml")
+        tmpFile.renameTo(legacyFile)
+        assertThat(legacyFile.exists()).isTrue()
+
+        // getSharedpreferences() should migrate the legacy file to the new location
+        val prefs = userFileManager.getSharedPreferences(fileName, Context.MODE_PRIVATE, userId)
+        assertThat(prefs.getString(contents, "")).isEqualTo(contents)
+        assertThat(legacyFile.exists()).isFalse()
+        assertThat(File(context.filesDir, UserFileManagerImpl.ROOT_DIR).exists()).isFalse()
     }
 
     @Test
@@ -111,44 +160,14 @@
 
     @Test
     fun testClearDeletedUserData() {
-        val dir = Environment.buildPath(context.filesDir, UserFileManagerImpl.ID, "11", "files")
-        dir.mkdirs()
-        val file =
-            Environment.buildPath(
-                context.filesDir,
-                UserFileManagerImpl.ID,
-                "11",
-                "files",
-                TEST_FILE_NAME
-            )
-        val secondaryUserDir =
-            Environment.buildPath(
-                context.filesDir,
-                UserFileManagerImpl.ID,
-                "11",
-            )
+        val file = userFileManager.getFile(TEST_FILE_NAME, 11)
         file.createNewFile()
-        assertThat(secondaryUserDir.exists()).isTrue()
+
         assertThat(file.exists()).isTrue()
         userFileManager.clearDeletedUserData()
         assertThat(backgroundExecutor.runAllReady()).isGreaterThan(0)
-        verify(userManager).aliveUsers
-        assertThat(secondaryUserDir.exists()).isFalse()
-        assertThat(file.exists()).isFalse()
-    }
+        verify(userManager, atLeastOnce()).aliveUsers
 
-    @Test
-    fun testEnsureParentDirExists() {
-        val file =
-            Environment.buildPath(
-                context.filesDir,
-                UserFileManagerImpl.ID,
-                "11",
-                "files",
-                TEST_FILE_NAME
-            )
-        assertThat(file.parentFile.exists()).isFalse()
-        UserFileManagerImpl.ensureParentDirExists(file)
-        assertThat(file.parentFile.exists()).isTrue()
+        assertThat(file.exists()).isFalse()
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index e5d5e3b..d229a08 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -21,7 +21,7 @@
 import android.view.MotionEvent
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardHostViewController
+import com.android.keyguard.KeyguardSecurityContainerController
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
 import com.android.systemui.R
@@ -106,7 +106,7 @@
     private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
-    @Mock lateinit var keyguardHostViewController: KeyguardHostViewController
+    @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
 
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
@@ -122,8 +122,8 @@
                 .thenReturn(mock(ViewGroup::class.java))
         whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
                 .thenReturn(keyguardBouncerComponent)
-        whenever(keyguardBouncerComponent.keyguardHostViewController)
-                .thenReturn(keyguardHostViewController)
+        whenever(keyguardBouncerComponent.securityContainerController)
+                .thenReturn(keyguardSecurityContainerController)
         underTest = NotificationShadeWindowViewController(
             lockscreenShadeTransitionController,
             FalsingCollectorFake(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5cc3ef1..5e9c219 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -33,7 +33,7 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.keyguard.KeyguardHostViewController;
+import com.android.keyguard.KeyguardSecurityContainerController;
 import com.android.keyguard.LockIconViewController;
 import com.android.keyguard.dagger.KeyguardBouncerComponent;
 import com.android.systemui.R;
@@ -97,7 +97,7 @@
     @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
     @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
     @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
-    @Mock private KeyguardHostViewController mKeyguardHostViewController;
+    @Mock private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
     @Mock private NotificationInsetsController mNotificationInsetsController;
     @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
     @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
@@ -117,8 +117,8 @@
         when(mView.findViewById(R.id.keyguard_bouncer_container)).thenReturn(mock(ViewGroup.class));
         when(mKeyguardBouncerComponentFactory.create(any(ViewGroup.class))).thenReturn(
                 mKeyguardBouncerComponent);
-        when(mKeyguardBouncerComponent.getKeyguardHostViewController()).thenReturn(
-                mKeyguardHostViewController);
+        when(mKeyguardBouncerComponent.getSecurityContainerController()).thenReturn(
+                mKeyguardSecurityContainerController);
 
         when(mStatusBarStateController.isDozing()).thenReturn(false);
         mDependency.injectTestDependency(ShadeController.class, mShadeController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index d01edcc..26eff61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -230,7 +230,7 @@
     }
 
     @Test
-    fun pluginRemoved_clockChanged() {
+    fun pluginRemoved_clockAndListChanged() {
         val plugin1 = FakeClockPlugin()
             .addClock("clock_1", "clock 1")
             .addClock("clock_2", "clock 2")
@@ -239,20 +239,36 @@
             .addClock("clock_3", "clock 3", { mockClock })
             .addClock("clock_4", "clock 4")
 
-        registry.applySettings(ClockSettings("clock_3", null))
-        pluginListener.onPluginConnected(plugin1, mockContext)
-        pluginListener.onPluginConnected(plugin2, mockContext)
 
         var changeCallCount = 0
-        registry.registerClockChangeListener { changeCallCount++ }
+        var listChangeCallCount = 0
+        registry.registerClockChangeListener(object : ClockRegistry.ClockChangeListener {
+            override fun onCurrentClockChanged() { changeCallCount++ }
+            override fun onAvailableClocksChanged() { listChangeCallCount++ }
+        })
+
+        registry.applySettings(ClockSettings("clock_3", null))
+        assertEquals(0, changeCallCount)
+        assertEquals(0, listChangeCallCount)
+
+        pluginListener.onPluginConnected(plugin1, mockContext)
+        assertEquals(0, changeCallCount)
+        assertEquals(1, listChangeCallCount)
+
+        pluginListener.onPluginConnected(plugin2, mockContext)
+        assertEquals(1, changeCallCount)
+        assertEquals(2, listChangeCallCount)
 
         pluginListener.onPluginDisconnected(plugin1)
-        assertEquals(0, changeCallCount)
+        assertEquals(1, changeCallCount)
+        assertEquals(3, listChangeCallCount)
 
         pluginListener.onPluginDisconnected(plugin2)
-        assertEquals(1, changeCallCount)
+        assertEquals(2, changeCallCount)
+        assertEquals(4, listChangeCallCount)
     }
 
+
     @Test
     fun jsonDeserialization_gotExpectedObject() {
         val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index c6207e5..413767a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -17,6 +17,8 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
+
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
 
 import static junit.framework.Assert.assertFalse;
@@ -28,6 +30,7 @@
 
 import android.app.ActivityManager;
 import android.app.Notification;
+import android.app.PendingIntent;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -42,6 +45,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.HeadsUpManagerLogger;
 
 import org.junit.After;
@@ -64,6 +68,7 @@
     private static final int TEST_UID = 0;
 
     protected static final int TEST_MINIMUM_DISPLAY_TIME = 200;
+    protected static final int TEST_STICKY_DISPLAY_TIME = 1000;
     protected static final int TEST_AUTO_DISMISS_TIME = 500;
     // Number of notifications to use in tests requiring multiple notifications
     private static final int TEST_NUM_NOTIFICATIONS = 4;
@@ -85,6 +90,7 @@
         private TestableAlertingNotificationManager(Handler handler) {
             super(mock(HeadsUpManagerLogger.class), handler);
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
+            mStickyDisplayTime = TEST_STICKY_DISPLAY_TIME;
             mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
         }
 
@@ -110,6 +116,20 @@
         return new TestableAlertingNotificationManager(handler);
     }
 
+    protected StatusBarNotification createNewSbn(int id, Notification n) {
+        return new StatusBarNotification(
+                TEST_PACKAGE_NAME /* pkg */,
+                TEST_PACKAGE_NAME,
+                id,
+                null /* tag */,
+                TEST_UID,
+                0 /* initialPid */,
+                n,
+                new UserHandle(ActivityManager.getCurrentUser()),
+                null /* overrideGroupKey */,
+                0 /* postTime */);
+    }
+
     protected StatusBarNotification createNewSbn(int id, Notification.Builder n) {
         return new StatusBarNotification(
                 TEST_PACKAGE_NAME /* pkg */,
@@ -132,6 +152,15 @@
         return createNewSbn(id, n);
     }
 
+    protected StatusBarNotification createStickySbn(int id) {
+        Notification stickyHun = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setFullScreenIntent(mock(PendingIntent.class), /* highPriority */ true)
+                .build();
+        stickyHun.flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
+        return createNewSbn(id, stickyHun);
+    }
+
     @Before
     public void setUp() {
         mTestHandler = Handler.createAsync(Looper.myLooper());
@@ -171,6 +200,20 @@
     }
 
     @Test
+    public void testShowNotification_stickyHun_earliestRemovalTime() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createStickySbn(/* id= */ 0))
+                .build();
+        notifEntry.setCreationElapsedRealTime(0);
+
+        mAlertingNotificationManager.showNotification(notifEntry);
+
+        final long earliestRemovalTime = mAlertingNotificationManager
+                .getCalculatedEarliestRemovalTime(notifEntry.getKey());
+        assertEquals(TEST_STICKY_DISPLAY_TIME, earliestRemovalTime);
+    }
+
+    @Test
     public void testRemoveNotification_removeDeferred() {
         mAlertingNotificationManager.showNotification(mEntry);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index d4add75..90f6201 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -21,6 +21,7 @@
 import static android.app.Notification.CATEGORY_EVENT;
 import static android.app.Notification.CATEGORY_MESSAGE;
 import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
 
 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
@@ -249,6 +250,36 @@
     }
 
     @Test
+    public void testIsStickyAndNotDemoted_noFlagAndDemoted_returnFalse() {
+        mEntry.getSbn().getNotification().flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
+        assertFalse(mEntry.isStickyAndNotDemoted());
+    }
+
+    @Test
+    public void testIsStickyAndNotDemoted_noFlagAndNotDemoted_demoteAndReturnFalse() {
+        mEntry.getSbn().getNotification().flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
+
+        assertFalse(mEntry.isStickyAndNotDemoted());
+        assertTrue(mEntry.isDemoted());
+    }
+
+    @Test
+    public void testIsStickyAndNotDemoted_hasFlagButAlreadyDemoted_returnFalse() {
+        mEntry.getSbn().getNotification().flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
+        mEntry.demoteStickyHun();
+
+        assertFalse(mEntry.isStickyAndNotDemoted());
+    }
+
+    @Test
+    public void testIsStickyAndNotDemoted_hasFlagAndNotDemoted_returnTrue() {
+        mEntry.getSbn().getNotification().flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
+
+        assertFalse(mEntry.isDemoted());
+        assertTrue(mEntry.isStickyAndNotDemoted());
+    }
+
+    @Test
     public void notificationDataEntry_testIsLastMessageFromReply() {
         Person.Builder person = new Person.Builder()
                 .setName("name")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 5832569..4d9db8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -518,7 +518,7 @@
         val childHunView = createHunViewMock(
                 isShadeOpen = true,
                 fullyVisible = false,
-                headerVisibleAmount = 1f,
+                headerVisibleAmount = 1f
         )
         val algorithmState = StackScrollAlgorithm.StackScrollAlgorithmState()
         algorithmState.visibleChildren.add(childHunView)
@@ -526,6 +526,7 @@
         // When: updateChildZValue() is called for the top HUN
         stackScrollAlgorithm.updateChildZValue(
                 /* i= */ 0,
+                /* childrenOnTop= */ 0.0f,
                 /* StackScrollAlgorithmState= */ algorithmState,
                 /* ambientState= */ ambientState,
                 /* shouldElevateHun= */ true
@@ -545,7 +546,7 @@
         val childHunView = createHunViewMock(
                 isShadeOpen = true,
                 fullyVisible = false,
-                headerVisibleAmount = 1f,
+                headerVisibleAmount = 1f
         )
         // Use half of the HUN's height as overlap
         childHunView.viewState.yTranslation = (childHunView.viewState.height + 1 shr 1).toFloat()
@@ -555,6 +556,7 @@
         // When: updateChildZValue() is called for the top HUN
         stackScrollAlgorithm.updateChildZValue(
                 /* i= */ 0,
+                /* childrenOnTop= */ 0.0f,
                 /* StackScrollAlgorithmState= */ algorithmState,
                 /* ambientState= */ ambientState,
                 /* shouldElevateHun= */ true
@@ -578,7 +580,7 @@
         val childHunView = createHunViewMock(
                 isShadeOpen = true,
                 fullyVisible = true,
-                headerVisibleAmount = 1f,
+                headerVisibleAmount = 1f
         )
         // HUN doesn't overlap with QQS Panel
         childHunView.viewState.yTranslation = ambientState.topPadding +
@@ -589,6 +591,7 @@
         // When: updateChildZValue() is called for the top HUN
         stackScrollAlgorithm.updateChildZValue(
                 /* i= */ 0,
+                /* childrenOnTop= */ 0.0f,
                 /* StackScrollAlgorithmState= */ algorithmState,
                 /* ambientState= */ ambientState,
                 /* shouldElevateHun= */ true
@@ -608,7 +611,7 @@
         val childHunView = createHunViewMock(
                 isShadeOpen = false,
                 fullyVisible = false,
-                headerVisibleAmount = 0f,
+                headerVisibleAmount = 0f
         )
         childHunView.viewState.yTranslation = 0f
         // Shade is closed, thus childHunView's headerVisibleAmount is 0
@@ -619,6 +622,7 @@
         // When: updateChildZValue() is called for the top HUN
         stackScrollAlgorithm.updateChildZValue(
                 /* i= */ 0,
+                /* childrenOnTop= */ 0.0f,
                 /* StackScrollAlgorithmState= */ algorithmState,
                 /* ambientState= */ ambientState,
                 /* shouldElevateHun= */ true
@@ -638,7 +642,7 @@
         val childHunView = createHunViewMock(
                 isShadeOpen = false,
                 fullyVisible = false,
-                headerVisibleAmount = 0.5f,
+                headerVisibleAmount = 0.5f
         )
         childHunView.viewState.yTranslation = 0f
         // Shade is being opened, thus childHunView's headerVisibleAmount is between 0 and 1
@@ -650,6 +654,7 @@
         // When: updateChildZValue() is called for the top HUN
         stackScrollAlgorithm.updateChildZValue(
                 /* i= */ 0,
+                /* childrenOnTop= */ 0.0f,
                 /* StackScrollAlgorithmState= */ algorithmState,
                 /* ambientState= */ ambientState,
                 /* shouldElevateHun= */ true
@@ -664,7 +669,7 @@
     private fun createHunViewMock(
             isShadeOpen: Boolean,
             fullyVisible: Boolean,
-            headerVisibleAmount: Float,
+            headerVisibleAmount: Float
     ) =
             mock<ExpandableNotificationRow>().apply {
                 val childViewStateMock = createHunChildViewState(isShadeOpen, fullyVisible)
@@ -675,10 +680,7 @@
             }
 
 
-    private fun createHunChildViewState(
-            isShadeOpen: Boolean,
-            fullyVisible: Boolean,
-    ) =
+    private fun createHunChildViewState(isShadeOpen: Boolean, fullyVisible: Boolean) =
             ExpandableViewState().apply {
                 // Mock the HUN's height with ambientState.topPadding +
                 // ambientState.stackTranslation
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java
index a986777..c669c6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FakeKeyguardStateController.java
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public boolean isBouncerShowing() {
+    public boolean isPrimaryBouncerShowing() {
         return false;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index ccc57ad..ee7e082 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -18,6 +18,9 @@
 
 import static android.service.notification.NotificationListenerService.REASON_CLICK;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
 import static org.mockito.AdditionalAnswers.answerVoid;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -28,7 +31,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
@@ -38,6 +40,8 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -51,6 +55,7 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ActivityIntentHelper;
 import com.android.systemui.SysuiTestCase;
@@ -90,9 +95,12 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
@@ -398,4 +406,40 @@
         // THEN display should try wake up for the full screen intent
         verify(mCentralSurfaces).wakeUpForFullScreenIntent();
     }
+
+    @Test
+    public void testOnFullScreenIntentWhenDozing_logToStatsd() {
+        final int kTestUid = 12345;
+        final String kTestActivityName = "TestActivity";
+        // GIVEN entry that can has a full screen intent that can show
+        PendingIntent mockFullScreenIntent = mock(PendingIntent.class);
+        when(mockFullScreenIntent.getCreatorUid()).thenReturn(kTestUid);
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.name = kTestActivityName;
+        when(mockFullScreenIntent.queryIntentComponents(anyInt()))
+                .thenReturn(Arrays.asList(resolveInfo));
+        Notification.Builder nb = new Notification.Builder(mContext, "a")
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setFullScreenIntent(mockFullScreenIntent, true);
+        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0,
+                "tag" + System.currentTimeMillis(), 0, 0,
+                nb.build(), new UserHandle(0), null, 0);
+        NotificationEntry entry = mock(NotificationEntry.class);
+        when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
+        when(entry.getSbn()).thenReturn(sbn);
+        MockitoSession mockingSession = mockitoSession()
+                .mockStatic(FrameworkStatsLog.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+
+        // WHEN
+        mNotificationActivityStarter.launchFullScreenIntent(entry);
+
+        // THEN the full screen intent should be logged to statsd.
+        verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.FULL_SCREEN_INTENT_LAUNCHED,
+                kTestUid, kTestActivityName));
+        mockingSession.finishMocking();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
index 5a6bb30..ab888f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
@@ -18,9 +18,9 @@
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.google.common.truth.Truth.assertThat
@@ -42,7 +42,7 @@
 
     private lateinit var underTest: AirplaneModeViewModelImpl
 
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: TableLogBuffer
     private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
     private lateinit var connectivityRepository: FakeConnectivityRepository
     private lateinit var interactor: AirplaneModeInteractor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
index 521c67f..0145103 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -53,7 +53,7 @@
     private lateinit var mockitoSession: MockitoSession
     private lateinit var carrierConfigCoreStartable: CarrierConfigCoreStartable
 
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: MobileInputLogger
     @Mock private lateinit var carrierConfigManager: CarrierConfigManager
     @Mock private lateinit var dumpManager: DumpManager
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 4da2104..17502f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -33,8 +33,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.util.mockito.any
@@ -81,7 +81,7 @@
     @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var subscriptionManager: SubscriptionManager
     @Mock private lateinit var telephonyManager: TelephonyManager
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: MobileInputLogger
     @Mock private lateinit var summaryLogger: TableLogBuffer
     @Mock private lateinit var demoModeController: DemoModeController
     @Mock private lateinit var dumpManager: DumpManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index a294088a..b2577e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -65,8 +65,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import com.android.systemui.util.mockito.any
@@ -94,7 +94,7 @@
     private lateinit var connectionsRepo: FakeMobileConnectionsRepository
 
     @Mock private lateinit var telephonyManager: TelephonyManager
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: MobileInputLogger
     @Mock private lateinit var tableLogger: TableLogBuffer
 
     private val scope = CoroutineScope(IMMEDIATE)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 8090205..09b7a66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -42,8 +42,8 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
+import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.util.mockito.any
@@ -86,7 +86,7 @@
     @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var subscriptionManager: SubscriptionManager
     @Mock private lateinit var telephonyManager: TelephonyManager
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: MobileInputLogger
     @Mock private lateinit var summaryLogger: TableLogBuffer
     @Mock private lateinit var logBufferFactory: TableLogBufferFactory
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index bbca001..c51dbf1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -85,7 +85,6 @@
             MobileIconsInteractorImpl(
                 connectionsRepository,
                 carrierConfigTracker,
-                logger = mock(),
                 tableLogger = mock(),
                 connectivityRepository,
                 userSetupRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt
new file mode 100644
index 0000000..86529dc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/shared/MobileInputLoggerTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.shared
+
+import android.net.Network
+import android.net.NetworkCapabilities
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
+import org.junit.Test
+import org.mockito.Mockito
+import org.mockito.Mockito.mock
+
+@SmallTest
+class MobileInputLoggerTest : SysuiTestCase() {
+    private val buffer =
+        LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java)).create("buffer", 10)
+    private val logger = MobileInputLogger(buffer)
+
+    @Test
+    fun testLogNetworkCapsChange_bufferHasInfo() {
+        logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true)
+
+        val stringWriter = StringWriter()
+        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
+        val actualString = stringWriter.toString()
+
+        val expectedNetId = NET_1_ID.toString()
+        val expectedCaps = NET_1_CAPS.toString()
+
+        assertThat(actualString).contains("true")
+        assertThat(actualString).contains(expectedNetId)
+        assertThat(actualString).contains(expectedCaps)
+    }
+
+    @Test
+    fun testLogOnLost_bufferHasNetIdOfLostNetwork() {
+        logger.logOnLost(NET_1)
+
+        val stringWriter = StringWriter()
+        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
+        val actualString = stringWriter.toString()
+
+        val expectedNetId = NET_1_ID.toString()
+
+        assertThat(actualString).contains(expectedNetId)
+    }
+
+    companion object {
+        private const val NET_1_ID = 100
+        private val NET_1 =
+            com.android.systemui.util.mockito.mock<Network>().also {
+                Mockito.`when`(it.getNetId()).thenReturn(NET_1_ID)
+            }
+        private val NET_1_CAPS =
+            NetworkCapabilities.Builder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+                .build()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index d9268a2..4628f84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
@@ -51,7 +50,6 @@
 
     private lateinit var airplaneModeInteractor: AirplaneModeInteractor
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var constants: ConnectivityConstants
 
     private val testDispatcher = UnconfinedTestDispatcher()
@@ -77,7 +75,6 @@
                 subscriptionIdsFlow,
                 interactor,
                 airplaneModeInteractor,
-                logger,
                 constants,
                 testScope.backgroundScope,
                 statusBarPipelineFlags,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
deleted file mode 100644
index 3dccbbf..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.shared
-
-import android.net.Network
-import android.net.NetworkCapabilities
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogcatEchoTracker
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
-import com.google.common.truth.Truth.assertThat
-import java.io.PrintWriter
-import java.io.StringWriter
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-
-@SmallTest
-class ConnectivityPipelineLoggerTest : SysuiTestCase() {
-    private val buffer = LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java))
-        .create("buffer", 10)
-    private val logger = ConnectivityPipelineLogger(buffer)
-
-    @Test
-    fun testLogNetworkCapsChange_bufferHasInfo() {
-        logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true)
-
-        val stringWriter = StringWriter()
-        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
-        val actualString = stringWriter.toString()
-
-        val expectedNetId = NET_1_ID.toString()
-        val expectedCaps = NET_1_CAPS.toString()
-
-        assertThat(actualString).contains("true")
-        assertThat(actualString).contains(expectedNetId)
-        assertThat(actualString).contains(expectedCaps)
-    }
-
-    @Test
-    fun testLogOnLost_bufferHasNetIdOfLostNetwork() {
-        logger.logOnLost(NET_1)
-
-        val stringWriter = StringWriter()
-        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
-        val actualString = stringWriter.toString()
-
-        val expectedNetId = NET_1_ID.toString()
-
-        assertThat(actualString).contains(expectedNetId)
-    }
-
-    @Test
-    fun logOutputChange_printsValuesAndNulls() = runBlocking(IMMEDIATE) {
-        val flow: Flow<Int?> = flowOf(1, null, 3)
-
-        val job = flow
-            .logOutputChange(logger, "testInts")
-            .launchIn(this)
-
-        val stringWriter = StringWriter()
-        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
-        val actualString = stringWriter.toString()
-
-        assertThat(actualString).contains("1")
-        assertThat(actualString).contains("null")
-        assertThat(actualString).contains("3")
-
-        job.cancel()
-    }
-
-    @Test
-    fun logInputChange_unit_printsInputName() = runBlocking(IMMEDIATE) {
-        val flow: Flow<Unit> = flowOf(Unit, Unit)
-
-        val job = flow
-            .logInputChange(logger, "testInputs")
-            .launchIn(this)
-
-        val stringWriter = StringWriter()
-        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
-        val actualString = stringWriter.toString()
-
-        assertThat(actualString).contains("testInputs")
-
-        job.cancel()
-    }
-
-    @Test
-    fun logInputChange_any_printsValuesAndNulls() = runBlocking(IMMEDIATE) {
-        val flow: Flow<Any?> = flowOf(null, 2, "threeString")
-
-        val job = flow
-            .logInputChange(logger, "testInputs")
-            .launchIn(this)
-
-        val stringWriter = StringWriter()
-        buffer.dump(PrintWriter(stringWriter), tailLength = 0)
-        val actualString = stringWriter.toString()
-
-        assertThat(actualString).contains("null")
-        assertThat(actualString).contains("2")
-        assertThat(actualString).contains("threeString")
-
-        job.cancel()
-    }
-
-    companion object {
-        private const val NET_1_ID = 100
-        private val NET_1 = com.android.systemui.util.mockito.mock<Network>().also {
-            Mockito.`when`(it.getNetId()).thenReturn(NET_1_ID)
-        }
-        private val NET_1_CAPS = NetworkCapabilities.Builder()
-            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-            .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
-            .build()
-        private val IMMEDIATE = Dispatchers.Main.immediate
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
index 6dbee2f..496f090 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
@@ -19,7 +19,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.DEFAULT_HIDDEN_ICONS_RESOURCE
@@ -52,7 +52,7 @@
 
     @Mock private lateinit var connectivitySlots: ConnectivitySlots
     @Mock private lateinit var dumpManager: DumpManager
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: ConnectivityInputLogger
     private lateinit var scope: CoroutineScope
     @Mock private lateinit var tunerService: TunerService
 
@@ -61,14 +61,15 @@
         MockitoAnnotations.initMocks(this)
         scope = CoroutineScope(IMMEDIATE)
 
-        underTest = ConnectivityRepositoryImpl(
-            connectivitySlots,
-            context,
-            dumpManager,
-            logger,
-            scope,
-            tunerService,
-        )
+        underTest =
+            ConnectivityRepositoryImpl(
+                connectivitySlots,
+                context,
+                dumpManager,
+                logger,
+                scope,
+                tunerService,
+            )
     }
 
     @After
@@ -77,199 +78,179 @@
     }
 
     @Test
-    fun forceHiddenSlots_initiallyGetsDefault() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
-        context.getOrCreateTestableResources().addOverride(
-            DEFAULT_HIDDEN_ICONS_RESOURCE,
-            arrayOf(SLOT_WIFI, SLOT_ETHERNET)
-        )
-        // Re-create our [ConnectivityRepositoryImpl], since it fetches
-        // config_statusBarIconsToExclude when it's first constructed
-        underTest = ConnectivityRepositoryImpl(
-            connectivitySlots,
-            context,
-            dumpManager,
-            logger,
-            scope,
-            tunerService,
-        )
+    fun forceHiddenSlots_initiallyGetsDefault() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
+            context
+                .getOrCreateTestableResources()
+                .addOverride(DEFAULT_HIDDEN_ICONS_RESOURCE, arrayOf(SLOT_WIFI, SLOT_ETHERNET))
+            // Re-create our [ConnectivityRepositoryImpl], since it fetches
+            // config_statusBarIconsToExclude when it's first constructed
+            underTest =
+                ConnectivityRepositoryImpl(
+                    connectivitySlots,
+                    context,
+                    dumpManager,
+                    logger,
+                    scope,
+                    tunerService,
+                )
 
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI)
+            assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_slotNamesAdded_flowHasSlots() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
+    fun forceHiddenSlots_slotNamesAdded_flowHasSlots() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
 
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
 
-        assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
+            assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_wrongKey_doesNotUpdate() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
+    fun forceHiddenSlots_wrongKey_doesNotUpdate() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
 
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
 
-        // WHEN onTuningChanged with the wrong key
-        getTunable().onTuningChanged("wrongKey", SLOT_WIFI)
-        yield()
+            // WHEN onTuningChanged with the wrong key
+            getTunable().onTuningChanged("wrongKey", SLOT_WIFI)
+            yield()
 
-        // THEN we didn't update our value and still have the old one
-        assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
+            // THEN we didn't update our value and still have the old one
+            assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_slotNamesAddedThenNull_flowHasDefault() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
-        context.getOrCreateTestableResources().addOverride(
-            DEFAULT_HIDDEN_ICONS_RESOURCE,
-            arrayOf(SLOT_WIFI, SLOT_ETHERNET)
-        )
-        // Re-create our [ConnectivityRepositoryImpl], since it fetches
-        // config_statusBarIconsToExclude when it's first constructed
-        underTest = ConnectivityRepositoryImpl(
-            connectivitySlots,
-            context,
-            dumpManager,
-            logger,
-            scope,
-            tunerService,
-        )
+    fun forceHiddenSlots_slotNamesAddedThenNull_flowHasDefault() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
+            context
+                .getOrCreateTestableResources()
+                .addOverride(DEFAULT_HIDDEN_ICONS_RESOURCE, arrayOf(SLOT_WIFI, SLOT_ETHERNET))
+            // Re-create our [ConnectivityRepositoryImpl], since it fetches
+            // config_statusBarIconsToExclude when it's first constructed
+            underTest =
+                ConnectivityRepositoryImpl(
+                    connectivitySlots,
+                    context,
+                    dumpManager,
+                    logger,
+                    scope,
+                    tunerService,
+                )
 
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        // First, update the slots
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
-        assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
+            // First, update the slots
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE)
+            assertThat(latest).containsExactly(ConnectivitySlot.MOBILE)
 
-        // WHEN we update to a null value
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, null)
-        yield()
+            // WHEN we update to a null value
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, null)
+            yield()
 
-        // THEN we go back to our default value
-        assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI)
+            // THEN we go back to our default value
+            assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_someInvalidSlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) {
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+    fun forceHiddenSlots_someInvalidSlotNames_flowHasValidSlotsOnly() =
+        runBlocking(IMMEDIATE) {
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        whenever(connectivitySlots.getSlotFromName(SLOT_WIFI))
-            .thenReturn(ConnectivitySlot.WIFI)
-        whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null)
+            whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(ConnectivitySlot.WIFI)
+            whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null)
 
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_MOBILE")
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_MOBILE")
 
-        assertThat(latest).containsExactly(ConnectivitySlot.WIFI)
+            assertThat(latest).containsExactly(ConnectivitySlot.WIFI)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_someEmptySlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
+    fun forceHiddenSlots_someEmptySlotNames_flowHasValidSlotsOnly() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
 
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        // WHEN there's empty and blank slot names
-        getTunable().onTuningChanged(
-            HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE,  ,,$SLOT_WIFI"
-        )
+            // WHEN there's empty and blank slot names
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE,  ,,$SLOT_WIFI")
 
-        // THEN we skip that slot but still process the other ones
-        assertThat(latest).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.MOBILE)
+            // THEN we skip that slot but still process the other ones
+            assertThat(latest).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.MOBILE)
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_allInvalidOrEmptySlotNames_flowHasEmpty() = runBlocking(IMMEDIATE) {
-        var latest: Set<ConnectivitySlot>? = null
-        val job = underTest
-            .forceHiddenSlots
-            .onEach { latest = it }
-            .launchIn(this)
+    fun forceHiddenSlots_allInvalidOrEmptySlotNames_flowHasEmpty() =
+        runBlocking(IMMEDIATE) {
+            var latest: Set<ConnectivitySlot>? = null
+            val job = underTest.forceHiddenSlots.onEach { latest = it }.launchIn(this)
 
-        whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(null)
-        whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)).thenReturn(null)
-        whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null)
+            whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(null)
+            whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)).thenReturn(null)
+            whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null)
 
-        getTunable().onTuningChanged(
-            HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE,,$SLOT_WIFI,$SLOT_ETHERNET,,,"
-        )
+            getTunable()
+                .onTuningChanged(
+                    HIDDEN_ICONS_TUNABLE_KEY,
+                    "$SLOT_MOBILE,,$SLOT_WIFI,$SLOT_ETHERNET,,,"
+                )
 
-        assertThat(latest).isEmpty()
+            assertThat(latest).isEmpty()
 
-        job.cancel()
-    }
+            job.cancel()
+        }
 
     @Test
-    fun forceHiddenSlots_newSubscriberGetsCurrentValue() = runBlocking(IMMEDIATE) {
-        setUpEthernetWifiMobileSlotNames()
+    fun forceHiddenSlots_newSubscriberGetsCurrentValue() =
+        runBlocking(IMMEDIATE) {
+            setUpEthernetWifiMobileSlotNames()
 
-        var latest1: Set<ConnectivitySlot>? = null
-        val job1 = underTest
-            .forceHiddenSlots
-            .onEach { latest1 = it }
-            .launchIn(this)
+            var latest1: Set<ConnectivitySlot>? = null
+            val job1 = underTest.forceHiddenSlots.onEach { latest1 = it }.launchIn(this)
 
-        getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_ETHERNET")
+            getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_ETHERNET")
 
-        assertThat(latest1).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET)
+            assertThat(latest1).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET)
 
-        // WHEN we add a second subscriber after having already emitted a value
-        var latest2: Set<ConnectivitySlot>? = null
-        val job2 = underTest
-            .forceHiddenSlots
-            .onEach { latest2 = it }
-            .launchIn(this)
+            // WHEN we add a second subscriber after having already emitted a value
+            var latest2: Set<ConnectivitySlot>? = null
+            val job2 = underTest.forceHiddenSlots.onEach { latest2 = it }.launchIn(this)
 
-        // THEN the second subscribe receives the already-emitted value
-        assertThat(latest2).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET)
+            // THEN the second subscribe receives the already-emitted value
+            assertThat(latest2).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET)
 
-        job1.cancel()
-        job2.cancel()
-    }
+            job1.cancel()
+            job2.cancel()
+        }
 
     private fun getTunable(): TunerService.Tunable {
         val callbackCaptor = argumentCaptor<TunerService.Tunable>()
@@ -280,10 +261,8 @@
     private fun setUpEthernetWifiMobileSlotNames() {
         whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET))
             .thenReturn(ConnectivitySlot.ETHERNET)
-        whenever(connectivitySlots.getSlotFromName(SLOT_WIFI))
-            .thenReturn(ConnectivitySlot.WIFI)
-        whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE))
-            .thenReturn(ConnectivitySlot.MOBILE)
+        whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(ConnectivitySlot.WIFI)
+        whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(ConnectivitySlot.MOBILE)
     }
 
     companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index 1085c2b..25678b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -23,11 +23,11 @@
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
+import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.kotlinArgumentCaptor
 import com.android.systemui.util.mockito.whenever
@@ -47,6 +47,7 @@
 import org.mockito.MockitoAnnotations
 
 @OptIn(ExperimentalCoroutinesApi::class)
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
 @SmallTest
 class WifiRepositorySwitcherTest : SysuiTestCase() {
     private lateinit var underTest: WifiRepositorySwitcher
@@ -54,7 +55,7 @@
     private lateinit var demoImpl: DemoWifiRepository
 
     @Mock private lateinit var demoModeController: DemoModeController
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: WifiInputLogger
     @Mock private lateinit var tableLogger: TableLogBuffer
     @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var wifiManager: WifiManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index db791bb..c7b31bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -34,9 +34,9 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
+import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
@@ -72,7 +72,7 @@
     private lateinit var underTest: WifiRepositoryImpl
 
     @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
+    @Mock private lateinit var logger: WifiInputLogger
     @Mock private lateinit var tableLogger: TableLogBuffer
     @Mock private lateinit var connectivityManager: ConnectivityManager
     @Mock private lateinit var wifiManager: WifiManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index 60f564e..64810d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -36,7 +36,6 @@
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
@@ -63,7 +62,6 @@
     private lateinit var testableLooper: TestableLooper
 
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
     @Mock private lateinit var connectivityConstants: ConnectivityConstants
     @Mock private lateinit var wifiConstants: WifiConstants
@@ -92,7 +90,7 @@
                     airplaneModeRepository,
                     connectivityRepository,
                 ),
-                logger,
+                tableLogBuffer,
                 scope,
             )
         viewModel =
@@ -100,7 +98,6 @@
                     airplaneModeViewModel,
                     connectivityConstants,
                     context,
-                    logger,
                     tableLogBuffer,
                     interactor,
                     scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 648d7a5..12b1664 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -33,7 +33,6 @@
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
@@ -68,7 +67,6 @@
     private lateinit var underTest: WifiViewModel
 
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
     @Mock private lateinit var connectivityConstants: ConnectivityConstants
     @Mock private lateinit var wifiConstants: WifiConstants
@@ -94,7 +92,7 @@
                     airplaneModeRepository,
                     connectivityRepository,
                 ),
-                logger,
+                tableLogBuffer,
                 scope,
             )
     }
@@ -125,7 +123,6 @@
                     airplaneModeViewModel,
                     connectivityConstants,
                     context,
-                    logger,
                     tableLogBuffer,
                     interactor,
                     scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index 45ebb39..7a62cb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
-import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -59,7 +58,6 @@
     private lateinit var underTest: WifiViewModel
 
     @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
-    @Mock private lateinit var logger: ConnectivityPipelineLogger
     @Mock private lateinit var tableLogBuffer: TableLogBuffer
     @Mock private lateinit var connectivityConstants: ConnectivityConstants
     @Mock private lateinit var wifiConstants: WifiConstants
@@ -85,7 +83,7 @@
                     airplaneModeRepository,
                     connectivityRepository,
                 ),
-                logger,
+                tableLogBuffer,
                 scope,
             )
 
@@ -478,7 +476,6 @@
                 airplaneModeViewModel,
                 connectivityConstants,
                 context,
-                logger,
                 tableLogBuffer,
                 interactor,
                 scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
index 4aa86c2..13a2baa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java
@@ -20,6 +20,7 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotSame;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -81,6 +82,7 @@
                 UiEventLogger uiEventLogger) {
             super(context, logger, handler, accessibilityManagerWrapper, uiEventLogger);
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
+            mStickyDisplayTime = TEST_STICKY_DISPLAY_TIME;
             mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
         }
     }
@@ -129,6 +131,86 @@
         assertFalse(mHeadsUpManager.isAlerting(mEntry.getKey()));
     }
 
+
+    @Test
+    public void testIsSticky_rowPinnedAndExpanded_true() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createNewNotification(/* id= */ 0))
+                .build();
+
+        when(mRow.isPinned()).thenReturn(true);
+        notifEntry.setRow(mRow);
+
+        mHeadsUpManager.showNotification(notifEntry);
+
+        HeadsUpManager.HeadsUpEntry headsUpEntry =
+                mHeadsUpManager.getHeadsUpEntry(notifEntry.getKey());
+        headsUpEntry.setExpanded(true);
+
+        assertTrue(mHeadsUpManager.isSticky(notifEntry.getKey()));
+    }
+
+    @Test
+    public void testIsSticky_remoteInputActive_true() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createNewNotification(/* id= */ 0))
+                .build();
+
+        mHeadsUpManager.showNotification(notifEntry);
+
+        HeadsUpManager.HeadsUpEntry headsUpEntry =
+                mHeadsUpManager.getHeadsUpEntry(notifEntry.getKey());
+
+        headsUpEntry.remoteInputActive = true;
+
+        assertTrue(mHeadsUpManager.isSticky(notifEntry.getKey()));
+    }
+
+    @Test
+    public void testIsSticky_hasFullScreenIntent_true() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createNewNotification(/* id= */ 0))
+                .build();
+
+        mHeadsUpManager.showNotification(notifEntry);
+
+        HeadsUpManager.HeadsUpEntry headsUpEntry =
+                mHeadsUpManager.getHeadsUpEntry(notifEntry.getKey());
+
+        notifEntry.getSbn().getNotification().fullScreenIntent = PendingIntent.getActivity(
+                getContext(), 0, new Intent(getContext(), this.getClass()),
+                PendingIntent.FLAG_MUTABLE_UNAUDITED);
+
+        assertTrue(mHeadsUpManager.isSticky(notifEntry.getKey()));
+    }
+
+    @Test
+    public void testIsSticky_stickyAndNotDemoted_true() {
+        NotificationEntry alertEntry = new NotificationEntryBuilder()
+                .setSbn(createStickySbn(0))
+                .build();
+
+        mHeadsUpManager.showNotification(alertEntry);
+
+        assertTrue(mHeadsUpManager.isSticky(alertEntry.getKey()));
+    }
+
+    @Test
+    public void testIsSticky_false() {
+        NotificationEntry notifEntry = new NotificationEntryBuilder()
+                .setSbn(createNewNotification(/* id= */ 0))
+                .build();
+
+        mHeadsUpManager.showNotification(notifEntry);
+
+        HeadsUpManager.HeadsUpEntry headsUpEntry =
+                mHeadsUpManager.getHeadsUpEntry(notifEntry.getKey());
+        headsUpEntry.setExpanded(false);
+        headsUpEntry.remoteInputActive = false;
+
+        assertFalse(mHeadsUpManager.isSticky(notifEntry.getKey()));
+    }
+
     @Test
     public void testCompareTo_withNullEntries() {
         NotificationEntry alertEntry = new NotificationEntryBuilder().setTag("alert").build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
index 48a2e09..f8bf4b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusManagerTest.kt
@@ -29,7 +29,9 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito.times
 import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
 import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.internal.logging.InstanceId
 import com.android.internal.logging.UiEventLogger
+import com.android.systemui.InstanceIdSequenceFake
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
@@ -59,21 +61,16 @@
     @Mock lateinit var bluetoothAdapter: BluetoothAdapter
     @Mock lateinit var bluetoothDevice: BluetoothDevice
     @Mock lateinit var handler: Handler
-
     @Mock lateinit var featureFlags: FeatureFlags
-
     @Mock lateinit var uiEventLogger: UiEventLogger
-
     @Mock lateinit var stylusCallback: StylusManager.StylusCallback
-
     @Mock lateinit var otherStylusCallback: StylusManager.StylusCallback
-
     @Mock lateinit var stylusBatteryCallback: StylusManager.StylusBatteryCallback
-
     @Mock lateinit var otherStylusBatteryCallback: StylusManager.StylusBatteryCallback
 
     private lateinit var mockitoSession: StaticMockitoSession
     private lateinit var stylusManager: StylusManager
+    private val instanceIdSequenceFake = InstanceIdSequenceFake(10)
 
     @Before
     fun setUp() {
@@ -100,6 +97,8 @@
                 uiEventLogger
             )
 
+        stylusManager.instanceIdSequence = instanceIdSequenceFake
+
         whenever(otherDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(false)
         whenever(stylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
         whenever(btStylusDevice.supportsSource(InputDevice.SOURCE_STYLUS)).thenReturn(true)
@@ -403,7 +402,13 @@
     fun onStylusBluetoothConnected_logsEvent() {
         stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
 
-        verify(uiEventLogger, times(1)).log(StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED)
+        verify(uiEventLogger, times(1))
+            .logWithInstanceId(
+                StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED,
+                0,
+                null,
+                InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId)
+            )
     }
 
     @Test
@@ -416,12 +421,16 @@
     }
 
     @Test
-    fun onStylusBluetoothDisconnected_logsEvent() {
+    fun onStylusBluetoothDisconnected_logsEventInSameSession() {
         stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)
+        val instanceId = InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId)
 
         stylusManager.onInputDeviceRemoved(BT_STYLUS_DEVICE_ID)
 
-        verify(uiEventLogger, times(1)).log(StylusUiEvent.BLUETOOTH_STYLUS_DISCONNECTED)
+        verify(uiEventLogger, times(1))
+            .logWithInstanceId(StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED, 0, null, instanceId)
+        verify(uiEventLogger, times(1))
+            .logWithInstanceId(StylusUiEvent.BLUETOOTH_STYLUS_DISCONNECTED, 0, null, instanceId)
     }
 
     @Test
@@ -519,7 +528,12 @@
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
 
         verify(uiEventLogger, times(1))
-            .log(StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED)
+            .logWithInstanceId(
+                StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
+                0,
+                null,
+                InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId)
+            )
     }
 
     @Test
@@ -530,7 +544,7 @@
 
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
 
-        verify(uiEventLogger, never()).log(any())
+        verifyZeroInteractions(uiEventLogger)
     }
 
     @Test
@@ -539,18 +553,33 @@
 
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
 
-        verify(uiEventLogger, never()).log(any())
+        verifyZeroInteractions(uiEventLogger)
     }
 
     @Test
     fun onBatteryStateChanged_batteryAbsent_inUsiSession_logSessionEnd() {
         whenever(batteryState.isPresent).thenReturn(true)
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
+        val instanceId = InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId)
         whenever(batteryState.isPresent).thenReturn(false)
 
         stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)
 
-        verify(uiEventLogger, times(1)).log(StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED)
+        verify(uiEventLogger, times(1))
+            .logWithInstanceId(
+                StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
+                0,
+                null,
+                instanceId
+            )
+
+        verify(uiEventLogger, times(1))
+            .logWithInstanceId(
+                StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED,
+                0,
+                null,
+                instanceId
+            )
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
index d51c514..572aca9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/stylus/StylusUsiPowerUiTest.kt
@@ -28,7 +28,9 @@
 import android.view.InputDevice
 import androidx.core.app.NotificationManagerCompat
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
 import com.android.internal.logging.UiEventLogger
+import com.android.systemui.InstanceIdSequenceFake
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
@@ -64,13 +66,14 @@
     @Mock lateinit var btStylusDevice: InputDevice
 
     @Mock lateinit var uiEventLogger: UiEventLogger
-
     @Captor lateinit var notificationCaptor: ArgumentCaptor<Notification>
 
     private lateinit var stylusUsiPowerUi: StylusUsiPowerUI
     private lateinit var broadcastReceiver: BroadcastReceiver
     private lateinit var contextSpy: Context
 
+    private val instanceIdSequenceFake = InstanceIdSequenceFake(10)
+
     private val uid = ActivityManager.getCurrentUser()
 
     @Before
@@ -92,6 +95,8 @@
 
         stylusUsiPowerUi =
             StylusUsiPowerUI(contextSpy, notificationManager, inputManager, handler, uiEventLogger)
+        stylusUsiPowerUi.instanceIdSequence = instanceIdSequenceFake
+
         broadcastReceiver = stylusUsiPowerUi.receiver
     }
 
@@ -212,10 +217,11 @@
         stylusUsiPowerUi.updateBatteryState(0, FixedCapacityBatteryState(0.1f))
 
         verify(uiEventLogger, times(1))
-            .logWithPosition(
+            .logWithInstanceIdAndPosition(
                 StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN,
                 uid,
                 contextSpy.packageName,
+                InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId),
                 10
             )
     }
@@ -250,10 +256,11 @@
         broadcastReceiver.onReceive(contextSpy, intent)
 
         verify(uiEventLogger, times(1))
-            .logWithPosition(
+            .logWithInstanceIdAndPosition(
                 StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED,
                 uid,
                 contextSpy.packageName,
+                InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId),
                 100
             )
     }
@@ -264,10 +271,11 @@
         broadcastReceiver.onReceive(contextSpy, intent)
 
         verify(uiEventLogger, times(1))
-            .logWithPosition(
+            .logWithInstanceIdAndPosition(
                 StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED,
                 uid,
                 contextSpy.packageName,
+                InstanceId.fakeInstanceId(instanceIdSequenceFake.lastInstanceId),
                 100
             )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index 3d75967..a87e61a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
 import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.shade.NotificationPanelViewController
@@ -112,7 +113,8 @@
             KeyguardInteractor(
                 repository = keyguardRepository,
                 commandQueue = commandQueue,
-                featureFlags = featureFlags
+                featureFlags = featureFlags,
+                bouncerRepository = FakeKeyguardBouncerRepository(),
             )
 
         // Needs to be run on the main thread
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
index 22d05bf..f0a53ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
@@ -145,6 +146,7 @@
                         repository = keyguardRepository,
                         commandQueue = commandQueue,
                         featureFlags = featureFlags,
+                        bouncerRepository = FakeKeyguardBouncerRepository(),
                     ),
                 manager = manager,
                 headlessSystemUserMode = headlessSystemUserMode,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
index 2f05e65..bc0881c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/StatusBarUserChipViewModelTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
@@ -251,6 +252,7 @@
                             repository = keyguardRepository,
                             commandQueue = commandQueue,
                             featureFlags = featureFlags,
+                            bouncerRepository = FakeKeyguardBouncerRepository(),
                         ),
                     featureFlags = featureFlags,
                     manager = manager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 9268904..c8b0496 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.plugins.ActivityStarter
@@ -152,7 +153,8 @@
                                 KeyguardInteractor(
                                     repository = keyguardRepository,
                                     commandQueue = commandQueue,
-                                    featureFlags = featureFlags
+                                    featureFlags = featureFlags,
+                                    bouncerRepository = FakeKeyguardBouncerRepository(),
                                 ),
                             featureFlags = featureFlags,
                             manager = manager,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
index d0383e9..3374219 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -57,10 +57,10 @@
     override val bouncerPromptReason = 0
     override val bouncerErrorMessage: CharSequence? = null
     private val _isAlternateBouncerVisible = MutableStateFlow(false)
-    override val isAlternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
+    override val alternateBouncerVisible = _isAlternateBouncerVisible.asStateFlow()
     override var lastAlternateBouncerVisibleTime: Long = 0L
     private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
-    override val isAlternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
+    override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
 
     override fun setPrimaryScrimmed(isScrimmed: Boolean) {
         _primaryBouncerScrimmed.value = isScrimmed
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 065fe89..1a371c7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -84,9 +84,6 @@
 
     private val _isUdfpsSupported = MutableStateFlow(false)
 
-    private val _isBouncerShowing = MutableStateFlow(false)
-    override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing
-
     private val _isKeyguardGoingAway = MutableStateFlow(false)
     override val isKeyguardGoingAway: Flow<Boolean> = _isKeyguardGoingAway
 
@@ -153,10 +150,6 @@
         _wakefulnessModel.value = model
     }
 
-    fun setBouncerShowing(isShowing: Boolean) {
-        _isBouncerShowing.value = isShowing
-    }
-
     fun setBiometricUnlockState(state: BiometricUnlockModel) {
         _biometricUnlockState.tryEmit(state)
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
index 95b62a1..bdf1aff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
@@ -49,7 +49,7 @@
     }
 
     @Override
-    public boolean isBouncerShowing() {
+    public boolean isPrimaryBouncerShowing() {
         return false;
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 72c5598..328b971 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3819,20 +3819,30 @@
                     + "proxy-ed");
         }
 
-        mProxyManager.registerProxy(client, displayId, mContext,
-                sIdCounter++, mMainHandler, mSecurityPolicy, this, getTraceManager(),
-                mWindowManagerService, mA11yWindowManager);
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mProxyManager.registerProxy(client, displayId, mContext,
+                    sIdCounter++, mMainHandler, mSecurityPolicy, this, getTraceManager(),
+                    mWindowManagerService, mA11yWindowManager);
 
-        synchronized (mLock) {
-            notifyClearAccessibilityCacheLocked();
+            synchronized (mLock) {
+                notifyClearAccessibilityCacheLocked();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
         return true;
     }
 
     @Override
-    public boolean unregisterProxyForDisplay(int displayId) throws RemoteException {
+    public boolean unregisterProxyForDisplay(int displayId) {
         mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
-        return mProxyManager.unregisterProxy(displayId);
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mProxyManager.unregisterProxy(displayId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     boolean isDisplayProxyed(int displayId) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index d7c5b5d..f8ab0d5 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -38,6 +38,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.os.Handler;
 import android.os.Message;
+import android.provider.DeviceConfig;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.MathUtils;
@@ -48,6 +49,7 @@
 import android.view.DisplayInfo;
 import android.view.MagnificationSpec;
 import android.view.View;
+import android.view.WindowManager;
 import android.view.accessibility.MagnificationAnimationCallback;
 import android.view.animation.DecelerateInterpolator;
 
@@ -62,6 +64,7 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import java.util.Locale;
+import java.util.function.Supplier;
 
 /**
  * This class is used to control and query the state of display magnification
@@ -104,6 +107,8 @@
     private boolean mAlwaysOnMagnificationEnabled = false;
     private final DisplayManagerInternal mDisplayManagerInternal;
 
+    @NonNull private final Supplier<MagnificationThumbnail> mThumbnailSupplier;
+
     /**
      * This class implements {@link WindowManagerInternal.MagnificationCallbacks} and holds
      * magnification information per display.
@@ -134,6 +139,8 @@
         private int mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
         private boolean mMagnificationActivated = false;
 
+        @GuardedBy("mLock") @Nullable private MagnificationThumbnail mMagnificationThumbnail;
+
         DisplayMagnification(int displayId) {
             mDisplayId = displayId;
             mSpecAnimationBridge = new SpecAnimationBridge(mControllerCtx, mLock, mDisplayId);
@@ -166,6 +173,11 @@
             mControllerCtx.getWindowManager().getMagnificationRegion(
                     mDisplayId, mMagnificationRegion);
             mMagnificationRegion.getBounds(mMagnificationBounds);
+
+            if (mMagnificationThumbnail == null) {
+                mMagnificationThumbnail = mThumbnailSupplier.get();
+            }
+
             return true;
         }
 
@@ -191,6 +203,8 @@
                 mMagnificationRegion.setEmpty();
                 mRegistered = false;
                 unregisterCallbackLocked(mDisplayId, delete);
+
+                destroyThumbNail();
             }
             mUnregisterPending = false;
         }
@@ -327,6 +341,9 @@
                 if (!mMagnificationRegion.equals(magnified)) {
                     mMagnificationRegion.set(magnified);
                     mMagnificationRegion.getBounds(mMagnificationBounds);
+
+                    refreshThumbNail(getScale(), getCenterX(), getCenterY());
+
                     // It's possible that our magnification spec is invalid with the new bounds.
                     // Adjust the current spec's offsets if necessary.
                     if (updateCurrentSpecWithOffsetsLocked(
@@ -368,18 +385,25 @@
         @GuardedBy("mLock")
         void onMagnificationChangedLocked() {
             final float scale = getScale();
-
+            final float centerX = getCenterX();
+            final float centerY = getCenterY();
             final MagnificationConfig config = new MagnificationConfig.Builder()
                     .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                     .setActivated(mMagnificationActivated)
                     .setScale(scale)
-                    .setCenterX(getCenterX())
-                    .setCenterY(getCenterY()).build();
+                    .setCenterX(centerX)
+                    .setCenterY(centerY).build();
             mMagnificationInfoChangedCallback.onFullScreenMagnificationChanged(mDisplayId,
                     mMagnificationRegion, config);
             if (mUnregisterPending && !isActivated()) {
                 unregister(mDeleteAfterUnregister);
             }
+
+            if (isActivated()) {
+                updateThumbNail(scale, centerX, centerY);
+            } else {
+                hideThumbNail();
+            }
         }
 
         @GuardedBy("mLock")
@@ -506,6 +530,9 @@
             }
             mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
             sendSpecToAnimation(spec, animationCallback);
+
+            hideThumbNail();
+
             return changed;
         }
 
@@ -559,6 +586,40 @@
             return changed;
         }
 
+        @GuardedBy("mLock")
+        void updateThumbNail(float scale, float centerX, float centerY) {
+            if (mMagnificationThumbnail != null) {
+                mMagnificationThumbnail.updateThumbNail(scale, centerX, centerY);
+            }
+        }
+
+        @GuardedBy("mLock")
+        void refreshThumbNail(float scale, float centerX, float centerY) {
+            if (mMagnificationThumbnail != null) {
+                mMagnificationThumbnail.setThumbNailBounds(
+                        mMagnificationBounds,
+                        scale,
+                        centerX,
+                        centerY
+                );
+            }
+        }
+
+        @GuardedBy("mLock")
+        void hideThumbNail() {
+            if (mMagnificationThumbnail != null) {
+                mMagnificationThumbnail.hideThumbNail();
+            }
+        }
+
+        @GuardedBy("mLock")
+        void destroyThumbNail() {
+            if (mMagnificationThumbnail != null) {
+                hideThumbNail();
+                mMagnificationThumbnail = null;
+            }
+        }
+
         /**
          * Updates the current magnification spec.
          *
@@ -688,21 +749,40 @@
             @NonNull AccessibilityTraceManager traceManager, @NonNull Object lock,
             @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
             @NonNull MagnificationScaleProvider scaleProvider) {
-        this(new ControllerContext(context, traceManager,
-                LocalServices.getService(WindowManagerInternal.class),
-                new Handler(context.getMainLooper()),
-                context.getResources().getInteger(R.integer.config_longAnimTime)), lock,
-                magnificationInfoChangedCallback, scaleProvider);
+        this(
+                new ControllerContext(
+                        context,
+                        traceManager,
+                        LocalServices.getService(WindowManagerInternal.class),
+                        new Handler(context.getMainLooper()),
+                        context.getResources().getInteger(R.integer.config_longAnimTime)),
+                lock,
+                magnificationInfoChangedCallback,
+                scaleProvider,
+                () -> {
+                    if (DeviceConfig.getBoolean(
+                            DeviceConfig.NAMESPACE_ACCESSIBILITY,
+                            "enable_magnifier_thumbnail",
+                            /* defaultValue= */ false)) {
+                        return new MagnificationThumbnail(
+                            context,
+                            context.getSystemService(WindowManager.class),
+                            new Handler(context.getMainLooper())
+                        );
+                    }
+
+                    return null;
+                });
     }
 
-    /**
-     * Constructor for tests
-     */
+    /** Constructor for tests */
     @VisibleForTesting
-    public FullScreenMagnificationController(@NonNull ControllerContext ctx,
+    public FullScreenMagnificationController(
+            @NonNull ControllerContext ctx,
             @NonNull Object lock,
             @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
-            @NonNull MagnificationScaleProvider scaleProvider) {
+            @NonNull MagnificationScaleProvider scaleProvider,
+            @NonNull Supplier<MagnificationThumbnail> thumbnailSupplier) {
         mControllerCtx = ctx;
         mLock = lock;
         mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
@@ -710,6 +790,7 @@
         mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
         mScaleProvider = scaleProvider;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+        mThumbnailSupplier = thumbnailSupplier;
     }
 
     /**
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java
new file mode 100644
index 0000000..fe7b11f
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java
@@ -0,0 +1,305 @@
+/*
+ * 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.server.accessibility.magnification;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.annotation.AnyThread;
+import android.annotation.MainThread;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.R;
+/**
+ *  This class is used to show of magnification thumbnail
+ *  from FullScreenMagnification. It is responsible for
+ *  show of magnification and fade in/out animation, and
+ *  it just only uses in FullScreenMagnification
+ */
+public class MagnificationThumbnail {
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "MagnificationThumbnail";
+
+    private static final int FADE_IN_ANIMATION_DURATION_MS = 200;
+    private static final int FADE_OUT_ANIMATION_DURATION_MS = 1000;
+    private static final int LINGER_DURATION_MS = 500;
+
+    private Rect mWindowBounds;
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private final Handler mHandler;
+
+    @VisibleForTesting
+    public final FrameLayout mThumbnailLayout;
+
+    private final View mThumbNailView;
+
+    private final WindowManager.LayoutParams mBackgroundParams;
+    private boolean mVisible = false;
+
+    private static final float ASPECT_RATIO = 28f;
+    private static final float BG_ASPECT_RATIO = ASPECT_RATIO / 2f;
+
+    private ObjectAnimator mThumbNailAnimator;
+    private boolean mIsFadingIn;
+
+    /**
+     * FullScreenMagnificationThumbnail Constructor
+     */
+    public MagnificationThumbnail(Context context, WindowManager windowManager, Handler handler) {
+        mContext = context;
+        mWindowManager = windowManager;
+        mHandler = handler;
+        mWindowBounds =  mWindowManager.getCurrentWindowMetrics().getBounds();
+        mThumbnailLayout = (FrameLayout) LayoutInflater.from(mContext)
+                .inflate(R.layout.thumbnail_background_view, /* root: */ null);
+        mThumbNailView =
+                mThumbnailLayout.findViewById(R.id.accessibility_magnification_thumbnail_view);
+        mBackgroundParams = createLayoutParams();
+    }
+
+    /**
+     * Sets the magnificationBounds for Thumbnail and resets the position on the screen.
+     *
+     * @param currentBounds the current magnification bounds
+     */
+    @AnyThread
+    public void setThumbNailBounds(Rect currentBounds, float scale, float centerX, float centerY) {
+        if (DEBUG) {
+            Log.d(LOG_TAG, "setThumbNailBounds " + currentBounds);
+        }
+        mHandler.post(() -> {
+            mWindowBounds = currentBounds;
+            setBackgroundBounds();
+            if (mVisible) {
+                updateThumbNailMainThread(scale, centerX, centerY);
+            }
+        });
+    }
+
+    private void setBackgroundBounds() {
+        Point magnificationBoundary = getMagnificationThumbnailPadding(mContext);
+        final int thumbNailWidth = (int) (mWindowBounds.width() / BG_ASPECT_RATIO);
+        final int thumbNailHeight = (int) (mWindowBounds.height() / BG_ASPECT_RATIO);
+        int initX = magnificationBoundary.x;
+        int initY = magnificationBoundary.y;
+        mBackgroundParams.width = thumbNailWidth;
+        mBackgroundParams.height = thumbNailHeight;
+        mBackgroundParams.x = initX;
+        mBackgroundParams.y = initY;
+    }
+
+    @MainThread
+    private void showThumbNail() {
+        if (DEBUG) {
+            Log.d(LOG_TAG, "showThumbNail " + mVisible);
+        }
+        animateThumbnail(true);
+    }
+
+    /**
+     * Hides thumbnail and removes the view from the window when finished animating.
+     */
+    @AnyThread
+    public void hideThumbNail() {
+        mHandler.post(this::hideThumbNailMainThread);
+    }
+
+    @MainThread
+    private void hideThumbNailMainThread() {
+        if (DEBUG) {
+            Log.d(LOG_TAG, "hideThumbNail " + mVisible);
+        }
+        if (mVisible) {
+            animateThumbnail(false);
+        }
+    }
+
+    /**
+     * Animates the thumbnail in or out and resets the timeout to auto-hiding.
+     *
+     * @param fadeIn true: fade in, false fade out
+     */
+    @MainThread
+    private void animateThumbnail(boolean fadeIn) {
+        if (DEBUG) {
+            Log.d(
+                    LOG_TAG,
+                    "setThumbnailAnimation "
+                        + " fadeIn: " + fadeIn
+                        + " mVisible: " + mVisible
+                        + " isFadingIn: " + mIsFadingIn
+                        + " isRunning: " + mThumbNailAnimator
+            );
+        }
+
+        // Reset countdown to hide automatically
+        mHandler.removeCallbacks(this::hideThumbNailMainThread);
+        if (fadeIn) {
+            mHandler.postDelayed(this::hideThumbNailMainThread, LINGER_DURATION_MS);
+        }
+
+        if (fadeIn == mIsFadingIn) {
+            return;
+        }
+        mIsFadingIn = fadeIn;
+
+        if (fadeIn && !mVisible) {
+            mWindowManager.addView(mThumbnailLayout, mBackgroundParams);
+            mVisible = true;
+        }
+
+        if (mThumbNailAnimator != null) {
+            mThumbNailAnimator.cancel();
+        }
+        mThumbNailAnimator = ObjectAnimator.ofFloat(
+                mThumbnailLayout,
+                "alpha",
+                fadeIn ? 1f : 0f
+        );
+        mThumbNailAnimator.setDuration(
+                fadeIn ? FADE_IN_ANIMATION_DURATION_MS : FADE_OUT_ANIMATION_DURATION_MS
+        );
+        mThumbNailAnimator.addListener(new Animator.AnimatorListener() {
+            private boolean mIsCancelled;
+
+            @Override
+            public void onAnimationStart(@NonNull Animator animation) {
+
+            }
+
+            @Override
+            public void onAnimationEnd(@NonNull Animator animation) {
+                if (DEBUG) {
+                    Log.d(
+                            LOG_TAG,
+                            "onAnimationEnd "
+                                + " fadeIn: " + fadeIn
+                                + " mVisible: " + mVisible
+                                + " mIsCancelled: " + mIsCancelled
+                                + " animation: " + animation);
+                }
+                if (mIsCancelled) {
+                    return;
+                }
+                if (!fadeIn && mVisible) {
+                    mWindowManager.removeView(mThumbnailLayout);
+                    mVisible = false;
+                }
+            }
+
+            @Override
+            public void onAnimationCancel(@NonNull Animator animation) {
+                if (DEBUG) {
+                    Log.d(LOG_TAG, "onAnimationCancel "
+                            + " fadeIn: " + fadeIn
+                            + " mVisible: " + mVisible
+                            + " animation: " + animation);
+                }
+                mIsCancelled = true;
+            }
+
+            @Override
+            public void onAnimationRepeat(@NonNull Animator animation) {
+
+            }
+        });
+
+        mThumbNailAnimator.start();
+    }
+
+    /**
+     * Scale up/down the current magnification thumbnail spec.
+     *
+     * <p>Will show/hide the thumbnail with animations when appropriate.
+     *
+     * @param scale the magnification scale
+     * @param centerX the unscaled, screen-relative X coordinate of the center
+     *                of the viewport, or {@link Float#NaN} to leave unchanged
+     * @param centerY the unscaled, screen-relative Y coordinate of the center
+     *                of the viewport, or {@link Float#NaN} to leave unchanged
+     */
+    @AnyThread
+    public void updateThumbNail(float scale, float centerX, float centerY) {
+        mHandler.post(() -> updateThumbNailMainThread(scale, centerX, centerY));
+    }
+
+    @MainThread
+    private void updateThumbNailMainThread(float scale, float centerX, float centerY) {
+        // Restart the fadeout countdown (or show if it's hidden)
+        showThumbNail();
+
+        var scaleDown = Float.isNaN(scale) ? mThumbNailView.getScaleX() : 1f / scale;
+        if (!Float.isNaN(scale)) {
+            mThumbNailView.setScaleX(scaleDown);
+            mThumbNailView.setScaleY(scaleDown);
+        }
+        if (!Float.isNaN(centerX)) {
+            var ratio = 1f / BG_ASPECT_RATIO;
+            var centerXScaled = centerX * ratio - mThumbNailView.getWidth() / 2f;
+            var centerYScaled = centerY * ratio - mThumbNailView.getHeight() / 2f;
+
+            if (DEBUG) {
+                Log.d(
+                        LOG_TAG,
+                        "updateThumbNail centerXScaled : " + centerXScaled
+                                + " centerYScaled : " + centerYScaled
+                                + " getTranslationX : " + mThumbNailView.getTranslationX()
+                                + " ratio : " + ratio
+                );
+            }
+
+            mThumbNailView.setTranslationX(centerXScaled);
+            mThumbNailView.setTranslationY(centerYScaled);
+        }
+    }
+
+    private WindowManager.LayoutParams createLayoutParams() {
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
+                PixelFormat.TRANSPARENT);
+        params.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
+        params.gravity = Gravity.BOTTOM | Gravity.LEFT;
+        params.setFitInsetsTypes(WindowInsets.Type.ime() | WindowInsets.Type.navigationBars());
+        return params;
+    }
+
+    private Point getMagnificationThumbnailPadding(Context context) {
+        Point thumbnailPaddings = new Point(0, 0);
+        final int defaultPadding = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.accessibility_magnification_thumbnail_padding);
+        thumbnailPaddings.x = defaultPadding;
+        thumbnailPaddings.y = defaultPadding;
+        return thumbnailPaddings;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index dc475f6..3a7aa85 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -158,19 +158,19 @@
     /**
      * The user that the backup is activated by default for.
      *
-     * If there is a {@link UserManager#getMainUser()}, this will be that user. If not, it will be
-     * {@link UserHandle#USER_SYSTEM}.
+     * <p>If there is a {@link UserManager#getMainUser()}, this will be that user. If not, it will
+     * be {@link UserHandle#USER_SYSTEM}.
+     *
+     * <p>Note: on the first ever boot of a new device, this might change once the first user is
+     * unlocked. See {@link #updateDefaultBackupUserIdIfNeeded()}.
      *
      * @see #isBackupActivatedForUser(int)
      */
-    @UserIdInt private final int mDefaultBackupUserId;
+    @UserIdInt private int mDefaultBackupUserId;
+
+    private boolean mHasFirstUserUnlockedSinceBoot = false;
 
     public BackupManagerService(Context context) {
-        this(context, new SparseArray<>());
-    }
-
-    @VisibleForTesting
-    BackupManagerService(Context context, SparseArray<UserBackupManagerService> userServices) {
         mContext = context;
         mGlobalDisable = isBackupDisabled();
         HandlerThread handlerThread =
@@ -178,7 +178,7 @@
         handlerThread.start();
         mHandler = new Handler(handlerThread.getLooper());
         mUserManager = UserManager.get(context);
-        mUserServices = userServices;
+        mUserServices = new SparseArray<>();
         Set<ComponentName> transportWhitelist =
                 SystemConfig.getInstance().getBackupTransportWhitelist();
         mTransportWhitelist = (transportWhitelist == null) ? emptySet() : transportWhitelist;
@@ -186,6 +186,9 @@
                 mUserRemovedReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
         UserHandle mainUser = getUserManager().getMainUser();
         mDefaultBackupUserId = mainUser == null ? UserHandle.USER_SYSTEM : mainUser.getIdentifier();
+        if (DEBUG) {
+            Slog.d(TAG, "Default backup user id = " + mDefaultBackupUserId);
+        }
     }
 
     // TODO: Remove this when we implement DI by injecting in the construtor.
@@ -361,17 +364,6 @@
     }
 
     /**
-     * Called from {@link BackupManagerService.Lifecycle} when a user {@code userId} is unlocked.
-     * Starts the backup service for this user if backup is active for this user. Offloads work onto
-     * the handler thread {@link #mHandlerThread} to keep unlock time low since backup is not
-     * essential for device functioning.
-     */
-    @VisibleForTesting
-    void onUnlockUser(int userId) {
-        postToHandler(() -> startServiceForUser(userId));
-    }
-
-    /**
      * Starts the backup service for user {@code userId} by creating a new instance of {@link
      * UserBackupManagerService} and registering it with this service.
      */
@@ -1687,7 +1679,15 @@
 
         @Override
         public void onUserUnlocking(@NonNull TargetUser user) {
-            sInstance.onUnlockUser(user.getUserIdentifier());
+            // Starts the backup service for this user if backup is active for this user. Offloads
+            // work onto the handler thread {@link #mHandlerThread} to keep unlock time low since
+            // backup is not essential for device functioning.
+            sInstance.postToHandler(
+                    () -> {
+                        sInstance.updateDefaultBackupUserIdIfNeeded();
+                        sInstance.startServiceForUser(user.getUserIdentifier());
+                        sInstance.mHasFirstUserUnlockedSinceBoot = true;
+                    });
         }
 
         @Override
@@ -1700,4 +1700,42 @@
             publishBinderService(name, service);
         }
     }
+
+    /**
+     * On the first ever boot of a new device, the 'main' user might not exist for a short period of
+     * time and be created after {@link BackupManagerService} is created. In this case the {@link
+     * #mDefaultBackupUserId} will be the system user initially, but we need to change it to the
+     * newly created {@link UserManager#getMainUser()} later.
+     *
+     * <p>{@link Lifecycle#onUserUnlocking(SystemService.TargetUser)} (for any user) is the earliest
+     * point where we know that a main user (if there is going to be one) is created.
+     */
+    private void updateDefaultBackupUserIdIfNeeded() {
+        // The default user can only change before any user unlocks since boot, and it will only
+        // change from the system user to a non-system user.
+        if (mHasFirstUserUnlockedSinceBoot || mDefaultBackupUserId != UserHandle.USER_SYSTEM) {
+            return;
+        }
+
+        UserHandle mainUser = getUserManager().getMainUser();
+        if (mainUser == null) {
+            return;
+        }
+
+        if (mDefaultBackupUserId != mainUser.getIdentifier()) {
+            int oldDefaultBackupUserId = mDefaultBackupUserId;
+            mDefaultBackupUserId = mainUser.getIdentifier();
+            // We don't expect the service to be started for the old default user but we attempt to
+            // stop its service to be safe.
+            if (!isBackupActivatedForUser(oldDefaultBackupUserId)) {
+                stopServiceForUser(oldDefaultBackupUserId);
+            }
+            Slog.i(
+                    TAG,
+                    "Default backup user changed from "
+                            + oldDefaultBackupUserId
+                            + " to "
+                            + mDefaultBackupUserId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 9d07365..2992bf9 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -81,6 +81,7 @@
 import android.util.apk.ApkSigningBlockUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.expresslog.Histogram;
 import com.android.internal.os.IBinaryTransparencyService;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.pm.ApexManager;
@@ -141,6 +142,10 @@
 
     private static final boolean DEBUG = false;     // toggle this for local debug
 
+    private static final Histogram digestAllPackagesLatency = new Histogram(
+            "binary_transparency.value_digest_all_packages_latency_uniform",
+            new Histogram.UniformOptions(50, 0, 500));
+
     private final Context mContext;
     private String mVbmetaDigest;
     // the system time (in ms) the last measurement was taken
@@ -350,8 +355,9 @@
                     writeAppInfoToLog(appInfo);
                 }
             }
+            long timeSpentMeasuring = System.currentTimeMillis() - currentTimeMs;
+            digestAllPackagesLatency.logSample(timeSpentMeasuring);
             if (DEBUG) {
-                long timeSpentMeasuring = System.currentTimeMillis() - currentTimeMs;
                 Slog.d(TAG, "Measured " + packagesMeasured.size()
                         + " packages altogether in " + timeSpentMeasuring + "ms");
             }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a66e598..57a0713 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -416,6 +416,11 @@
             LinkCapacityEstimate.INVALID, LinkCapacityEstimate.INVALID)));
     private List<List<LinkCapacityEstimate>> mLinkCapacityEstimateLists;
 
+    private int[] mECBMReason;
+    private boolean[] mECBMStarted;
+    private int[] mSCBMReason;
+    private boolean[] mSCBMStarted;
+
     /**
      * Per-phone map of precise data connection state. The key of the map is the pair of transport
      * type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -556,7 +561,8 @@
         return events.contains(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED)
                 || events.contains(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
                 || events.contains(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
-                || events.contains(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED);
+                || events.contains(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED)
+                || events.contains(TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
     }
 
     private static final int MSG_USER_SWITCHED = 1;
@@ -707,7 +713,10 @@
             mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones);
             mAllowedNetworkTypeReason = copyOf(mAllowedNetworkTypeReason, mNumPhones);
             mAllowedNetworkTypeValue = copyOf(mAllowedNetworkTypeValue, mNumPhones);
-
+            mECBMReason = copyOf(mECBMReason, mNumPhones);
+            mECBMStarted = copyOf(mECBMStarted, mNumPhones);
+            mSCBMReason = copyOf(mSCBMReason, mNumPhones);
+            mSCBMStarted = copyOf(mSCBMStarted, mNumPhones);
             // ds -> ss switch.
             if (mNumPhones < oldNumPhones) {
                 cutListToSize(mCellInfo, mNumPhones);
@@ -762,6 +771,10 @@
                 mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
                 mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
                 mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
+                mECBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
+                mECBMStarted[i] = false;
+                mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
+                mSCBMStarted[i] = false;
             }
         }
     }
@@ -831,6 +844,10 @@
         mLinkCapacityEstimateLists = new ArrayList<>();
         mCarrierPrivilegeStates = new ArrayList<>();
         mCarrierServiceStates = new ArrayList<>();
+        mECBMReason = new int[numPhones];
+        mECBMStarted = new boolean[numPhones];
+        mSCBMReason = new int[numPhones];
+        mSCBMStarted = new boolean[numPhones];
 
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
@@ -870,6 +887,10 @@
             mLinkCapacityEstimateLists.add(i, INVALID_LCE_LIST);
             mCarrierPrivilegeStates.add(i, new Pair<>(Collections.emptyList(), new int[0]));
             mCarrierServiceStates.add(i, new Pair<>(null, Process.INVALID_UID));
+            mECBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
+            mECBMStarted[i] = false;
+            mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
+            mSCBMStarted[i] = false;
         }
 
         mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1441,6 +1462,31 @@
                         }
                     }
                 }
+                if (events.contains(TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED)) {
+                    try {
+                        boolean ecbmStarted = mECBMStarted[r.phoneId];
+                        if (ecbmStarted) {
+                            r.callback.onCallBackModeStarted(
+                                    TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL);
+                        } else {
+                            r.callback.onCallBackModeStopped(
+                                    TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL,
+                                    mECBMReason[r.phoneId]);
+                        }
+
+                        boolean scbmStarted = mSCBMStarted[r.phoneId];
+                        if (scbmStarted) {
+                            r.callback.onCallBackModeStarted(
+                                    TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS);
+                        } else {
+                            r.callback.onCallBackModeStopped(
+                                    TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS,
+                                    mSCBMReason[r.phoneId]);
+                        }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
+                }
             }
         }
     }
@@ -3258,6 +3304,72 @@
         }
     }
 
+    @Override
+    public void notifyCallbackModeStarted(int phoneId, int subId, int type) {
+        if (!checkNotifyPermission("notifyCallbackModeStarted()")) {
+            return;
+        }
+        if (VDBG) {
+            log("notifyCallbackModeStarted: phoneId=" + phoneId + ", subId=" + subId
+                    + ", type=" + type);
+        }
+        synchronized (mRecords) {
+            if (validatePhoneId(phoneId)) {
+                if (type == TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL) {
+                    mECBMStarted[phoneId] = true;
+                } else if (type == TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS) {
+                    mSCBMStarted[phoneId] = true;
+                }
+            }
+            for (Record r : mRecords) {
+                // Send to all listeners regardless of subscription
+                if (r.matchTelephonyCallbackEvent(
+                        TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED)) {
+                    try {
+                        r.callback.onCallBackModeStarted(type);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+        }
+        handleRemoveListLocked();
+    }
+
+    @Override
+    public void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason) {
+        if (!checkNotifyPermission("notifyCallbackModeStopped()")) {
+            return;
+        }
+        if (VDBG) {
+            log("notifyCallbackModeStopped: phoneId=" + phoneId + ", subId=" + subId
+                    + ", type=" + type + ", reason=" + reason);
+        }
+        synchronized (mRecords) {
+            if (validatePhoneId(phoneId)) {
+                if (type == TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL) {
+                    mECBMStarted[phoneId] = false;
+                    mECBMReason[phoneId] = reason;
+                } else if (type == TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS) {
+                    mSCBMStarted[phoneId] = false;
+                    mSCBMReason[phoneId] = reason;
+                }
+            }
+            for (Record r : mRecords) {
+                // Send to all listeners regardless of subscription
+                if (r.matchTelephonyCallbackEvent(
+                        TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED)) {
+                    try {
+                        r.callback.onCallBackModeStopped(type, reason);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+        }
+        handleRemoveListLocked();
+    }
+
     @NeverCompile // Avoid size overhead of debugging code.
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -3307,6 +3419,11 @@
                 pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
                 pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs.get(i));
                 pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i));
+                pw.println("mECBMReason=" + mECBMReason[i]);
+                pw.println("mECBMStarted=" + mECBMStarted[i]);
+                pw.println("mSCBMReason=" + mSCBMReason[i]);
+                pw.println("mSCBMStarted=" + mSCBMStarted[i]);
+
                 // We need to obfuscate package names, and primitive arrays' native toString is ugly
                 Pair<List<String>, int[]> carrierPrivilegeState = mCarrierPrivilegeStates.get(i);
                 pw.println(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f0931ca..7da8869 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -102,6 +102,8 @@
 import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
+import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NEW_MUTABLE_IMPLICIT_PENDING_INTENT_RETRIEVED;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALLOWLISTS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
@@ -5581,6 +5583,25 @@
                         throw new IllegalArgumentException(
                                 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
                     }
+                    if (PendingIntent.isNewMutableDisallowedImplicitPendingIntent(flags, intent)) {
+                        boolean isChangeEnabled = CompatChanges.isChangeEnabled(
+                                        PendingIntent.BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT,
+                                        owningUid);
+                        logUnsafeMutableImplicitPi(packageName, resolvedTypes, owningUid, i, intent,
+                                isChangeEnabled);
+                        if (isChangeEnabled) {
+                            String msg = packageName + ": Targeting U+ (version "
+                                    + Build.VERSION_CODES.UPSIDE_DOWN_CAKE + " and above) disallows"
+                                    + " creating or retrieving a PendingIntent with FLAG_MUTABLE,"
+                                    + " an implicit Intent within and without FLAG_NO_CREATE and"
+                                    + " FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT for"
+                                    + " security reasons. To retrieve an already existing"
+                                    + " PendingIntent, use FLAG_NO_CREATE, however, to create a"
+                                    + " new PendingIntent with an implicit Intent use"
+                                    + " FLAG_IMMUTABLE.";
+                            throw new IllegalArgumentException(msg);
+                        }
+                    }
                     intents[i] = new Intent(intent);
                 }
             }
@@ -5633,6 +5654,24 @@
         }
     }
 
+    private void logUnsafeMutableImplicitPi(String packageName, String[] resolvedTypes,
+            int owningUid, int i, Intent intent, boolean isChangeEnabled) {
+        String[] categories = intent.getCategories() == null ? new String[0]
+                : intent.getCategories().toArray(String[]::new);
+        String resolvedType = resolvedTypes == null || i >= resolvedTypes.length ? null
+                : resolvedTypes[i];
+        FrameworkStatsLog.write(UNSAFE_INTENT_EVENT_REPORTED,
+                UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NEW_MUTABLE_IMPLICIT_PENDING_INTENT_RETRIEVED,
+                owningUid,
+                null,
+                packageName,
+                intent.getAction(),
+                categories,
+                resolvedType,
+                intent.getScheme(),
+                isChangeEnabled);
+    }
+
     @Override
     public int sendIntentSender(IApplicationThread caller, IIntentSender target,
             IBinder allowlistToken, int code, Intent intent, String resolvedType,
@@ -12909,7 +12948,7 @@
                     callingUid);
             String[] categories = intent.getCategories() == null ? new String[0]
                     : intent.getCategories().toArray(String[]::new);
-            FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
+            FrameworkStatsLog.write(UNSAFE_INTENT_EVENT_REPORTED,
                     FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__INTERNAL_NON_EXPORTED_COMPONENT_MATCH,
                     callingUid,
                     componentInfo,
@@ -14259,6 +14298,21 @@
         // Ensure all internal loopers are registered for idle checks
         BroadcastLoopers.addMyLooper();
 
+        if (Process.isSdkSandboxUid(realCallingUid)) {
+            final SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
+                    SdkSandboxManagerLocal.class);
+            if (sdkSandboxManagerLocal == null) {
+                throw new IllegalStateException("SdkSandboxManagerLocal not found when sending"
+                        + " a broadcast from an SDK sandbox uid.");
+            }
+            if (!sdkSandboxManagerLocal.canSendBroadcast(intent)) {
+                throw new SecurityException(
+                        "Intent " + intent.getAction() + " may not be broadcast from an SDK sandbox"
+                        + " uid. Given caller package " + callerPackage + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ")");
+            }
+        }
+
         if ((resultTo != null) && (resultToApp == null)) {
             if (resultTo.asBinder() instanceof BinderProxy) {
                 // Warn when requesting results without a way to deliver them
@@ -14463,16 +14517,6 @@
             }
         }
 
-        if (Process.isSdkSandboxUid(realCallingUid)) {
-            SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
-                    SdkSandboxManagerLocal.class);
-            if (sdkSandboxManagerLocal == null) {
-                throw new IllegalStateException("SdkSandboxManagerLocal not found when sending"
-                    + " a broadcast from an SDK sandbox uid.");
-            }
-            sdkSandboxManagerLocal.enforceAllowedToSendBroadcast(intent);
-        }
-
         boolean timeoutExempt = false;
 
         if (action != null) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index dd49730..b5b86e0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4032,10 +4032,10 @@
         vgs.adjustVolume(direction, flags);
     }
 
-    /** @see AudioManager#getLastAudibleVolumeGroupVolume(int) */
+    /** @see AudioManager#getLastAudibleVolumeForVolumeGroup(int) */
     @android.annotation.EnforcePermission(android.Manifest.permission.QUERY_AUDIO_STATE)
-    public int getLastAudibleVolumeGroupVolume(int groupId) {
-        super.getLastAudibleVolumeGroupVolume_enforcePermission();
+    public int getLastAudibleVolumeForVolumeGroup(int groupId) {
+        super.getLastAudibleVolumeForVolumeGroup_enforcePermission();
         synchronized (VolumeStreamState.class) {
             if (sVolumeGroupStates.indexOfKey(groupId) < 0) {
                 Log.e(TAG, ": no volume group found for id " + groupId);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 0a4b5b0..d26968a 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -3236,10 +3236,7 @@
 
         @Override
         public boolean supportsFrameRateOverride() {
-            return SurfaceFlingerProperties.enable_frame_rate_override().orElse(true)
-                            && !SurfaceFlingerProperties.frame_rate_override_for_native_rates()
-                                    .orElse(false)
-                            && SurfaceFlingerProperties.frame_rate_override_global().orElse(true);
+            return SurfaceFlingerProperties.enable_frame_rate_override().orElse(true);
         }
 
         private DisplayManager getDisplayManager() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f5ca8aa..82e6e30 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1882,6 +1882,10 @@
                     ? BrightnessEvent.FLAG_USER_SET : 0));
             Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
 
+            // Log all events which are not temporary
+            if (newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
+                logBrightnessEvent(newEvent, unthrottledBrightnessState);
+            }
             if (userSetBrightnessChanged) {
                 logManualBrightnessEvent(newEvent);
             }
@@ -2976,6 +2980,154 @@
         }
     }
 
+    // Return bucket index of range_[left]_[right] where
+    // left <= nits < right
+    private int nitsToRangeIndex(float nits) {
+        float[] boundaries = {
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
+            90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
+            1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+        int[] rangeIndex = {
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_UNKNOWN,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_0_1,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1_2,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2_3,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3_4,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_4_5,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_5_6,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_6_7,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_7_8,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_8_9,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_9_10,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_10_20,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_20_30,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_30_40,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_40_50,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_50_60,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_60_70,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_70_80,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_80_90,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_90_100,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_100_200,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_200_300,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_300_400,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_400_500,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_500_600,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_600_700,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_700_800,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_800_900,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_900_1000,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1000_1200,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1200_1400,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1400_1600,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1600_1800,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1800_2000,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2000_2250,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2250_2500,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2500_2750,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2750_3000,
+        };
+        for (int i = 0; i < boundaries.length; i++) {
+            if (nits < boundaries[i]) {
+                return rangeIndex[i];
+            }
+        }
+        return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3000_INF;
+    }
+
+    private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
+        switch(brightnessReason) {
+            case BrightnessReason.REASON_UNKNOWN:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
+            case BrightnessReason.REASON_MANUAL:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_MANUAL;
+            case BrightnessReason.REASON_DOZE:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE;
+            case BrightnessReason.REASON_DOZE_DEFAULT:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE_DEFAULT;
+            case BrightnessReason.REASON_AUTOMATIC:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_AUTOMATIC;
+            case BrightnessReason.REASON_SCREEN_OFF:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF;
+            case BrightnessReason.REASON_OVERRIDE:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_OVERRIDE;
+            case BrightnessReason.REASON_TEMPORARY:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_TEMPORARY;
+            case BrightnessReason.REASON_BOOST:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_BOOST;
+            case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
+            case BrightnessReason.REASON_FOLLOWER:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_FOLLOWER;
+        }
+        return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
+    }
+
+    private int convertHbmModeToStatsEnum(int mode) {
+        switch(mode) {
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_SUNLIGHT;
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_HDR;
+        }
+        return FrameworkStatsLog
+            .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
+    }
+
+    // unmodifiedBrightness: the brightness value that has not been
+    // modified by any modifiers(dimming/throttling/low-power-mode)
+    private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
+        int modifier = event.getReason().getModifier();
+        // It's easier to check if the brightness is at maximum level using the brightness
+        // value untouched by any modifiers
+        boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
+        float brightnessInNits = convertToNits(event.getBrightness());
+        float lowPowerModeFactor = event.getPowerFactor();
+        int rbcStrength  = event.getRbcStrength();
+        float hbmMaxNits = convertToNits(event.getHbmMax());
+        float thermalCapNits = convertToNits(event.getThermalMax());
+
+        if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
+                && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
+                    .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
+            FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2,
+                    event.getPhysicalDisplayId().hashCode(),
+                    brightnessInNits,
+                    convertToNits(unmodifiedBrightness),
+                    nitsToRangeIndex(brightnessInNits),
+                    brightnessIsMax,
+                    (event.getFlags() & BrightnessEvent.FLAG_USER_SET) > 0,
+                    convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
+                    convertHbmModeToStatsEnum(event.getHbmMode()),
+                    (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
+                    (modifier & BrightnessReason.MODIFIER_THROTTLED) > 0,
+                    event.isRbcEnabled(),
+                    event.getLux(),
+                    event.wasShortTermModelActive(),
+                    lowPowerModeFactor,
+                    rbcStrength,
+                    hbmMaxNits,
+                    thermalCapNits,
+                    event.isAutomaticBrightnessEnabled());
+        }
+    }
+
     private void logManualBrightnessEvent(BrightnessEvent event) {
         float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f;
         int appliedRbcStrength  = event.isRbcEnabled() ? event.getRbcStrength() : -1;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 5667ddf..39bc09e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1595,6 +1595,10 @@
                     ? BrightnessEvent.FLAG_USER_SET : 0));
             Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
 
+            // Log all events which are not temporary
+            if (newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
+                logBrightnessEvent(newEvent, unthrottledBrightnessState);
+            }
             if (userSetBrightnessChanged) {
                 logManualBrightnessEvent(newEvent);
             }
@@ -2512,6 +2516,154 @@
         }
     }
 
+    // Return bucket index of range_[left]_[right] where
+    // left <= nits < right
+    private int nitsToRangeIndex(float nits) {
+        float[] boundaries = {
+            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
+            90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
+            1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+        int[] rangeIndex = {
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_UNKNOWN,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_0_1,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1_2,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2_3,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3_4,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_4_5,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_5_6,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_6_7,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_7_8,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_8_9,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_9_10,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_10_20,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_20_30,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_30_40,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_40_50,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_50_60,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_60_70,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_70_80,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_80_90,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_90_100,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_100_200,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_200_300,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_300_400,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_400_500,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_500_600,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_600_700,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_700_800,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_800_900,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_900_1000,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1000_1200,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1200_1400,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1400_1600,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1600_1800,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_1800_2000,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2000_2250,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2250_2500,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2500_2750,
+            FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_2750_3000,
+        };
+        for (int i = 0; i < boundaries.length; i++) {
+            if (nits < boundaries[i]) {
+                return rangeIndex[i];
+            }
+        }
+        return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__BUCKET_INDEX__RANGE_3000_INF;
+    }
+
+    private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
+        switch(brightnessReason) {
+            case BrightnessReason.REASON_UNKNOWN:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
+            case BrightnessReason.REASON_MANUAL:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_MANUAL;
+            case BrightnessReason.REASON_DOZE:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE;
+            case BrightnessReason.REASON_DOZE_DEFAULT:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_DOZE_DEFAULT;
+            case BrightnessReason.REASON_AUTOMATIC:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_AUTOMATIC;
+            case BrightnessReason.REASON_SCREEN_OFF:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF;
+            case BrightnessReason.REASON_OVERRIDE:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_OVERRIDE;
+            case BrightnessReason.REASON_TEMPORARY:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_TEMPORARY;
+            case BrightnessReason.REASON_BOOST:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_BOOST;
+            case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
+            case BrightnessReason.REASON_FOLLOWER:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_FOLLOWER;
+        }
+        return FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2__REASON__REASON_UNKNOWN;
+    }
+
+    private int convertHbmModeToStatsEnum(int mode) {
+        switch(mode) {
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_SUNLIGHT;
+            case BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR:
+                return FrameworkStatsLog
+                    .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_HDR;
+        }
+        return FrameworkStatsLog
+            .SCREEN_BRIGHTNESS_CHANGED_V2__HBM_MODE__HIGH_BRIGHTNESS_MODE_OFF;
+    }
+
+    // unmodifiedBrightness: the brightness value that has not been
+    // modified by any modifiers(dimming/throttling/low-power-mode)
+    private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
+        int modifier = event.getReason().getModifier();
+        // It's easier to check if the brightness is at maximum level using the brightness
+        // value untouched by any modifiers
+        boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
+        float brightnessInNits = convertToNits(event.getBrightness());
+        float lowPowerModeFactor = event.getPowerFactor();
+        int rbcStrength  = event.getRbcStrength();
+        float hbmMaxNits = convertToNits(event.getHbmMax());
+        float thermalCapNits = convertToNits(event.getThermalMax());
+
+        if (mLogicalDisplay.getPrimaryDisplayDeviceLocked() != null
+                && mLogicalDisplay.getPrimaryDisplayDeviceLocked()
+                    .getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL) {
+            FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED_V2,
+                    event.getPhysicalDisplayId().hashCode(),
+                    brightnessInNits,
+                    convertToNits(unmodifiedBrightness),
+                    nitsToRangeIndex(brightnessInNits),
+                    brightnessIsMax,
+                    (event.getFlags() & BrightnessEvent.FLAG_USER_SET) > 0,
+                    convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
+                    convertHbmModeToStatsEnum(event.getHbmMode()),
+                    (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
+                    (modifier & BrightnessReason.MODIFIER_THROTTLED) > 0,
+                    event.isRbcEnabled(),
+                    event.getLux(),
+                    event.wasShortTermModelActive(),
+                    lowPowerModeFactor,
+                    rbcStrength,
+                    hbmMaxNits,
+                    thermalCapNits,
+                    event.isAutomaticBrightnessEnabled());
+        }
+    }
+
     private final class DisplayControllerHandler extends Handler {
         DisplayControllerHandler(Looper looper) {
             super(looper, null, true /*async*/);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 149a915..ce2656b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -103,7 +103,6 @@
 import android.security.KeyStore;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.security.keystore.UserNotAuthenticatedException;
 import android.security.keystore.recovery.KeyChainProtectionParams;
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.RecoveryCertPath;
@@ -788,31 +787,12 @@
         }
     }
 
-    /**
-     * Check if profile got unlocked but the keystore is still locked. This happens on full disk
-     * encryption devices since the profile may not yet be running when we consider unlocking it
-     * during the normal flow. In this case unlock the keystore for the profile.
-     */
-    private void ensureProfileKeystoreUnlocked(int userId) {
-        final KeyStore ks = KeyStore.getInstance();
-        if (ks.state(userId) == KeyStore.State.LOCKED
-                && isCredentialSharableWithParent(userId)
-                && hasUnifiedChallenge(userId)) {
-            Slog.i(TAG, "Profile got unlocked, will unlock its keystore");
-            // If boot took too long and the password in vold got expired, parent keystore will
-            // be still locked, we ignore this case since the user will be prompted to unlock
-            // the device after boot.
-            unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */);
-        }
-    }
-
     private void onUnlockUser(final int userId) {
         // Perform tasks which require locks in LSS on a handler, as we are callbacks from
         // ActivityManager.unlockUser()
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                ensureProfileKeystoreUnlocked(userId);
                 // Hide notification first, as tie managed profile lock takes time
                 hideEncryptionNotification(new UserHandle(userId));
 
@@ -1335,7 +1315,7 @@
         return credential;
     }
 
-    private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated) {
+    private void unlockChildProfile(int profileHandle) {
         try {
             doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
                     profileHandle, null /* progressCallback */, 0 /* flags */);
@@ -1345,8 +1325,6 @@
                 | BadPaddingException | CertificateException | IOException e) {
             if (e instanceof FileNotFoundException) {
                 Slog.i(TAG, "Child profile key not found");
-            } else if (ignoreUserNotAuthenticated && e instanceof UserNotAuthenticatedException) {
-                Slog.i(TAG, "Parent keystore seems locked, ignoring");
             } else {
                 Slog.e(TAG, "Failed to decrypt child profile key", e);
             }
@@ -1410,7 +1388,7 @@
             if (hasUnifiedChallenge(profile.id)) {
                 if (mUserManager.isUserRunning(profile.id)) {
                     // Unlock profile with unified lock
-                    unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */);
+                    unlockChildProfile(profile.id);
                 } else {
                     try {
                         // Profile not ready for unlock yet, but decrypt the unified challenge now
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 27d2527..bba1dbe 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -22,6 +22,7 @@
 import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
 import static android.app.Notification.FLAG_BUBBLE;
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
+import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
 import static android.app.Notification.FLAG_INSISTENT;
 import static android.app.Notification.FLAG_NO_CLEAR;
 import static android.app.Notification.FLAG_NO_DISMISS;
@@ -175,6 +176,7 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.LoggingOnly;
+import android.content.AttributionSource;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProvider;
@@ -226,6 +228,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.VibrationEffect;
+import android.permission.PermissionCheckerManager;
+import android.permission.PermissionManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
@@ -528,6 +532,7 @@
     private IPackageManager mPackageManager;
     private PackageManager mPackageManagerClient;
     PackageManagerInternal mPackageManagerInternal;
+    private PermissionManager mPermissionManager;
     private PermissionPolicyInternal mPermissionPolicyInternal;
     AudioManager mAudioManager;
     AudioManagerInternal mAudioManagerInternal;
@@ -2226,7 +2231,8 @@
             MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper,
             UsageStatsManagerInternal usageStatsManagerInternal,
             TelecomManager telecomManager, NotificationChannelLogger channelLogger,
-            SystemUiSystemPropertiesFlags.FlagResolver flagResolver) {
+            SystemUiSystemPropertiesFlags.FlagResolver flagResolver,
+            PermissionManager permissionManager) {
         mHandler = handler;
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2243,6 +2249,7 @@
         mPackageManager = packageManager;
         mPackageManagerClient = packageManagerClient;
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+        mPermissionManager = permissionManager;
         mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
         mUmInternal = LocalServices.getService(UserManagerInternal.class);
         mUsageStatsManagerInternal = usageStatsManagerInternal;
@@ -2557,7 +2564,8 @@
                         AppGlobals.getPermissionManager()),
                 LocalServices.getService(UsageStatsManagerInternal.class),
                 getContext().getSystemService(TelecomManager.class),
-                new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver());
+                new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver(),
+                getContext().getSystemService(PermissionManager.class));
 
         publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
                 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL);
@@ -6687,10 +6695,21 @@
         handleSavePolicyFile();
     }
 
+    private void makeStickyHun(Notification notification) {
+        notification.flags |= FLAG_FSI_REQUESTED_BUT_DENIED;
+        if (notification.contentIntent == null) {
+            // On notification click, if contentIntent is null, SystemUI launches the
+            // fullScreenIntent instead.
+            notification.contentIntent = notification.fullScreenIntent;
+        }
+        notification.fullScreenIntent = null;
+    }
+
     @VisibleForTesting
     protected void fixNotification(Notification notification, String pkg, String tag, int id,
             @UserIdInt int userId, int notificationUid) throws NameNotFoundException,
             RemoteException {
+
         final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
                 pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                 (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
@@ -6728,13 +6747,40 @@
             }
         }
 
+        notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
+
         if (notification.fullScreenIntent != null && ai.targetSdkVersion >= Build.VERSION_CODES.Q) {
-            int fullscreenIntentPermission = getContext().checkPermission(
-                    android.Manifest.permission.USE_FULL_SCREEN_INTENT, -1, notificationUid);
-            if (fullscreenIntentPermission != PERMISSION_GRANTED) {
-                notification.fullScreenIntent = null;
-                Slog.w(TAG, "Package " + pkg +
-                        ": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission");
+            final boolean forceDemoteFsiToStickyHun = mFlagResolver.isEnabled(
+                    SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE);
+
+            final boolean showStickyHunIfDenied = mFlagResolver.isEnabled(
+                    SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI);
+
+            if (forceDemoteFsiToStickyHun) {
+                makeStickyHun(notification);
+
+            } else if (showStickyHunIfDenied) {
+
+                final AttributionSource source = new AttributionSource.Builder(notificationUid)
+                        .setPackageName(pkg)
+                        .build();
+
+                final int permissionResult = mPermissionManager.checkPermissionForDataDelivery(
+                        Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null);
+
+                if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) {
+                    makeStickyHun(notification);
+                }
+
+            } else {
+                int fullscreenIntentPermission = getContext().checkPermission(
+                        android.Manifest.permission.USE_FULL_SCREEN_INTENT, -1, notificationUid);
+
+                if (fullscreenIntentPermission != PERMISSION_GRANTED) {
+                    notification.fullScreenIntent = null;
+                    Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the"
+                            + "USE_FULL_SCREEN_INTENT permission");
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index b1c6f8c..2e86df8 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -485,18 +485,22 @@
             String packageName, int userId) throws PackageManagerException {
         final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
         if (packageState == null) {
-            throw new PackageManagerException("Package " + packageName + " is unknown");
+            throw PackageManagerException.ofInternalError("Package " + packageName + " is unknown",
+                    PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_PACKAGE_UNKNOWN);
         } else if (!TextUtils.equals(volumeUuid, packageState.getVolumeUuid())) {
-            throw new PackageManagerException(
+            throw PackageManagerException.ofInternalError(
                     "Package " + packageName + " found on unknown volume " + volumeUuid
-                            + "; expected volume " + packageState.getVolumeUuid());
+                            + "; expected volume " + packageState.getVolumeUuid(),
+                    PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_VOLUME_UNKNOWN);
         } else if (!packageState.getUserStateOrDefault(userId).isInstalled()) {
-            throw new PackageManagerException(
-                    "Package " + packageName + " not installed for user " + userId);
+            throw PackageManagerException.ofInternalError(
+                    "Package " + packageName + " not installed for user " + userId,
+                    PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_NOT_INSTALLED_FOR_USER);
         } else if (packageState.getPkg() != null
                 && !shouldHaveAppStorage(packageState.getPkg())) {
-            throw new PackageManagerException(
-                    "Package " + packageName + " shouldn't have storage");
+            throw PackageManagerException.ofInternalError(
+                    "Package " + packageName + " shouldn't have storage",
+                    PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_SHOULD_NOT_HAVE_STORAGE);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/BroadcastHelper.java b/services/core/java/com/android/server/pm/BroadcastHelper.java
index 1823a39..c1171fa 100644
--- a/services/core/java/com/android/server/pm/BroadcastHelper.java
+++ b/services/core/java/com/android/server/pm/BroadcastHelper.java
@@ -18,7 +18,6 @@
 
 import static android.os.PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED;
 import static android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED;
 
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
@@ -392,8 +391,7 @@
     /** Returns whether the Safety Label Change notification, a privacy feature, is enabled. */
     public static boolean isPrivacySafetyLabelChangeNotificationsEnabled() {
         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-                SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false) && DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_PRIVACY, PERMISSION_RATIONALE_ENABLED, false);
+                SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false);
     }
 
     @NonNull
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 9ec68da..cd70394 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -24,7 +24,6 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP;
-import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
 import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
@@ -1490,8 +1489,9 @@
             synchronized (mPm.mLock) {
                 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
                 if (ps == null) {
-                    request.setError(INSTALL_FAILED_INTERNAL_ERROR,
-                            "Missing settings for moved package " + pkgName);
+                    request.setError(PackageManagerException.ofInternalError(
+                            "Missing settings for moved package " + pkgName,
+                            PackageManagerException.INTERNAL_ERROR_MISSING_SETTING_FOR_MOVE));
                 }
 
                 // We moved the entire application as-is, so bring over the
@@ -1523,8 +1523,9 @@
                 derivedAbi.second.applyTo(parsedPackage);
             } catch (PackageManagerException pme) {
                 Slog.e(TAG, "Error deriving application ABI", pme);
-                throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
-                        "Error deriving application ABI: " + pme.getMessage());
+                throw PrepareFailure.ofInternalError(
+                        "Error deriving application ABI: " + pme.getMessage(),
+                        PackageManagerException.INTERNAL_ERROR_DERIVING_ABI);
             }
         }
 
@@ -1535,8 +1536,9 @@
                 setUpFsVerity(parsedPackage);
             } catch (Installer.InstallerException | IOException | DigestException
                     | NoSuchAlgorithmException e) {
-                throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
-                        "Failed to set up verity: " + e);
+                throw PrepareFailure.ofInternalError(
+                        "Failed to set up verity: " + e,
+                        PackageManagerException.INTERNAL_ERROR_VERITY_SETUP);
             }
         } else {
             // Use the path returned by apexd
@@ -3215,8 +3217,9 @@
         // uncompress the binary to its eventual destination on /data
         final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath());
         if (scanFile == null) {
-            throw new PackageManagerException(
-                    "Unable to decompress stub at " + stubPkg.getPath());
+            throw PackageManagerException.ofInternalError(
+                    "Unable to decompress stub at " + stubPkg.getPath(),
+                    PackageManagerException.INTERNAL_ERROR_DECOMPRESS_STUB);
         }
         synchronized (mPm.mLock) {
             mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
@@ -4174,10 +4177,12 @@
             // This is relevant for cases where the disabled system package is used for flags or
             // other metadata.
             parsedPackage.hideAsFinal();
-            throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName()
+            throw PackageManagerException.ofInternalError(
+                    "Package " + parsedPackage.getPackageName()
                     + " at " + parsedPackage.getPath() + " ignored: updated version "
                     + (pkgAlreadyExists ? String.valueOf(pkgSetting.getVersionCode()) : "unknown")
-                    + " better than this " + parsedPackage.getLongVersionCode());
+                    + " better than this " + parsedPackage.getLongVersionCode(),
+                    PackageManagerException.INTERNAL_ERROR_UPDATED_VERSION_BETTER_THAN_SYSTEM);
         }
 
         // Verify certificates against what was last scanned. Force re-collecting certificate in two
@@ -4449,8 +4454,9 @@
                 // but we still want the base name to be unique.
                 if ((scanFlags & SCAN_NEW_INSTALL) == 0
                         && mPm.mPackages.containsKey(pkg.getManifestPackageName())) {
-                    throw new PackageManagerException(
-                            "Duplicate static shared lib provider package");
+                    throw PackageManagerException.ofInternalError(
+                            "Duplicate static shared lib provider package",
+                            PackageManagerException.INTERNAL_ERROR_DUP_STATIC_SHARED_LIB_PROVIDER);
                 }
                 ScanPackageUtils.assertStaticSharedLibraryIsValid(pkg, scanFlags);
                 assertStaticSharedLibraryVersionCodeIsValid(pkg);
@@ -4543,8 +4549,9 @@
         }
         if (pkg.getLongVersionCode() < minVersionCode
                 || pkg.getLongVersionCode() > maxVersionCode) {
-            throw new PackageManagerException("Static shared"
-                    + " lib version codes must be ordered as lib versions");
+            throw PackageManagerException.ofInternalError("Static shared"
+                    + " lib version codes must be ordered as lib versions",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_VERSION_CODES_ORDER);
         }
     }
 
@@ -4559,9 +4566,10 @@
                 // This must be an update to a system overlay. Immutable overlays cannot be
                 // upgraded.
                 if (!mPm.isOverlayMutable(pkg.getPackageName())) {
-                    throw new PackageManagerException("Overlay "
+                    throw PackageManagerException.ofInternalError("Overlay "
                             + pkg.getPackageName()
-                            + " is static and cannot be upgraded.");
+                            + " is static and cannot be upgraded.",
+                            PackageManagerException.INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC);
                 }
             } else {
                 if ((scanFlags & SCAN_AS_VENDOR) != 0) {
@@ -4591,10 +4599,11 @@
                 }
                 if (!comparePackageSignatures(platformPkgSetting,
                         pkg.getSigningDetails().getSignatures())) {
-                    throw new PackageManagerException("Overlay "
+                    throw PackageManagerException.ofInternalError("Overlay "
                             + pkg.getPackageName()
                             + " must target Q or later, "
-                            + "or be signed with the platform certificate");
+                            + "or be signed with the platform certificate",
+                            PackageManagerException.INTERNAL_ERROR_OVERLAY_LOW_TARGET_SDK);
                 }
             }
 
@@ -4615,11 +4624,12 @@
                             pkg.getSigningDetails().getSignatures())) {
                         // check reference signature
                         if (mPm.mOverlayConfigSignaturePackage == null) {
-                            throw new PackageManagerException("Overlay "
+                            throw PackageManagerException.ofInternalError("Overlay "
                                     + pkg.getPackageName() + " and target "
                                     + pkg.getOverlayTarget() + " signed with"
                                     + " different certificates, and the overlay lacks"
-                                    + " <overlay android:targetName>");
+                                    + " <overlay android:targetName>",
+                                    PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE1);
                         }
                         final PackageSetting refPkgSetting;
                         synchronized (mPm.mLock) {
@@ -4628,11 +4638,12 @@
                         }
                         if (!comparePackageSignatures(refPkgSetting,
                                 pkg.getSigningDetails().getSignatures())) {
-                            throw new PackageManagerException("Overlay "
+                            throw PackageManagerException.ofInternalError("Overlay "
                                     + pkg.getPackageName() + " signed with a different "
                                     + "certificate than both the reference package and "
                                     + "target " + pkg.getOverlayTarget() + ", and the "
-                                    + "overlay lacks <overlay android:targetName>");
+                                    + "overlay lacks <overlay android:targetName>",
+                                    PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE2);
                         }
                     }
                 }
@@ -4659,10 +4670,11 @@
                 }
                 if (!comparePackageSignatures(platformPkgSetting,
                         pkg.getSigningDetails().getSignatures())) {
-                    throw new PackageManagerException("Apps that share a user with a "
+                    throw PackageManagerException.ofInternalError("Apps that share a user with a "
                             + "privileged app must themselves be marked as privileged. "
                             + pkg.getPackageName() + " shares privileged user "
-                            + pkg.getSharedUserId() + ".");
+                            + pkg.getSharedUserId() + ".",
+                            PackageManagerException.INTERNAL_ERROR_NOT_PRIV_SHARED_USER);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 1516384..46ea010 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -93,6 +93,7 @@
     @Nullable
     private AndroidPackage mPkg;
     private int mReturnCode;
+    private int mInternalErrorCode;
     @Nullable
     private String mReturnMsg;
     // The set of packages consuming this shared library or null if no consumers exist.
@@ -227,6 +228,10 @@
         return mReturnCode;
     }
 
+    public int getInternalErrorCode() {
+        return mInternalErrorCode;
+    }
+
     @Nullable
     public IPackageInstallObserver2 getObserver() {
         return mInstallArgs == null ? null : mInstallArgs.mObserver;
@@ -635,7 +640,12 @@
         }
     }
 
+    public void setError(PackageManagerException e) {
+        setError(null, e);
+    }
+
     public void setError(String msg, PackageManagerException e) {
+        mInternalErrorCode = e.internalErrorCode;
         mReturnCode = e.error;
         setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e));
         Slog.w(TAG, msg, e);
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index c3cc392..35862db 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -19,7 +19,6 @@
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.content.pm.PackageInstaller.SessionParams.MODE_INHERIT_EXISTING;
 import static android.content.pm.PackageInstaller.SessionParams.USER_ACTION_UNSPECIFIED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_STAGED;
 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -341,11 +340,15 @@
                 handle = NativeLibraryHelper.Handle.create(request.getCodeFile());
                 ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                         request.getAbiOverride(), isIncremental);
+                if (ret != PackageManager.INSTALL_SUCCEEDED) {
+                    final String errorMessage = "Failed to copy native libraries";
+                    request.setError(ret, errorMessage);
+                }
             } catch (IOException e) {
                 final String errorMessage = "Copying native libraries failed";
                 Slog.e(TAG, errorMessage, e);
-                ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-                request.setError(ret, errorMessage);
+                request.setError(PackageManagerException.ofInternalError(errorMessage,
+                        PackageManagerException.INTERNAL_ERROR_NATIVE_LIBRARY_COPY));
             } finally {
                 IoUtils.closeQuietly(handle);
             }
@@ -368,10 +371,10 @@
                         mMoveInfo.mTargetSdkVersion, mMoveInfo.mFromCodePath);
             } catch (Installer.InstallerException e) {
                 final String errorMessage = "Failed to move app";
-                final int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-                request.setError(ret, errorMessage);
+                request.setError(PackageManagerException.ofInternalError(errorMessage,
+                        PackageManagerException.INTERNAL_ERROR_MOVE));
                 Slog.w(TAG, errorMessage, e);
-                return ret;
+                return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
             }
         }
 
@@ -594,13 +597,15 @@
             final File dir = request.getOriginInfo().mResolvedFile;
             final File[] apexes = dir.listFiles();
             if (apexes == null) {
-                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
-                        dir.getAbsolutePath() + " is not a directory");
+                throw PackageManagerException.ofInternalError(
+                        dir.getAbsolutePath() + " is not a directory",
+                        PackageManagerException.INTERNAL_ERROR_APEX_NOT_DIRECTORY);
             }
             if (apexes.length != 1) {
-                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+                throw PackageManagerException.ofInternalError(
                         "Expected exactly one .apex file under " + dir.getAbsolutePath()
-                                + " got: " + apexes.length);
+                                + " got: " + apexes.length,
+                        PackageManagerException.INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE);
             }
             try (PackageParser2 packageParser = mPm.mInjector.getScanningPackageParser()) {
                 ApexInfo apexInfo = mPm.mApexManager.installPackage(apexes[0]);
@@ -638,7 +643,8 @@
                 PackageManagerService pm)
                 throws PackageManagerException {
             if (childInstallingSessions.size() == 0) {
-                throw new PackageManagerException("No child sessions found!");
+                throw PackageManagerException.ofInternalError("No child sessions found!",
+                        PackageManagerException.INTERNAL_ERROR_INSTALL_MISSING_CHILD_SESSIONS);
             }
             mPm = pm;
             mUser = user;
diff --git a/services/core/java/com/android/server/pm/MultiPackageVerifyingSession.java b/services/core/java/com/android/server/pm/MultiPackageVerifyingSession.java
index 06e5497..126a930 100644
--- a/services/core/java/com/android/server/pm/MultiPackageVerifyingSession.java
+++ b/services/core/java/com/android/server/pm/MultiPackageVerifyingSession.java
@@ -47,7 +47,8 @@
             throws PackageManagerException {
         mUser = parent.getUser();
         if (children.size() == 0) {
-            throw new PackageManagerException("No child sessions found!");
+            throw PackageManagerException.ofInternalError("No child sessions found!",
+                    PackageManagerException.INTERNAL_ERROR_VERIFY_MISSING_CHILD_SESSIONS);
         }
         mChildVerifyingSessions = children;
         // Provide every child with reference to this object as parent
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 25f9ccd..fb6ae8b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -66,6 +66,8 @@
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -124,6 +126,7 @@
 import android.os.RemoteException;
 import android.os.RevocableFileDescriptor;
 import android.os.SELinux;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.incremental.IStorageHealthListener;
@@ -146,6 +149,7 @@
 import android.util.EventLog;
 import android.util.ExceptionUtils;
 import android.util.IntArray;
+import android.util.Log;
 import android.util.MathUtils;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -154,6 +158,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
 import com.android.internal.content.InstallLocationUtils;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.messages.nano.SystemMessageProto;
@@ -297,8 +302,18 @@
     private static final int INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS = 60000;
 
     /**
+     * If an app being installed targets {@link Build.VERSION_CODES#S API 31} and above, the app
+     * can be installed without user action.
+     * See {@link PackageInstaller.SessionParams#setRequireUserAction} for other conditions required
+     * to be satisfied for a silent install.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
+    private static final long SILENT_INSTALL_ALLOWED = 265131695L;
+
+    /**
      * The default value of {@link #mValidatedTargetSdk} is {@link Integer#MAX_VALUE}. If {@link
-     * #mValidatedTargetSdk} is compared with {@link Build.VERSION_CODES#R} before getting the
+     * #mValidatedTargetSdk} is compared with {@link Build.VERSION_CODES#S} before getting the
      * target sdk version from a validated apk in {@link #validateApkInstallLocked()}, the compared
      * result will not trigger any user action in
      * {@link #checkUserActionRequirement(PackageInstallerSession, IntentSender)}.
@@ -2353,13 +2368,7 @@
         }
 
         if (!session.isApexSession() && userActionRequirement == USER_ACTION_PENDING_APK_PARSING) {
-            final int validatedTargetSdk;
-            synchronized (session.mLock) {
-                validatedTargetSdk = session.mValidatedTargetSdk;
-            }
-
-            if (validatedTargetSdk != INVALID_TARGET_SDK_VERSION
-                    && validatedTargetSdk < Build.VERSION_CODES.R) {
+            if (!isTargetSdkConditionSatisfied(session)) {
                 session.sendPendingUserActionIntent(target);
                 return true;
             }
@@ -2380,6 +2389,39 @@
         return false;
     }
 
+    /**
+     * Checks if the app being installed has a targetSdk more than the minimum required for a
+     * silent install. See {@link SessionParams#setRequireUserAction(int)} for details about the
+     * targetSdk requirement.
+     * @param session Current install session
+     * @return true if the targetSdk of the app being installed is more than the minimum required,
+     *          resulting in a silent install, false otherwise.
+     */
+    private static boolean isTargetSdkConditionSatisfied(PackageInstallerSession session) {
+        final int validatedTargetSdk;
+        final String packageName;
+        synchronized (session.mLock) {
+            validatedTargetSdk = session.mValidatedTargetSdk;
+            packageName = session.mPackageName;
+        }
+
+        ApplicationInfo appInfo = new ApplicationInfo();
+        appInfo.packageName = packageName;
+        appInfo.targetSdkVersion = validatedTargetSdk;
+
+        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        try {
+            // Using manually constructed AppInfo to check if a change is enabled may not work
+            // in the future.
+            return validatedTargetSdk != INVALID_TARGET_SDK_VERSION
+                    && platformCompat.isChangeEnabled(SILENT_INSTALL_ALLOWED, appInfo);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
+            return false;
+        }
+    }
+
     private static @UserActionReason int userActionRequirementToReason(
             @UserActionRequirement int requirement) {
         switch (requirement) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index 4662389..dea6659 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -16,32 +16,138 @@
 
 package com.android.server.pm;
 
+import android.annotation.IntDef;
 import android.content.pm.PackageManager;
 
 import com.android.server.pm.Installer.InstallerException;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /** {@hide} */
 public class PackageManagerException extends Exception {
-    public final int error;
+    public static final int INTERNAL_ERROR_NATIVE_LIBRARY_COPY = -1;
+    public static final int INTERNAL_ERROR_MOVE = -2;
+    public static final int INTERNAL_ERROR_MISSING_SETTING_FOR_MOVE = -3;
+    public static final int INTERNAL_ERROR_DERIVING_ABI = -4;
+    public static final int INTERNAL_ERROR_VERITY_SETUP = -5;
+    public static final int INTERNAL_ERROR_SHARED_LIB_INSTALLED_TWICE = -6;
+    public static final int INTERNAL_ERROR_STORAGE_INVALID_PACKAGE_UNKNOWN = -7;
+    public static final int INTERNAL_ERROR_STORAGE_INVALID_VOLUME_UNKNOWN = -8;
+    public static final int INTERNAL_ERROR_STORAGE_INVALID_NOT_INSTALLED_FOR_USER = -9;
+    public static final int INTERNAL_ERROR_STORAGE_INVALID_SHOULD_NOT_HAVE_STORAGE = -10;
+    public static final int INTERNAL_ERROR_DECOMPRESS_STUB = -11;
+    public static final int INTERNAL_ERROR_UPDATED_VERSION_BETTER_THAN_SYSTEM = -12;
+    public static final int INTERNAL_ERROR_DUP_STATIC_SHARED_LIB_PROVIDER = -13;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_VERSION_CODES_ORDER = -14;
+    public static final int INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC = -15;
+    public static final int INTERNAL_ERROR_OVERLAY_LOW_TARGET_SDK = -16;
+    public static final int INTERNAL_ERROR_OVERLAY_SIGNATURE1 = -17;
+    public static final int INTERNAL_ERROR_OVERLAY_SIGNATURE2 = -18;
+    public static final int INTERNAL_ERROR_NOT_PRIV_SHARED_USER = -19;
+    public static final int INTERNAL_ERROR_INSTALL_MISSING_CHILD_SESSIONS = -20;
+    public static final int INTERNAL_ERROR_VERIFY_MISSING_CHILD_SESSIONS = -21;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_LOW_SDK = -22;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_INSTANT = -23;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_RENAMED = -24;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_DYNAMIC = -25;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_SHARED_USER = -26;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_ACTIVITY = -27;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_SERVICE = -28;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_CONTENT_PROVIDER = -29;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_BROADCAST_RECEIVER = -30;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION_GROUP = -31;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_FEATURE = -32;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION = -33;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_PROTECTED_BROADCAST = -34;
+    public static final int INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS = -35;
+    public static final int INTERNAL_ERROR_APEX_NOT_DIRECTORY = -36;
+    public static final int INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE = -37;
 
-    public PackageManagerException(String detailMessage) {
+    @IntDef(prefix = { "INTERNAL_ERROR_" }, value = {
+            INTERNAL_ERROR_NATIVE_LIBRARY_COPY,
+            INTERNAL_ERROR_MOVE,
+            INTERNAL_ERROR_MISSING_SETTING_FOR_MOVE,
+            INTERNAL_ERROR_DERIVING_ABI,
+            INTERNAL_ERROR_VERITY_SETUP,
+            INTERNAL_ERROR_SHARED_LIB_INSTALLED_TWICE,
+            INTERNAL_ERROR_STORAGE_INVALID_PACKAGE_UNKNOWN,
+            INTERNAL_ERROR_STORAGE_INVALID_VOLUME_UNKNOWN,
+            INTERNAL_ERROR_STORAGE_INVALID_NOT_INSTALLED_FOR_USER,
+            INTERNAL_ERROR_STORAGE_INVALID_SHOULD_NOT_HAVE_STORAGE,
+            INTERNAL_ERROR_DECOMPRESS_STUB,
+            INTERNAL_ERROR_UPDATED_VERSION_BETTER_THAN_SYSTEM,
+            INTERNAL_ERROR_DUP_STATIC_SHARED_LIB_PROVIDER,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_VERSION_CODES_ORDER,
+            INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC,
+            INTERNAL_ERROR_OVERLAY_LOW_TARGET_SDK,
+            INTERNAL_ERROR_OVERLAY_SIGNATURE1,
+            INTERNAL_ERROR_OVERLAY_SIGNATURE2,
+            INTERNAL_ERROR_NOT_PRIV_SHARED_USER,
+            INTERNAL_ERROR_INSTALL_MISSING_CHILD_SESSIONS,
+            INTERNAL_ERROR_VERIFY_MISSING_CHILD_SESSIONS,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_LOW_SDK,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_INSTANT,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_RENAMED,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_DYNAMIC,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_SHARED_USER,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_ACTIVITY,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_SERVICE,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_CONTENT_PROVIDER,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_BROADCAST_RECEIVER,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION_GROUP,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_FEATURE,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_PROTECTED_BROADCAST,
+            INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS,
+            INTERNAL_ERROR_APEX_NOT_DIRECTORY,
+            INTERNAL_ERROR_APEX_MORE_THAN_ONE_FILE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface InternalErrorCode {}
+
+    public final int error;
+    public final int internalErrorCode;
+
+    /**
+     * Default constructor without specifying the public return code of this exception.
+     * The public error code will be {@link PackageManager.INSTALL_FAILED_INTERNAL_ERROR}.
+     *
+     * Note for developers: if you use this constructor, assuming you have a different case where
+     * the exception should be thrown with {@link PackageManager.INSTALL_FAILED_INTERNAL_ERROR},
+     * please create a new {@link InternalErrorCode} constant.
+     *
+     * @param detailMessage Details about the cause of the exception.
+     * @param internalErrorCode Used for logging and analysis.
+     */
+    public static PackageManagerException ofInternalError(String detailMessage,
+            @InternalErrorCode int internalErrorCode) {
+        return new PackageManagerException(
+                PackageManager.INSTALL_FAILED_INTERNAL_ERROR, detailMessage, internalErrorCode);
+    }
+
+    protected PackageManagerException(int error, String detailMessage, int internalErrorCode) {
         super(detailMessage);
-        this.error = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+        this.error = error;
+        this.internalErrorCode = internalErrorCode;
     }
 
     public PackageManagerException(int error, String detailMessage) {
         super(detailMessage);
         this.error = error;
+        this.internalErrorCode = 0;
     }
 
     public PackageManagerException(int error, String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
         this.error = error;
+        this.internalErrorCode = 0;
     }
 
     public PackageManagerException(Throwable e) {
         super(e);
         this.error = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+        this.internalErrorCode = 0;
     }
 
     public static PackageManagerException from(InstallerException e)
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 74bd0092a..93b0dcb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -972,6 +972,9 @@
                         showUid = true;
                         uid = Integer.parseInt(getNextArgRequired());
                         break;
+                    case "--match-libraries":
+                        getFlags |= PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
+                        break;
                     default:
                         pw.println("Error: Unknown option: " + opt);
                         return -1;
@@ -4080,6 +4083,7 @@
         pw.println("      --factory-only: only show system packages excluding updates");
         pw.println("      --uid UID: filter to only show packages with the given UID");
         pw.println("      --user USER_ID: only list packages belonging to the given user");
+        pw.println("      --match-libraries: include packages that declare static shared and SDK libraries");
         pw.println("");
         pw.println("  list permission-groups");
         pw.println("    Prints all known permission groups.");
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index c4ad20e..fe014a4 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -122,7 +122,7 @@
                 originalUsers /* original_user_ids */,
                 userManagerInternal.getUserTypesForStatsd(originalUsers) /* original_user_types */,
                 mInstallRequest.getReturnCode() /* public_return_code */,
-                0 /* internal_error_code */,
+                mInstallRequest.getInternalErrorCode() /* internal_error_code */,
                 apksSize /* apks_size_bytes */,
                 versionCode /* version_code */,
                 stepDurations.first /* install_steps */,
diff --git a/services/core/java/com/android/server/pm/PrepareFailure.java b/services/core/java/com/android/server/pm/PrepareFailure.java
index a54ffa3..3180bac 100644
--- a/services/core/java/com/android/server/pm/PrepareFailure.java
+++ b/services/core/java/com/android/server/pm/PrepareFailure.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.content.pm.PackageManager;
 import android.util.ExceptionUtils;
 
 final class PrepareFailure extends PackageManagerException {
@@ -31,6 +32,15 @@
         super(error, detailMessage);
     }
 
+    public static PrepareFailure ofInternalError(String detailMessage, int internalErrorCode) {
+        return new PrepareFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, detailMessage,
+                internalErrorCode);
+    }
+
+    private PrepareFailure(int error, String message, int internalErrorCode) {
+        super(error, message, internalErrorCode);
+    }
+
     PrepareFailure(String message, Exception e) {
         super(((PackageManagerException) e).error,
                 ExceptionUtils.getCompleteMessage(message, e));
diff --git a/services/core/java/com/android/server/pm/ReconcileFailure.java b/services/core/java/com/android/server/pm/ReconcileFailure.java
index c9615ff..71a10f9 100644
--- a/services/core/java/com/android/server/pm/ReconcileFailure.java
+++ b/services/core/java/com/android/server/pm/ReconcileFailure.java
@@ -16,10 +16,18 @@
 
 package com.android.server.pm;
 
+import android.content.pm.PackageManager;
+
 final class ReconcileFailure extends PackageManagerException {
-    ReconcileFailure(String message) {
-        super("Reconcile failed: " + message);
+    public static ReconcileFailure ofInternalError(String message, int internalErrorCode) {
+        return new ReconcileFailure(message, internalErrorCode);
     }
+
+    private ReconcileFailure(String message, int internalErrorCode) {
+        super(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, "Reconcile failed: " + message,
+                internalErrorCode);
+    }
+
     ReconcileFailure(int reason, String message) {
         super(reason, "Reconcile failed: " + message);
     }
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index 58dcb02..d160740 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -82,8 +82,10 @@
                 for (SharedLibraryInfo info : allowedSharedLibInfos) {
                     if (!SharedLibraryUtils.addSharedLibraryToPackageVersionMap(
                             incomingSharedLibraries, info)) {
-                        throw new ReconcileFailure("Shared Library " + info.getName()
-                                + " is being installed twice in this set!");
+                        throw ReconcileFailure.ofInternalError(
+                                "Shared Library " + info.getName()
+                                + " is being installed twice in this set!",
+                                PackageManagerException.INTERNAL_ERROR_SHARED_LIB_INSTALLED_TWICE);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index e4f3e2b..c3106a8 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -569,87 +569,101 @@
             @PackageManagerService.ScanFlags int scanFlags) throws PackageManagerException {
         // Static shared libraries should have at least O target SDK
         if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) {
-            throw new PackageManagerException(
-                    "Packages declaring static-shared libs must target O SDK or higher");
+            throw PackageManagerException.ofInternalError(
+                    "Packages declaring static-shared libs must target O SDK or higher",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_LOW_SDK);
         }
 
         // Package declaring static a shared lib cannot be instant apps
         if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
-            throw new PackageManagerException(
-                    "Packages declaring static-shared libs cannot be instant apps");
+            throw PackageManagerException.ofInternalError(
+                    "Packages declaring static-shared libs cannot be instant apps",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_INSTANT);
         }
 
         // Package declaring static a shared lib cannot be renamed since the package
         // name is synthetic and apps can't code around package manager internals.
         if (!ArrayUtils.isEmpty(pkg.getOriginalPackages())) {
-            throw new PackageManagerException(
-                    "Packages declaring static-shared libs cannot be renamed");
+            throw PackageManagerException.ofInternalError(
+                    "Packages declaring static-shared libs cannot be renamed",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_RENAMED);
         }
 
         // Package declaring static a shared lib cannot declare dynamic libs
         if (!ArrayUtils.isEmpty(pkg.getLibraryNames())) {
-            throw new PackageManagerException(
-                    "Packages declaring static-shared libs cannot declare dynamic libs");
+            throw PackageManagerException.ofInternalError(
+                    "Packages declaring static-shared libs cannot declare dynamic libs",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_DYNAMIC);
         }
 
         // Package declaring static a shared lib cannot declare shared users
         if (pkg.getSharedUserId() != null) {
-            throw new PackageManagerException(
-                    "Packages declaring static-shared libs cannot declare shared users");
+            throw PackageManagerException.ofInternalError(
+                    "Packages declaring static-shared libs cannot declare shared users",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_SHARED_USER);
         }
 
         // Static shared libs cannot declare activities
         if (!pkg.getActivities().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare activities");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare activities",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_ACTIVITY);
         }
 
         // Static shared libs cannot declare services
         if (!pkg.getServices().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare services");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare services",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_SERVICE);
         }
 
         // Static shared libs cannot declare providers
         if (!pkg.getProviders().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare content providers");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare content providers",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_CONTENT_PROVIDER);
         }
 
         // Static shared libs cannot declare receivers
         if (!pkg.getReceivers().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare broadcast receivers");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare broadcast receivers",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_BROADCAST_RECEIVER);
         }
 
         // Static shared libs cannot declare permission groups
         if (!pkg.getPermissionGroups().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare permission groups");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare permission groups",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION_GROUP);
         }
 
         // Static shared libs cannot declare attributions
         if (!pkg.getAttributions().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare features");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare features",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_FEATURE);
         }
 
         // Static shared libs cannot declare permissions
         if (!pkg.getPermissions().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare permissions");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare permissions",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION);
         }
 
         // Static shared libs cannot declare protected broadcasts
         if (!pkg.getProtectedBroadcasts().isEmpty()) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot declare protected broadcasts");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot declare protected broadcasts",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PROTECTED_BROADCAST);
         }
 
         // Static shared libs cannot be overlay targets
         if (pkg.getOverlayTarget() != null) {
-            throw new PackageManagerException(
-                    "Static shared libs cannot be overlay targets");
+            throw PackageManagerException.ofInternalError(
+                    "Static shared libs cannot be overlay targets",
+                    PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a7fc3ed..19a0e03 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1962,6 +1962,14 @@
     }
 
     @Override
+    public int getDisplayIdAssignedToUser() {
+        // Not checking for any permission as it returns info about calling user
+        int userId = UserHandle.getUserId(Binder.getCallingUid());
+        int displayId = mUserVisibilityMediator.getDisplayAssignedToUser(userId);
+        return displayId;
+    }
+
+    @Override
     public @NonNull String getUserName() {
         final int callingUid = Binder.getCallingUid();
         if (!hasQueryOrCreateUsersPermission()
@@ -5920,11 +5928,21 @@
                 /* receiverPermission= */null);
     }
 
+    /**
+     * @deprecated Use {@link
+     * android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+     */
+    @Deprecated
     @Override
     public Bundle getApplicationRestrictions(String packageName) {
         return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
     }
 
+    /**
+     * @deprecated Use {@link
+     * android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+     */
+    @Deprecated
     @Override
     public Bundle getApplicationRestrictionsForUser(String packageName, @UserIdInt int userId) {
         if (UserHandle.getCallingUserId() != userId
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 89a9eb0..78761bd 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3305,7 +3305,7 @@
         if (Objects.equals(packageName, PLATFORM_PACKAGE_NAME)) {
             return true;
         }
-        if (!packageSetting.isPrivileged()) {
+        if (!(packageSetting.isSystem() && packageSetting.isPrivileged())) {
             return true;
         }
         if (!mPrivilegedPermissionAllowlistSourcePackageNames
diff --git a/services/core/java/com/android/server/power/LowPowerStandbyController.java b/services/core/java/com/android/server/power/LowPowerStandbyController.java
index f248a02..b939cdc 100644
--- a/services/core/java/com/android/server/power/LowPowerStandbyController.java
+++ b/services/core/java/com/android/server/power/LowPowerStandbyController.java
@@ -19,6 +19,7 @@
 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
 import static android.os.PowerManager.lowPowerStandbyAllowedReasonsToString;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
@@ -33,12 +34,15 @@
 import android.net.Uri;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.LowPowerStandbyAllowedReason;
 import android.os.PowerManager.LowPowerStandbyPolicy;
+import android.os.PowerManager.LowPowerStandbyPortDescription;
 import android.os.PowerManagerInternal;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -111,6 +115,7 @@
     private static final int MSG_NOTIFY_ACTIVE_CHANGED = 1;
     private static final int MSG_NOTIFY_ALLOWLIST_CHANGED = 2;
     private static final int MSG_NOTIFY_POLICY_CHANGED = 3;
+    private static final int MSG_NOTIFY_STANDBY_PORTS_CHANGED = 4;
 
     private static final String TAG_ROOT = "low-power-standby-policy";
     private static final String TAG_IDENTIFIER = "identifier";
@@ -131,9 +136,11 @@
             this::onStandbyTimeoutExpired;
     private final LowPowerStandbyControllerInternal mLocalService = new LocalService();
     private final SparseIntArray mUidAllowedReasons = new SparseIntArray();
+    private final List<StandbyPortsLock> mStandbyPortLocks = new ArrayList<>();
 
     @GuardedBy("mLock")
     private boolean mEnableCustomPolicy;
+    private boolean mEnableStandbyPorts;
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -189,6 +196,49 @@
         }
     };
 
+    private final class StandbyPortsLock implements IBinder.DeathRecipient {
+        private final IBinder mToken;
+        private final int mUid;
+        private final List<LowPowerStandbyPortDescription> mPorts;
+
+        StandbyPortsLock(IBinder token, int uid, List<LowPowerStandbyPortDescription> ports) {
+            mToken = token;
+            mUid = uid;
+            mPorts = ports;
+        }
+
+        public boolean linkToDeath() {
+            try {
+                mToken.linkToDeath(this, 0);
+                return true;
+            } catch (RemoteException e) {
+                Slog.i(TAG, "StandbyPorts token already died");
+                return false;
+            }
+        }
+
+        public void unlinkToDeath() {
+            mToken.unlinkToDeath(this, 0);
+        }
+
+        public IBinder getToken() {
+            return mToken;
+        }
+
+        public int getUid() {
+            return mUid;
+        }
+
+        public List<LowPowerStandbyPortDescription> getPorts() {
+            return mPorts;
+        }
+
+        @Override
+        public void binderDied() {
+            releaseStandbyPorts(mToken);
+        }
+    }
+
     @GuardedBy("mLock")
     private AlarmManager mAlarmManager;
     @GuardedBy("mLock")
@@ -311,6 +361,7 @@
             mDeviceConfig.registerPropertyUpdateListener(mContext.getMainExecutor(),
                     properties -> onDeviceConfigFlagsChanged());
             mEnableCustomPolicy = mDeviceConfig.enableCustomPolicy();
+            mEnableStandbyPorts = mDeviceConfig.enableStandbyPorts();
 
             if (mEnableCustomPolicy) {
                 mPolicy = loadPolicy();
@@ -336,6 +387,8 @@
                 enqueueNotifyAllowlistChangedLocked();
                 mEnableCustomPolicy = enableCustomPolicy;
             }
+
+            mEnableStandbyPorts = mDeviceConfig.enableStandbyPorts();
         }
     }
 
@@ -861,6 +914,78 @@
         }
     }
 
+    private int findIndexOfStandbyPorts(@NonNull IBinder token) {
+        for (int i = 0; i < mStandbyPortLocks.size(); i++) {
+            if (mStandbyPortLocks.get(i).getToken() == token) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    void acquireStandbyPorts(@NonNull IBinder token, int uid,
+            @NonNull List<LowPowerStandbyPortDescription> ports) {
+        validatePorts(ports);
+
+        StandbyPortsLock standbyPortsLock = new StandbyPortsLock(token, uid, ports);
+        synchronized (mLock) {
+            if (findIndexOfStandbyPorts(token) != -1) {
+                return;
+            }
+
+            if (standbyPortsLock.linkToDeath()) {
+                mStandbyPortLocks.add(standbyPortsLock);
+                if (mEnableStandbyPorts && isEnabled() && isPackageExempt(uid)) {
+                    enqueueNotifyStandbyPortsChangedLocked();
+                }
+            }
+        }
+    }
+
+    void validatePorts(@NonNull List<LowPowerStandbyPortDescription> ports) {
+        for (LowPowerStandbyPortDescription portDescription : ports) {
+            int port = portDescription.getPortNumber();
+            if (port < 0 || port > 0xFFFF) {
+                throw new IllegalArgumentException("port out of range:" + port);
+            }
+        }
+    }
+
+    void releaseStandbyPorts(@NonNull IBinder token) {
+        synchronized (mLock) {
+            int index = findIndexOfStandbyPorts(token);
+            if (index == -1) {
+                return;
+            }
+
+            StandbyPortsLock standbyPortsLock = mStandbyPortLocks.remove(index);
+            standbyPortsLock.unlinkToDeath();
+            if (mEnableStandbyPorts && isEnabled() && isPackageExempt(standbyPortsLock.getUid())) {
+                enqueueNotifyStandbyPortsChangedLocked();
+            }
+        }
+    }
+
+    @NonNull
+    List<LowPowerStandbyPortDescription> getActiveStandbyPorts() {
+        List<LowPowerStandbyPortDescription> activeStandbyPorts = new ArrayList<>();
+        synchronized (mLock) {
+            if (!isEnabled() || !mEnableStandbyPorts) {
+                return activeStandbyPorts;
+            }
+
+            List<Integer> exemptPackageAppIds = getExemptPackageAppIdsLocked();
+            for (StandbyPortsLock standbyPortsLock : mStandbyPortLocks) {
+                int standbyPortsAppid = UserHandle.getAppId(standbyPortsLock.getUid());
+                if (exemptPackageAppIds.contains(standbyPortsAppid)) {
+                    activeStandbyPorts.addAll(standbyPortsLock.getPorts());
+                }
+            }
+
+            return activeStandbyPorts;
+        }
+    }
+
     private boolean policyChangeAffectsAllowlistLocked(
             @Nullable LowPowerStandbyPolicy oldPolicy, @Nullable LowPowerStandbyPolicy newPolicy) {
         final LowPowerStandbyPolicy policyA = policyOrDefault(oldPolicy);
@@ -941,6 +1066,17 @@
                 }
             }
             ipw.decreaseIndent();
+
+            final List<LowPowerStandbyPortDescription> activeStandbyPorts = getActiveStandbyPorts();
+            if (!activeStandbyPorts.isEmpty()) {
+                ipw.println();
+                ipw.println("Active standby ports locks:");
+                ipw.increaseIndent();
+                for (LowPowerStandbyPortDescription portDescription : activeStandbyPorts) {
+                    ipw.print(portDescription.toString());
+                }
+                ipw.decreaseIndent();
+            }
         }
         ipw.decreaseIndent();
     }
@@ -1006,6 +1142,9 @@
                 case MSG_NOTIFY_POLICY_CHANGED:
                     notifyPolicyChanged((LowPowerStandbyPolicy) msg.obj);
                     break;
+                case MSG_NOTIFY_STANDBY_PORTS_CHANGED:
+                    notifyStandbyPortsChanged();
+                    break;
             }
         }
     }
@@ -1172,6 +1311,29 @@
         npmi.setLowPowerStandbyAllowlist(allowlistUids);
     }
 
+    @GuardedBy("mLock")
+    private void enqueueNotifyStandbyPortsChangedLocked() {
+        final long now = mClock.elapsedRealtime();
+
+        if (DEBUG) {
+            Slog.d(TAG, "enqueueNotifyStandbyPortsChangedLocked");
+        }
+
+        final Message msg = mHandler.obtainMessage(MSG_NOTIFY_STANDBY_PORTS_CHANGED);
+        mHandler.sendMessageAtTime(msg, now);
+    }
+
+    private void notifyStandbyPortsChanged() {
+        if (DEBUG) {
+            Slog.d(TAG, "notifyStandbyPortsChanged");
+        }
+
+        final Intent intent = new Intent(PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                Manifest.permission.MANAGE_LOW_POWER_STANDBY);
+    }
+
     /**
      * Class that is used to read device config for low power standby configuration.
      */
@@ -1179,6 +1341,7 @@
     public static class DeviceConfigWrapper {
         public static final String NAMESPACE = "low_power_standby";
         public static final String FEATURE_FLAG_ENABLE_POLICY = "enable_policy";
+        public static final String FEATURE_FLAG_ENABLE_STANDBY_PORTS = "enable_standby_ports";
 
         /**
          * Returns true if custom policies are enabled.
@@ -1189,6 +1352,14 @@
         }
 
         /**
+         * Returns true if standby ports are enabled.
+         * Otherwise, returns false, and {@link #getActiveStandbyPorts()} will always be empty.
+         */
+        public boolean enableStandbyPorts() {
+            return DeviceConfig.getBoolean(NAMESPACE, FEATURE_FLAG_ENABLE_STANDBY_PORTS, false);
+        }
+
+        /**
          * Registers a DeviceConfig update listener.
          */
         public void registerPropertyUpdateListener(
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ddf70f3..b83d509 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -6226,6 +6226,61 @@
             }
         }
 
+        @Override // Binder call
+        @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
+        public void acquireLowPowerStandbyPorts(IBinder token,
+                List<LowPowerStandbyPortDescription> ports) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS,
+                    "acquireLowPowerStandbyPorts");
+
+            final int callingUid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mLowPowerStandbyController.acquireStandbyPorts(token, callingUid,
+                        PowerManager.LowPowerStandbyPortDescription.fromParcelable(ports));
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        @RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
+        public void releaseLowPowerStandbyPorts(IBinder token) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS,
+                    "releaseLowPowerStandbyPorts");
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mLowPowerStandbyController.releaseStandbyPorts(token);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        @RequiresPermission(anyOf = {
+                android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
+                android.Manifest.permission.DEVICE_POWER
+        })
+        public List<LowPowerStandbyPortDescription> getActiveLowPowerStandbyPorts() {
+            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
+                    != PackageManager.PERMISSION_GRANTED) {
+                mContext.enforceCallingOrSelfPermission(
+                        android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
+                        "getActiveLowPowerStandbyPorts");
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return PowerManager.LowPowerStandbyPortDescription.toParcelable(
+                        mLowPowerStandbyController.getActiveStandbyPorts());
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         /**
          * Gets the reason for the last time the phone had to reboot.
          *
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index e3d2189..43f96e7 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -505,47 +505,9 @@
             return mTemperatureWatcher.getForecast(forecastSeconds);
         }
 
-        private void dumpItemsLocked(PrintWriter pw, String prefix,
-                Collection<?> items) {
-            for (Iterator iterator = items.iterator(); iterator.hasNext();) {
-                pw.println(prefix + iterator.next().toString());
-            }
-        }
-
         @Override
-        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
-                return;
-            }
-            final long token = Binder.clearCallingIdentity();
-            try {
-                synchronized (mLock) {
-                    pw.println("IsStatusOverride: " + mIsStatusOverride);
-                    pw.println("ThermalEventListeners:");
-                    mThermalEventListeners.dump(pw, "\t");
-                    pw.println("ThermalStatusListeners:");
-                    mThermalStatusListeners.dump(pw, "\t");
-                    pw.println("Thermal Status: " + mStatus);
-                    pw.println("Cached temperatures:");
-                    dumpItemsLocked(pw, "\t", mTemperatureMap.values());
-                    pw.println("HAL Ready: " + mHalReady.get());
-                    if (mHalReady.get()) {
-                        pw.println("HAL connection:");
-                        mHalWrapper.dump(pw, "\t");
-                        pw.println("Current temperatures from HAL:");
-                        dumpItemsLocked(pw, "\t",
-                                mHalWrapper.getCurrentTemperatures(false, 0));
-                        pw.println("Current cooling devices from HAL:");
-                        dumpItemsLocked(pw, "\t",
-                                mHalWrapper.getCurrentCoolingDevices(false, 0));
-                        pw.println("Temperature static thresholds from HAL:");
-                        dumpItemsLocked(pw, "\t",
-                                mHalWrapper.getTemperatureThresholds(false, 0));
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            dumpInternal(fd, pw, args);
         }
 
         private boolean isCallerShell() {
@@ -567,6 +529,62 @@
 
     };
 
+    private static void dumpItemsLocked(PrintWriter pw, String prefix,
+            Collection<?> items) {
+        for (Iterator iterator = items.iterator(); iterator.hasNext();) {
+            pw.println(prefix + iterator.next().toString());
+        }
+    }
+
+    private static void dumpTemperatureThresholds(PrintWriter pw, String prefix,
+            List<TemperatureThreshold> thresholds) {
+        for (TemperatureThreshold threshold : thresholds) {
+            pw.println(prefix + "TemperatureThreshold{mType=" + threshold.type
+                    + ", mName=" + threshold.name
+                    + ", mHotThrottlingThresholds=" + Arrays.toString(
+                    threshold.hotThrottlingThresholds)
+                    + ", mColdThrottlingThresholds=" + Arrays.toString(
+                    threshold.coldThrottlingThresholds)
+                    + "}");
+        }
+    }
+
+    @VisibleForTesting
+    void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
+            return;
+        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                pw.println("IsStatusOverride: " + mIsStatusOverride);
+                pw.println("ThermalEventListeners:");
+                mThermalEventListeners.dump(pw, "\t");
+                pw.println("ThermalStatusListeners:");
+                mThermalStatusListeners.dump(pw, "\t");
+                pw.println("Thermal Status: " + mStatus);
+                pw.println("Cached temperatures:");
+                dumpItemsLocked(pw, "\t", mTemperatureMap.values());
+                pw.println("HAL Ready: " + mHalReady.get());
+                if (mHalReady.get()) {
+                    pw.println("HAL connection:");
+                    mHalWrapper.dump(pw, "\t");
+                    pw.println("Current temperatures from HAL:");
+                    dumpItemsLocked(pw, "\t",
+                            mHalWrapper.getCurrentTemperatures(false, 0));
+                    pw.println("Current cooling devices from HAL:");
+                    dumpItemsLocked(pw, "\t",
+                            mHalWrapper.getCurrentCoolingDevices(false, 0));
+                    pw.println("Temperature static thresholds from HAL:");
+                    dumpTemperatureThresholds(pw, "\t",
+                            mHalWrapper.getTemperatureThresholds(false, 0));
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     class ThermalShellCommand extends ShellCommand {
         @Override
         public int onCommand(String cmd) {
diff --git a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
index b04d7df..8e8abf6 100644
--- a/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
+++ b/services/core/java/com/android/server/speech/RemoteSpeechRecognitionService.java
@@ -452,6 +452,11 @@
         }
 
         @Override
+        public void onLanguageDetection(Bundle results) throws RemoteException {
+            mRemoteListener.onLanguageDetection(results);
+        }
+
+        @Override
         public void onEvent(int eventType, Bundle params) throws RemoteException {
             mRemoteListener.onEvent(eventType, params);
         }
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index f452378..587138d 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -45,6 +45,7 @@
 import android.util.DebugUtils;
 import android.util.Slog;
 
+import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.am.PendingIntentRecord;
 
 import java.lang.annotation.Retention;
@@ -176,22 +177,24 @@
             if (callingUid == Process.ROOT_UID
                     || callingAppId == Process.SYSTEM_UID
                     || callingAppId == Process.NFC_UID) {
-                return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_UID, "Important callingUid");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
+                        callingUid, realCallingUid, intent, "Important callingUid");
             }
 
             // Always allow home application to start activities.
             if (isHomeApp(callingUid, callingPackage)) {
-                return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_COMPONENT, "Home app");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
+                        "Home app");
             }
 
             // IME should always be allowed to start activity, like IME settings.
             final WindowState imeWindow =
                     mService.mRootWindowContainer.getCurrentInputMethodWindow();
             if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
-                return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_COMPONENT, "Active ime");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
+                        "Active ime");
             }
         }
 
@@ -218,8 +221,8 @@
                                 && callingUidHasAnyVisibleWindow)
                         || isCallingUidPersistentSystemProcess;
         if (useCallingUidState && allowCallingUidStartActivity) {
-            return logStartAllowedAndReturnCode(/*background*/ false,
-                    BAL_ALLOW_VISIBLE_WINDOW,
+            return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW,
+                    /*background*/ false, callingUid, realCallingUid, intent,
                     "callingUidHasAnyVisibleWindow = "
                             + callingUid
                             + ", isCallingUidPersistentSystemProcess = "
@@ -254,8 +257,8 @@
                     Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid));
 
             if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
-                return logStartAllowedAndReturnCode(/*background*/ false, realCallingUid,
-                        BAL_ALLOW_SDK_SANDBOX,
+                return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX,
+                        /*background*/ false, callingUid, realCallingUid, intent,
                         "uid in SDK sandbox has visible (non-toast) window");
             }
         }
@@ -276,16 +279,16 @@
                                     -1,
                                     true)
                             == PackageManager.PERMISSION_GRANTED) {
-                return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
-                        BAL_ALLOW_PENDING_INTENT,
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
                         "realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
             }
 
             // don't abort if the realCallingUid has a visible window
             // TODO(b/171459802): We should check appSwitchAllowed also
             if (realCallingUidHasAnyVisibleWindow) {
-                return logStartAllowedAndReturnCode(/*background*/ false,
-                        callingUid, BAL_ALLOW_PENDING_INTENT,
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
                         "realCallingUid has visible (non-toast) window. realCallingUid: "
                                 + realCallingUid);
             }
@@ -293,9 +296,8 @@
             // wasn't allowed to start an activity
             if (isRealCallingUidPersistentSystemProcess
                     && backgroundStartPrivileges.allowsBackgroundActivityStarts()) {
-                return logStartAllowedAndReturnCode(/*background*/ false,
-                        callingUid,
-                        BAL_ALLOW_PENDING_INTENT,
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
                         "realCallingUid is persistent system process AND intent "
                                 + "sender allowed (allowBackgroundActivityStart = true). "
                                 + "realCallingUid: " + realCallingUid);
@@ -303,8 +305,9 @@
             // don't abort if the realCallingUid is an associated companion app
             if (mService.isAssociatedCompanionApp(
                     UserHandle.getUserId(realCallingUid), realCallingUid)) {
-                return logStartAllowedAndReturnCode(/*background*/ false, callingUid,
-                        BAL_ALLOW_PENDING_INTENT,  "realCallingUid is a companion app. "
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
+                        /*background*/ false, callingUid, realCallingUid, intent,
+                        "realCallingUid is a companion app. "
                                 + "realCallingUid: " + realCallingUid);
             }
         }
@@ -312,25 +315,28 @@
             // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
             if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
                     callingPid, callingUid) == PERMISSION_GRANTED) {
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                    BAL_ALLOW_PERMISSION,
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
+                        /*background*/ true, callingUid, realCallingUid, intent,
                         "START_ACTIVITIES_FROM_BACKGROUND permission granted");
             }
             // don't abort if the caller has the same uid as the recents component
             if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_COMPONENT, "Recents Component");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+                        /*background*/ true, callingUid, realCallingUid,
+                        intent, "Recents Component");
             }
             // don't abort if the callingUid is the device owner
             if (mService.isDeviceOwner(callingUid)) {
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_COMPONENT, "Device Owner");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+                        /*background*/ true, callingUid, realCallingUid,
+                        intent, "Device Owner");
             }
             // don't abort if the callingUid has companion device
             final int callingUserId = UserHandle.getUserId(callingUid);
             if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                        BAL_ALLOW_ALLOWLISTED_COMPONENT, "Companion App");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
+                        /*background*/ true, callingUid, realCallingUid,
+                        intent, "Companion App");
             }
             // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
             if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
@@ -339,8 +345,9 @@
                         "Background activity start for "
                                 + callingPackage
                                 + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                        BAL_ALLOW_SAW_PERMISSION, "SYSTEM_ALERT_WINDOW permission is granted");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_SAW_PERMISSION,
+                        /*background*/ true, callingUid, realCallingUid,
+                        intent, "SYSTEM_ALERT_WINDOW permission is granted");
             }
             // don't abort if the callingUid and callingPackage have the
             // OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop
@@ -349,9 +356,9 @@
                     callingUid,
                     callingPackage)
                     == AppOpsManager.MODE_ALLOWED) {
-                return logStartAllowedAndReturnCode(/*background*/ true, callingUid,
-                    BAL_ALLOW_PERMISSION,
-                    "OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
+                return logStartAllowedAndReturnCode(BAL_ALLOW_PERMISSION,
+                        /*background*/ true, callingUid, realCallingUid, intent,
+                        "OP_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION appop is granted");
             }
         }
         // If we don't have callerApp at this point, no caller was provided to startActivity().
@@ -369,7 +376,8 @@
             @BalCode int balAllowedForCaller = callerApp
                     .areBackgroundActivityStartsAllowed(appSwitchState);
             if (balAllowedForCaller != BAL_BLOCK) {
-                return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForCaller,
+                return logStartAllowedAndReturnCode(balAllowedForCaller,
+                        /*background*/ true, callingUid, realCallingUid, intent,
                         "callerApp process (pid = " + callerApp.getPid()
                                 + ", uid = " + callerAppUid + ") is allowed");
             }
@@ -382,7 +390,8 @@
                     int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState);
                     if (proc != callerApp
                             && balAllowedForUid != BAL_BLOCK) {
-                        return logStartAllowedAndReturnCode(/*background*/ true, balAllowedForUid,
+                        return logStartAllowedAndReturnCode(balAllowedForUid,
+                                /*background*/ true, callingUid, realCallingUid, intent,
                                 "process" + proc.getPid()
                                         + " from uid " + callerAppUid + " is allowed");
                     }
@@ -448,27 +457,21 @@
         return BAL_BLOCK;
     }
 
-    private int logStartAllowedAndReturnCode(boolean background, int callingUid, int code,
-            String msg) {
-        if (DEBUG_ACTIVITY_STARTS) {
-            return logStartAllowedAndReturnCode(background, code,
-                    msg, "callingUid: " + callingUid);
-        }
-        return code;
+    static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
+            int callingUid, int realCallingUid, Intent intent, int pid, String msg) {
+        return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
+                DEBUG_ACTIVITY_STARTS ?  ("[Process(" + pid + ")]" + msg) : "");
     }
 
-    private int logStartAllowedAndReturnCode(boolean background, int code,
-            String... msg) {
+    static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
+            int callingUid, int realCallingUid, Intent intent, String msg) {
+        statsLogBalAllowed(code, callingUid, realCallingUid, intent);
         if (DEBUG_ACTIVITY_STARTS) {
             StringBuilder builder = new StringBuilder();
             if (background) {
                 builder.append("Background ");
             }
-            builder.append("Activity start allowed: ");
-            for (int i = 0; i < msg.length; i++) {
-                builder.append(msg[i]);
-                builder.append(". ");
-            }
+            builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". ");
             builder.append("BAL Code: ");
             builder.append(code);
             Slog.d(TAG,  builder.toString());
@@ -482,4 +485,27 @@
                 /* name= */ "system_exempt_from_activity_bg_start_restriction_enabled",
                 /* defaultValue= */ true);
     }
+
+    private static void statsLogBalAllowed(
+            @BalCode int code, int callingUid, int realCallingUid, Intent intent) {
+        if (code == BAL_ALLOW_PENDING_INTENT
+                && (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
+            String activityName =
+                    intent != null ? intent.getComponent().flattenToShortString() : "";
+            FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+                    activityName,
+                    code,
+                    callingUid,
+                    realCallingUid);
+        }
+        if (code == BAL_ALLOW_PERMISSION || code == BAL_ALLOW_FOREGROUND
+                    || code == BAL_ALLOW_SAW_PERMISSION) {
+            // We don't need to know which activity in this case.
+            FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+                    /*activityName*/ "",
+                    code,
+                    callingUid,
+                    realCallingUid);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 9298afc..74f0ddc 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -104,37 +104,29 @@
             long lastActivityFinishTime) {
         // Allow if the proc is instrumenting with background activity starts privs.
         if (hasBackgroundActivityStartPrivileges) {
-            if (DEBUG_ACTIVITY_STARTS) {
-                Slog.d(TAG, "[Process(" + pid
-                        + ")] Activity start allowed: process instrumenting with background "
+            return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+                    BAL_ALLOW_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
+                    pid, "Activity start allowed: process instrumenting with background "
                         + "activity starts privileges");
-            }
-            return BAL_ALLOW_PERMISSION;
         }
         // Allow if the flag was explicitly set.
         if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
-            if (DEBUG_ACTIVITY_STARTS) {
-                Slog.d(TAG, "[Process(" + pid
-                        + ")] Activity start allowed: process allowed by token");
-            }
-            return BAL_ALLOW_PERMISSION;
+            return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+                    BAL_ALLOW_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
+                    pid, "Activity start allowed: process allowed by token");
         }
         // Allow if the caller is bound by a UID that's currently foreground.
         if (isBoundByForegroundUid()) {
-            if (DEBUG_ACTIVITY_STARTS) {
-                Slog.d(TAG, "[Process(" + pid
-                        + ")] Activity start allowed: process bound by foreground uid");
-            }
-            return BAL_ALLOW_VISIBLE_WINDOW;
+            return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+                    BAL_ALLOW_VISIBLE_WINDOW, /*background*/ false, uid, uid, /*intent*/ null,
+                    pid, "Activity start allowed: process bound by foreground uid");
         }
         // Allow if the caller has an activity in any foreground task.
         if (hasActivityInVisibleTask
                 && (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
-            if (DEBUG_ACTIVITY_STARTS) {
-                Slog.d(TAG, "[Process(" + pid
-                        + ")] Activity start allowed: process has activity in foreground task");
-            }
-            return BAL_ALLOW_FOREGROUND;
+            return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+                    BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
+                    pid, "Activity start allowed: process has activity in foreground task");
         }
 
         // If app switching is not allowed, we ignore all the start activity grace period
@@ -149,12 +141,10 @@
                 // let app to be able to start background activity even it's in grace period.
                 if (lastActivityLaunchTime > lastStopAppSwitchesTime
                         || lastActivityFinishTime > lastStopAppSwitchesTime) {
-                    if (DEBUG_ACTIVITY_STARTS) {
-                        Slog.d(TAG, "[Process(" + pid
-                                + ")] Activity start allowed: within "
-                                + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
-                    }
-                    return BAL_ALLOW_GRACE_PERIOD;
+                    return BackgroundActivityStartController.logStartAllowedAndReturnCode(
+                            BAL_ALLOW_GRACE_PERIOD, /*background*/ true, uid, uid, /*intent*/ null,
+                            pid, "Activity start allowed: within "
+                                    + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
                 }
                 if (DEBUG_ACTIVITY_STARTS) {
                     Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0e61b46..8cd22fe 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5658,8 +5658,8 @@
         final Rect df = state.getDisplayFrame();
         final Insets gestureInsets = state.calculateInsets(df, systemGestures(),
                 false /* ignoreVisibility */);
-        mSystemGestureFrameLeft.set(df.left, df.top, gestureInsets.left, df.bottom);
-        mSystemGestureFrameRight.set(gestureInsets.right, df.top, df.right, df.bottom);
+        mSystemGestureFrameLeft.set(df.left, df.top, df.left + gestureInsets.left, df.bottom);
+        mSystemGestureFrameRight.set(df.right - gestureInsets.right, df.top, df.right, df.bottom);
 
         final Region touchableRegion = Region.obtain();
         final Region local = Region.obtain();
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index cbc36c3..5a481f4 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1000,7 +1000,7 @@
 
     @VisibleForTesting
     boolean shouldShowLetterboxUi(WindowState mainWindow) {
-        return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
+        return isSurfaceVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
                 // Check for FLAG_SHOW_WALLPAPER explicitly instead of using
                 // WindowContainer#showWallpaper because the later will return true when this
                 // activity is using blurred wallpaper for letterbox background.
@@ -1008,11 +1008,8 @@
     }
 
     @VisibleForTesting
-    boolean isSurfaceReadyAndVisible(WindowState mainWindow) {
-        boolean surfaceReady = mainWindow.isDrawn() // Regular case
-                // Waiting for relayoutWindow to call preserveSurface
-                || mainWindow.isDragResizeChanged();
-        return surfaceReady && (mActivityRecord.isVisible()
+    boolean isSurfaceVisible(WindowState mainWindow) {
+        return mainWindow.isOnScreen() && (mActivityRecord.isVisible()
                 || mActivityRecord.isVisibleRequested());
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 88b82d7..e16b0f7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -175,6 +175,8 @@
     private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
     private static final String ATTR_PACKAGE_POLICY_MODE = "package-policy-type";
     private static final String TAG_CREDENTIAL_MANAGER_POLICY = "credential-manager-policy";
+    private static final String TAG_DIALER_PACKAGE = "dialer_package";
+    private static final String TAG_SMS_PACKAGE = "sms_package";
 
     // If the ActiveAdmin is a permission-based admin, then info will be null because the
     // permission-based admin is not mapped to a device administrator component.
@@ -350,6 +352,8 @@
     boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT;
 
     int mWifiMinimumSecurityLevel = DevicePolicyManager.WIFI_SECURITY_OPEN;
+    String mDialerPackage;
+    String mSmsPackage;
 
     ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
         this.info = info;
@@ -661,6 +665,12 @@
             mManagedSubscriptionsPolicy.saveToXml(out);
             out.endTag(null, TAG_MANAGED_SUBSCRIPTIONS_POLICY);
         }
+        if (!TextUtils.isEmpty(mDialerPackage)) {
+            writeAttributeValueToXml(out, TAG_DIALER_PACKAGE, mDialerPackage);
+        }
+        if (!TextUtils.isEmpty(mSmsPackage)) {
+            writeAttributeValueToXml(out, TAG_SMS_PACKAGE, mSmsPackage);
+        }
     }
 
     private void writePackagePolicy(TypedXmlSerializer out, String tag,
@@ -969,6 +979,10 @@
                 mManagedSubscriptionsPolicy = ManagedSubscriptionsPolicy.readFromXml(parser);
             } else if (TAG_CREDENTIAL_MANAGER_POLICY.equals(tag)) {
                 mCredentialManagerPolicy = readPackagePolicy(parser);
+            } else if (TAG_DIALER_PACKAGE.equals(tag)) {
+                mDialerPackage = parser.getAttributeValue(null, ATTR_VALUE);
+            } else if (TAG_SMS_PACKAGE.equals(tag)) {
+                mSmsPackage = parser.getAttributeValue(null, ATTR_VALUE);
             } else {
                 Slogf.w(LOG_TAG, "Unknown admin tag: %s", tag);
                 XmlUtils.skipCurrentTag(parser);
@@ -1449,5 +1463,10 @@
             pw.println(mManagedSubscriptionsPolicy);
             pw.decreaseIndent();
         }
+
+        pw.print("mDialerPackage=");
+        pw.println(mDialerPackage);
+        pw.print("mSmsPackage=");
+        pw.println(mSmsPackage);
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b386598..729a482 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -19,24 +19,63 @@
 import static android.Manifest.permission.BIND_DEVICE_ADMIN;
 import static android.Manifest.permission.LOCK_DEVICE;
 import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_AIRPLANE_MODE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_APP_RESTRICTIONS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_AUTOFILL;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_BLUETOOTH;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CALLS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CERTIFICATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DISPLAY;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FUN;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCALE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCATION;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCK_TASK;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MICROPHONE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_MTE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PRINTING;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SAFE_BOOT;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SCREEN_CONTENT;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SMS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_TIME;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_USERS;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_VPN;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WALLPAPER;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WINDOWS;
 import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
 import static android.Manifest.permission.QUERY_ADMIN_POLICY;
 import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
@@ -47,11 +86,10 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION;
-import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS;
-import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION;
 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS;
+import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION;
 import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
 import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
@@ -78,11 +116,10 @@
 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
 import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
 import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION;
-import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_APP_STANDBY;
 import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS;
-import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION;
 import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_HIBERNATION;
 import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_POWER_RESTRICTIONS;
+import static android.app.admin.DevicePolicyManager.EXEMPT_FROM_SUSPENSION;
 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_IDS;
 import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE;
@@ -342,6 +379,7 @@
 import android.net.VpnManager;
 import android.net.metrics.IpConnectivityLog;
 import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -482,8 +520,12 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -748,7 +790,7 @@
             new ArrayMap<>();
     static {
         APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
-                EXEMPT_FROM_APP_STANDBY, OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY);
+                EXEMPT_FROM_SUSPENSION, OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION);
         APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
                 EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
                 OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS);
@@ -758,9 +800,6 @@
         APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
                 EXEMPT_FROM_HIBERNATION, OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION);
         APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
-                EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
-                OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION);
-        APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.put(
                 EXEMPT_FROM_POWER_RESTRICTIONS, OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS);
     }
 
@@ -843,6 +882,7 @@
     final UserManagerInternal mUserManagerInternal;
     final UsageStatsManagerInternal mUsageStatsManagerInternal;
     final TelephonyManager mTelephonyManager;
+    final RoleManager mRoleManager;
     private final LockPatternUtils mLockPatternUtils;
     private final LockSettingsInternal mLockSettingsInternal;
     private final DeviceAdminServiceController mDeviceAdminServiceController;
@@ -1630,6 +1670,10 @@
             return mContext.getSystemService(TelephonyManager.class);
         }
 
+        RoleManager getRoleManager() {
+            return mContext.getSystemService(RoleManager.class);
+        }
+
         TrustManager getTrustManager() {
             return (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
         }
@@ -1972,6 +2016,7 @@
         mIPackageManager = Objects.requireNonNull(injector.getIPackageManager());
         mIPermissionManager = Objects.requireNonNull(injector.getIPermissionManager());
         mTelephonyManager = Objects.requireNonNull(injector.getTelephonyManager());
+        mRoleManager = Objects.requireNonNull(injector.getRoleManager());
 
         mLocalService = new LocalService();
         mLockPatternUtils = injector.newLockPatternUtils();
@@ -4503,15 +4548,28 @@
     }
 
     @Override
-    public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
-        Objects.requireNonNull(admin, "ComponentName is null");
+    public boolean addCrossProfileWidgetProvider(ComponentName admin, String callerPackageName,
+            String packageName) {
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
+        ActiveAdmin activeAdmin;
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isProfileOwner(caller));
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            activeAdmin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwner(caller));
+            synchronized (getLockObject()) {
+                activeAdmin = getProfileOwnerLocked(caller.getUserId());
+            }
+        }
         List<String> changedProviders = null;
 
         synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin = getProfileOwnerLocked(caller.getUserId());
             if (activeAdmin.crossProfileWidgetProviders == null) {
                 activeAdmin.crossProfileWidgetProviders = new ArrayList<>();
             }
@@ -4525,7 +4583,7 @@
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.ADD_CROSS_PROFILE_WIDGET_PROVIDER)
-                .setAdmin(admin)
+                .setAdmin(caller.getPackageName())
                 .write();
 
         if (changedProviders != null) {
@@ -4538,15 +4596,28 @@
     }
 
     @Override
-    public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
-        Objects.requireNonNull(admin, "ComponentName is null");
+    public boolean removeCrossProfileWidgetProvider(ComponentName admin, String callerPackageName,
+            String packageName) {
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
+        ActiveAdmin activeAdmin;
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isProfileOwner(caller));
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            activeAdmin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwner(caller));
+            synchronized (getLockObject()) {
+                activeAdmin = getProfileOwnerLocked(caller.getUserId());
+            }
+        }
         List<String> changedProviders = null;
 
         synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin = getProfileOwnerLocked(caller.getUserId());
             if (activeAdmin.crossProfileWidgetProviders == null
                     || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
                 return false;
@@ -4560,7 +4631,7 @@
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.REMOVE_CROSS_PROFILE_WIDGET_PROVIDER)
-                .setAdmin(admin)
+                .setAdmin(caller.getPackageName())
                 .write();
 
         if (changedProviders != null) {
@@ -4573,14 +4644,27 @@
     }
 
     @Override
-    public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
-        Objects.requireNonNull(admin, "ComponentName is null");
+    public List<String> getCrossProfileWidgetProviders(ComponentName admin,
+            String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
+        ActiveAdmin activeAdmin;
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isProfileOwner(caller));
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            activeAdmin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwner(caller));
+            synchronized (getLockObject()) {
+                activeAdmin = getProfileOwnerLocked(caller.getUserId());
+            }
+        }
 
         synchronized (getLockObject()) {
-            ActiveAdmin activeAdmin = getProfileOwnerLocked(caller.getUserId());
             if (activeAdmin.crossProfileWidgetProviders == null
                     || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
                 return null;
@@ -4923,7 +5007,8 @@
         synchronized (getLockObject()) {
             if (isPermissionCheckFlagEnabled()) {
                 int affectedUser = parent ? getProfileParentId(userHandle) : userHandle;
-                enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser);
+                enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                        /*callerPackageName=*/ null, affectedUser);
             } else {
                 // This API can only be called by an active device admin,
                 // so try to retrieve it to check that the caller is one.
@@ -5211,7 +5296,8 @@
         if (isPermissionCheckFlagEnabled()) {
             int affectedUser = calledOnParent ? getProfileParentId(caller.getUserId())
                     : caller.getUserId();
-            enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser);
+            enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                    /*callerPackageName=*/ null, affectedUser);
         } else {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller) || isProfileOwner(caller));
@@ -5257,7 +5343,8 @@
                 if (!hasCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)) {
                     if (isPermissionCheckFlagEnabled()) {
                         int affectedUser = parent ? getProfileParentId(userHandle) : userHandle;
-                        enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS, affectedUser);
+                        enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                                /*callerPackageName=*/ null, affectedUser);
                     } else {
                         getActiveAdminForCallerLocked(
                                 null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
@@ -5994,9 +6081,16 @@
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
         final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        if (isPermissionCheckFlagEnabled()) {
+            Preconditions.checkCallAuthorization(
+                    hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES,
+                            caller.getPackageName(), caller.getUserId())
+                            || isCredentialManagementApp);
+        }  else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        }
         if (isCredentialManagementApp) {
             Preconditions.checkCallAuthorization(!isUserSelectable, "The credential "
                     + "management app is not allowed to install a user selectable key pair");
@@ -6059,9 +6153,16 @@
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
         final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        if (isPermissionCheckFlagEnabled()) {
+            Preconditions.checkCallAuthorization(
+                    hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES,
+                            caller.getPackageName(), caller.getUserId())
+                            || isCredentialManagementApp);
+        }  else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        }
         if (isCredentialManagementApp) {
             Preconditions.checkCallAuthorization(
                     isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -6124,8 +6225,13 @@
     }
 
     private boolean canInstallCertificates(CallerIdentity caller) {
-        return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
-                || isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+        if (isPermissionCheckFlagEnabled()) {
+            return hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES,
+                    caller.getPackageName(), caller.getUserId());
+        }  else {
+            return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+                    || isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+        }
     }
 
     private boolean canChooseCertificates(CallerIdentity caller) {
@@ -6318,9 +6424,16 @@
                     caller.getPackageName(), caller.getUid()));
             enforceIndividualAttestationSupportedIfRequested(attestationUtilsFlags);
         } else {
-            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                    || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+            if (isPermissionCheckFlagEnabled()) {
+                Preconditions.checkCallAuthorization(
+                        hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES,
+                                caller.getPackageName(), caller.getUserId())
+                                || isCredentialManagementApp);
+            }  else {
+                Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(
+                        caller) || isDefaultDeviceOwner(caller))) || (caller.hasPackage() && (
+                        isCallerDelegate || isCredentialManagementApp)));
+            }
             if (isCredentialManagementApp) {
                 Preconditions.checkCallAuthorization(
                         isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -6453,9 +6566,16 @@
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
         final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        if (isPermissionCheckFlagEnabled()) {
+            Preconditions.checkCallAuthorization(
+                    hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES,
+                            caller.getPackageName(), caller.getUserId())
+                            || isCredentialManagementApp);
+        } else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+        }
         if (isCredentialManagementApp) {
             Preconditions.checkCallAuthorization(
                     isAliasInCredentialManagementAppPolicy(caller, alias),
@@ -6851,7 +6971,9 @@
      * @return {@code true} if the calling process is a delegate of {@code scope}.
      */
     private boolean isCallerDelegate(CallerIdentity caller, String scope) {
-        Objects.requireNonNull(caller.getPackageName(), "callerPackage is null");
+        if (caller.getPackageName() == null) {
+            return false;
+        }
         Preconditions.checkArgument(Arrays.asList(DELEGATIONS).contains(scope),
                 "Unexpected delegation scope: %s", scope);
 
@@ -6866,6 +6988,31 @@
     }
 
     /**
+     * Check whether a caller application has been delegated any scope via
+     * {@link #setDelegatedScopes} to access privileged APIs on the behalf of a profile owner or
+     * device owner.
+     * <p>
+     * This is done by checking that the calling package was granted any scope delegations and
+     * then comparing the calling UID with the UID of the calling package as reported by
+     * {@link PackageManager#getPackageUidAsUser}.
+     *
+     * @param caller the calling identity
+     * @return {@code true} if the calling process is a delegate of any scope.
+     */
+    private boolean isCallerDelegate(CallerIdentity caller) {
+        Objects.requireNonNull(caller.getPackageName(), "callerPackage is null");
+
+        synchronized (getLockObject()) {
+            // Retrieve user policy data.
+            final DevicePolicyData policy = getUserData(caller.getUserId());
+            // Retrieve the list of delegation scopes granted to callerPackage.
+            final List<String> scopes = policy.mDelegationMap.get(caller.getPackageName());
+            // Check callingUid only if callerPackage has the required scope delegation.
+            return scopes != null;
+        }
+    }
+
+    /**
      * Helper function to preserve delegation behavior pre-O when using the deprecated functions
      * {@code #setCertInstallerPackage} and {@code #setApplicationRestrictionsManagingPackage}.
      */
@@ -7214,31 +7361,41 @@
     }
 
     @Override
-    public void wipeDataWithReason(int flags, @NonNull String wipeReasonForUser,
-            boolean calledOnParentInstance, boolean factoryReset) {
+    public void wipeDataWithReason(String callerPackageName, int flags,
+            @NonNull String wipeReasonForUser, boolean calledOnParentInstance,
+            boolean factoryReset) {
         if (!mHasFeature && !hasCallingOrSelfPermission(permission.MASTER_CLEAR)) {
             return;
         }
-        final CallerIdentity caller = getCallerIdentity();
+        final CallerIdentity caller = getCallerIdentity(callerPackageName);
+        ActiveAdmin admin;
+
         boolean calledByProfileOwnerOnOrgOwnedDevice =
                 isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId());
-        if (calledOnParentInstance) {
-            Preconditions.checkCallAuthorization(calledByProfileOwnerOnOrgOwnedDevice,
-                    "Wiping the entire device can only be done by a profile owner on "
-                            + "organization-owned device.");
-        }
-        if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
-            Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                            || calledByProfileOwnerOnOrgOwnedDevice
-                            || isFinancedDeviceOwner(caller),
-                    "Only device owners or profile owners of organization-owned device can set "
-                            + "WIPE_RESET_PROTECTION_DATA");
-        }
-
-        final ActiveAdmin admin;
-        synchronized (getLockObject()) {
-            admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
-                    DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    /*admin=*/ null,
+                    MANAGE_DEVICE_POLICY_WIPE_DATA,
+                    caller.getPackageName(),
+                    factoryReset ? UserHandle.USER_ALL : getAffectedUser(calledOnParentInstance));
+            admin = enforcingAdmin.getActiveAdmin();
+        } else {
+            if (calledOnParentInstance) {
+                Preconditions.checkCallAuthorization(calledByProfileOwnerOnOrgOwnedDevice,
+                        "Wiping the entire device can only be done by a profile owner on "
+                                + "organization-owned device.");
+            }
+            if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
+                Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                                || calledByProfileOwnerOnOrgOwnedDevice
+                                || isFinancedDeviceOwner(caller),
+                        "Only device owners or profile owners of organization-owned device can set "
+                                + "WIPE_RESET_PROTECTION_DATA");
+            }
+            synchronized (getLockObject()) {
+                admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
+                        DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
+            }
         }
 
         Preconditions.checkCallAuthorization(
@@ -8484,18 +8641,19 @@
      * Set whether auto time is enabled on the device.
      */
     @Override
-    public void setAutoTimeEnabled(ComponentName who, boolean enabled) {
+    public void setAutoTimeEnabled(@Nullable ComponentName who, String callerPackageName,
+            boolean enabled) {
         if (!mHasFeature) {
             return;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (isPermissionCheckFlagEnabled()) {
             // The effect of this policy is device-wide.
-            enforcePermission(SET_TIME, UserHandle.USER_ALL);
+            enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                     || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                     caller));
@@ -8505,7 +8663,7 @@
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_AUTO_TIME)
-                .setAdmin(caller.getComponentName())
+                .setAdmin(caller.getPackageName())
                 .setBoolean(enabled)
                 .write();
     }
@@ -8514,17 +8672,17 @@
      * Returns whether auto time is used on the device or not.
      */
     @Override
-    public boolean getAutoTimeEnabled(ComponentName who) {
+    public boolean getAutoTimeEnabled(@Nullable ComponentName who, String callerPackageName) {
         if (!mHasFeature) {
             return false;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (isPermissionCheckFlagEnabled()) {
-            enforceCanQuery(SET_TIME, UserHandle.USER_ALL);
+            enforceCanQuery(caller.getPackageName(), SET_TIME, UserHandle.USER_ALL);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                     || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                     caller));
@@ -8537,39 +8695,40 @@
      * Set whether auto time zone is enabled on the device.
      */
     @Override
-    public void setAutoTimeZoneEnabled(ComponentName who, boolean enabled) {
+    public void setAutoTimeZoneEnabled(@Nullable ComponentName who, String callerPackageName,
+            boolean enabled) {
         if (!mHasFeature) {
             return;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
-
-        if (isPermissionCheckFlagEnabled()) {
-            // The effect of this policy is device-wide.
-            enforcePermission(SET_TIME_ZONE, UserHandle.USER_ALL);
-        } else {
-            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
-                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
-                    caller));
-        }
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            // The effect of this policy is device-wide.
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    SET_TIME_ZONE,
+                    caller.getPackageName(),
+                    UserHandle.USER_ALL
+            );
             mDevicePolicyEngine.setGlobalPolicy(
                     PolicyDefinition.AUTO_TIMEZONE,
                     // TODO(b/260573124): add correct enforcing admin when permission changes are
                     //  merged.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()),
+                    enforcingAdmin,
                     new BooleanPolicyValue(enabled));
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
+                    || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
+                    caller));
             mInjector.binderWithCleanCallingIdentity(() ->
                     mInjector.settingsGlobalPutInt(Global.AUTO_TIME_ZONE, enabled ? 1 : 0));
         }
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_AUTO_TIME_ZONE)
-                .setAdmin(caller.getComponentName())
+                .setAdmin(caller.getPackageName())
                 .setBoolean(enabled)
                 .write();
     }
@@ -8578,18 +8737,18 @@
      * Returns whether auto time zone is used on the device or not.
      */
     @Override
-    public boolean getAutoTimeZoneEnabled(ComponentName who) {
+    public boolean getAutoTimeZoneEnabled(@Nullable ComponentName who, String callerPackageName) {
         if (!mHasFeature) {
             return false;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (isPermissionCheckFlagEnabled()) {
             // The effect of this policy is device-wide.
-            enforceCanQuery(SET_TIME_ZONE, UserHandle.USER_ALL);
+            enforceCanQuery(caller.getPackageName(), SET_TIME_ZONE, UserHandle.USER_ALL);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
                     || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(
                     caller));
@@ -8752,16 +8911,16 @@
         }
 
         final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
-        final int userHandle = caller.getUserId();
+        final int userId = caller.getUserId();
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_CAMERA_DISABLED);
 
-        ActiveAdmin admin = null;
+        ActiveAdmin admin;
         if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     who,
                     MANAGE_DEVICE_POLICY_CAMERA,
                     caller.getPackageName(),
-                    getProfileParentUserIfRequested(userHandle, parent));
+                    getProfileParentUserIfRequested(userId, parent));
             admin = enforcingAdmin.getActiveAdmin();
         } else {
             Objects.requireNonNull(who, "ComponentName is null");
@@ -8778,20 +8937,20 @@
         synchronized (getLockObject()) {
             if (admin.disableCamera != disabled) {
                 admin.disableCamera = disabled;
-                saveSettingsLocked(userHandle);
+                saveSettingsLocked(userId);
             }
         }
         // Tell the user manager that the restrictions have changed.
-        pushUserRestrictions(userHandle);
+        pushUserRestrictions(userId);
 
-        final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
+        final int affectedUserId = parent ? getProfileParentId(userId) : userId;
         if (SecurityLog.isLoggingEnabled()) {
             SecurityLog.writeEvent(SecurityLog.TAG_CAMERA_POLICY_SET,
-                    who.getPackageName(), userHandle, affectedUserId, disabled ? 1 : 0);
+                    who.getPackageName(), userId, affectedUserId, disabled ? 1 : 0);
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED)
-                .setAdmin(caller.getComponentName())
+                .setAdmin(caller.getPackageName())
                 .setBoolean(disabled)
                 .setStrings(parent ? CALLED_FROM_PARENT : NOT_CALLED_FROM_PARENT)
                 .write();
@@ -8802,16 +8961,19 @@
      * active admins.
      */
     @Override
-    public boolean getCameraDisabled(ComponentName who, int userHandle, boolean parent) {
+    public boolean getCameraDisabled(ComponentName who, String callerPackageName, int userHandle,
+            boolean parent) {
         if (!mHasFeature) {
             return false;
         }
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         if (isPermissionCheckFlagEnabled()) {
             Preconditions.checkCallAuthorization(
-                    hasFullCrossUsersPermission(caller, userHandle) || isCameraServerUid(caller)
-                            || hasPermission(MANAGE_DEVICE_POLICY_CAMERA, userHandle)
-                            || hasPermission(QUERY_ADMIN_POLICY));
+                    hasFullCrossUsersPermission(caller, userHandle)
+                            || isCameraServerUid(caller)
+                            || hasPermission(MANAGE_DEVICE_POLICY_CAMERA,
+                                caller.getPackageName(), userHandle)
+                            || hasPermission(QUERY_ADMIN_POLICY, caller.getPackageName()));
         } else {
             Preconditions.checkCallAuthorization(
                     hasFullCrossUsersPermission(caller, userHandle) || isCameraServerUid(caller));
@@ -10170,6 +10332,8 @@
      *     (2.1.1) The caller is the profile owner.
      *     (2.1.2) The caller is from another app in the same user as the profile owner, AND
      *             the caller is the delegated cert installer.
+     * (3) The caller holds the
+     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_CERTIFICATES} permission.
      *
      *  For the device owner case, simply check that the caller is the device owner or the
      *  delegated certificate installer.
@@ -10182,19 +10346,23 @@
      */
     @VisibleForTesting
     boolean hasDeviceIdAccessUnchecked(String packageName, int uid) {
-        ComponentName deviceOwner = getDeviceOwnerComponent(true);
-        if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
-                || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
-            return true;
-        }
         final int userId = UserHandle.getUserId(uid);
-        ComponentName profileOwner = getProfileOwnerAsUser(userId);
-        final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
-                && (profileOwner.getPackageName().equals(packageName)
-                || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
-        if (isCallerProfileOwnerOrDelegate && (isProfileOwnerOfOrganizationOwnedDevice(userId)
-                || isUserAffiliatedWithDevice(userId))) {
-            return true;
+        if (isPermissionCheckFlagEnabled()) {
+            return hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, packageName, userId);
+        } else {
+            ComponentName deviceOwner = getDeviceOwnerComponent(true);
+            if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
+                    || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+                return true;
+            }
+            ComponentName profileOwner = getProfileOwnerAsUser(userId);
+            final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
+                    && (profileOwner.getPackageName().equals(packageName)
+                    || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
+            if (isCallerProfileOwnerOrDelegate && (isProfileOwnerOfOrganizationOwnedDevice(userId)
+                    || isUserAffiliatedWithDevice(userId))) {
+                return true;
+            }
         }
         return false;
     }
@@ -10452,6 +10620,33 @@
         }
     }
 
+    private void enforceCanQueryLockTaskLocked(ComponentName who, String callerPackageName) {
+        CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        final int userId = caller.getUserId();
+
+        enforceCanQuery(caller.getPackageName(), MANAGE_DEVICE_POLICY_LOCK_TASK, userId);
+        if (!canUserUseLockTaskLocked(userId)) {
+            throw new SecurityException("User " + userId + " is not allowed to use lock task");
+        }
+    }
+
+    private EnforcingAdmin enforceCanCallLockTaskLocked(ComponentName who,
+            String callerPackageName) {
+        CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        final int userId =  caller.getUserId();
+
+        EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                who,
+                MANAGE_DEVICE_POLICY_LOCK_TASK,
+                caller.getPackageName(),
+                userId
+        );
+        if (!canUserUseLockTaskLocked(userId)) {
+            throw new SecurityException("User " + userId + " is not allowed to use lock task");
+        }
+        return enforcingAdmin;
+    }
+
     private boolean isSystemUid(CallerIdentity caller) {
         return UserHandle.isSameApp(caller.getUid(), Process.SYSTEM_UID);
     }
@@ -10702,26 +10897,38 @@
     }
 
     @Override
-    public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
-            ComponentName activity) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(isProfileOwner(caller)
-                || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
+    public void addPersistentPreferredActivity(ComponentName who, String callerPackageName,
+            IntentFilter filter, ComponentName activity) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
-        final int userHandle = caller.getUserId();
+        final int userId = caller.getUserId();
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            EnforcingAdmin enforcingAdmin;
+            if (who == null) {
+                enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                        who,
+                        MANAGE_DEVICE_POLICY_LOCK_TASK,
+                        caller.getPackageName(),
+                        userId);
+            } else {
+                Preconditions.checkCallAuthorization(isProfileOwner(caller)
+                        || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
+                enforcingAdmin = getEnforcingAdminForCaller(who, callerPackageName);
+            }
             mDevicePolicyEngine.setLocalPolicy(
                     PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(filter),
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle),
+                    enforcingAdmin,
                     new ComponentNamePolicyValue(activity),
-                    userHandle);
+                    userId);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwner(caller)
+                    || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
             synchronized (getLockObject()) {
                 long id = mInjector.binderClearCallingIdentity();
                 try {
-                    mIPackageManager.addPersistentPreferredActivity(filter, activity, userHandle);
-                    mIPackageManager.flushPackageRestrictionsAsUser(userHandle);
+                    mIPackageManager.addPersistentPreferredActivity(filter, activity, userId);
+                    mIPackageManager.flushPackageRestrictionsAsUser(userId);
                 } catch (RemoteException re) {
                     // Shouldn't happen
                     Slog.wtf(LOG_TAG, "Error adding persistent preferred activity", re);
@@ -10734,32 +10941,44 @@
                 (activity != null ? activity.getPackageName() : null);
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.ADD_PERSISTENT_PREFERRED_ACTIVITY)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .setStrings(activityPackage, getIntentFilterActions(filter))
                 .write();
     }
 
     @Override
-    public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(isProfileOwner(caller)
-                || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
-
-        final int userHandle = caller.getUserId();
+    public void clearPackagePersistentPreferredActivities(ComponentName who,
+            String callerPackageName, String packageName) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        final int userId = caller.getUserId();
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            EnforcingAdmin enforcingAdmin;
+            if (who == null) {
+                enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                        who,
+                        MANAGE_DEVICE_POLICY_LOCK_TASK,
+                        caller.getPackageName(),
+                        userId);
+            } else {
+                Preconditions.checkCallAuthorization(isProfileOwner(caller)
+                        || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
+                enforcingAdmin = getEnforcingAdminForCaller(who, callerPackageName);
+            }
             clearPackagePersistentPreferredActivitiesFromPolicyEngine(
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle),
+                    enforcingAdmin,
                     packageName,
-                    userHandle);
+                    userId);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isProfileOwner(caller)
+                    || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
             synchronized (getLockObject()) {
                 long id = mInjector.binderClearCallingIdentity();
                 try {
                     mIPackageManager.clearPackagePersistentPreferredActivities(packageName,
-                            userHandle);
-                    mIPackageManager.flushPackageRestrictionsAsUser(userHandle);
+                            userId);
+                    mIPackageManager.flushPackageRestrictionsAsUser(userId);
                 } catch (RemoteException re) {
                     // Shouldn't happen
                     Slogf.wtf(
@@ -10807,19 +11026,86 @@
     }
 
     @Override
-    public void setDefaultSmsApplication(ComponentName admin, String packageName, boolean parent) {
-        Objects.requireNonNull(admin, "ComponentName is null");
+    public void setDefaultSmsApplication(ComponentName admin, String callerPackageName,
+            String packageName, boolean parent) {
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
+        final int userId;
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
+        if (isPermissionCheckFlagEnabled()) {
+            enforcePermission(
+                    MANAGE_DEVICE_POLICY_DEFAULT_SMS,
+                    caller.getPackageName(),
+                    getAffectedUser(parent));
+        } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                    || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
+        }
         if (parent) {
+            userId = getProfileParentId(mInjector.userHandleGetCallingUserId());
             mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage(
-                    packageName, getProfileParentId(mInjector.userHandleGetCallingUserId())));
+                    packageName, userId));
+        } else {
+            userId = mInjector.userHandleGetCallingUserId();
         }
 
         mInjector.binderWithCleanCallingIdentity(() ->
-                SmsApplication.setDefaultApplication(packageName, mContext));
+                SmsApplication.setDefaultApplicationAsUser(packageName, mContext, userId));
+
+        synchronized (getLockObject()) {
+            final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
+                    getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent);
+            if (!Objects.equals(activeAdmin.mSmsPackage, packageName)) {
+                activeAdmin.mSmsPackage = packageName;
+                saveSettingsLocked(caller.getUserId());
+            }
+        }
+    }
+
+    @Override
+    public void setDefaultDialerApplication(String packageName) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
+            return;
+        }
+
+        final CallerIdentity caller = getCallerIdentity();
+        final int callerUserId = caller.getUserId();
+        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                || isProfileOwnerOfOrganizationOwnedDevice(caller));
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            CompletableFuture<Void> future = new CompletableFuture<>();
+            Consumer<Boolean> callback = successful -> {
+                if (successful) {
+                    future.complete(null);
+                } else {
+                    future.completeExceptionally(new IllegalArgumentException(
+                            packageName +  " cannot be set as the dialer"));
+                }
+            };
+            mRoleManager.addRoleHolderAsUser(
+                    RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(callerUserId),
+                    AsyncTask.THREAD_POOL_EXECUTOR, callback);
+            try {
+                future.get(5, TimeUnit.SECONDS);
+            } catch (TimeoutException e) {
+                throw new IllegalArgumentException("Timeout when setting the app as the dialer", e);
+            } catch (ExecutionException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof IllegalArgumentException) {
+                    throw (IllegalArgumentException) cause;
+                } else {
+                    throw new IllegalStateException(cause);
+                }
+            }
+        });
+        // Only save the package when the setting the role succeeded without exception.
+        synchronized (getLockObject()) {
+            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(callerUserId);
+            if (!Objects.equals(admin.mDialerPackage, packageName)) {
+                admin.mDialerPackage = packageName;
+                saveSettingsLocked(callerUserId);
+            }
+        }
     }
 
     @Override
@@ -10850,12 +11136,15 @@
     public void setApplicationRestrictions(ComponentName who, String callerPackage,
             String packageName, Bundle restrictions) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS)));
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
 
         if (useDevicePolicyEngine(caller, DELEGATION_APP_RESTRICTIONS)) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
+                    caller.getPackageName(),
+                    caller.getUserId()
+            );
             // This check is eventually made in UMS, checking here to fail early.
             String validationResult =
                     FrameworkParsingPackageUtils.validateName(packageName, false, false);
@@ -10863,27 +11152,26 @@
                 throw new IllegalArgumentException("Invalid package name: " + validationResult);
             }
 
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    who == null
-                            ? new ComponentName(caller.getPackageName(), "Delegate")
-                            : who,
-                    caller.getUserId());
-
             if (restrictions == null || restrictions.isEmpty()) {
                 mDevicePolicyEngine.removeLocalPolicy(
                         PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
-                        admin,
+                        enforcingAdmin,
                         caller.getUserId());
             } else {
                 mDevicePolicyEngine.setLocalPolicy(
                         PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
-                        admin,
+                        enforcingAdmin,
                         new BundlePolicyValue(restrictions),
                         caller.getUserId());
             }
             setBackwardsCompatibleAppRestrictions(
                     packageName, restrictions, caller.getUserHandle());
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_APP_RESTRICTIONS)));
             mInjector.binderWithCleanCallingIdentity(() -> {
                 mUserManager.setApplicationRestrictions(packageName, restrictions,
                         caller.getUserHandle());
@@ -10921,6 +11209,17 @@
                 ? null : policies.entrySet().stream().findAny().get().getValue().getValue();
     }
 
+    private int getUidForPackage(String packageName, int userId) {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            try {
+                return mContext.getPackageManager().getApplicationInfoAsUser(
+                        packageName, /* flags= */ 0, userId).uid;
+            } catch (NameNotFoundException exception) {
+                return -1;
+            }
+        });
+    }
+
     @Override
     public void setTrustAgentConfiguration(
             ComponentName admin, String callerPackageName, ComponentName agent,
@@ -11040,12 +11339,21 @@
     }
 
     @Override
-    public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+    public void addCrossProfileIntentFilter(ComponentName who, String callerPackageName,
+            IntentFilter filter, int flags) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         int callingUserId = caller.getUserId();
+
+        if (isPermissionCheckFlagEnabled()) {
+            enforcePermission(
+                    MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                    caller.getPackageName(),
+                    callingUserId);
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        }
         synchronized (getLockObject()) {
             long id = mInjector.binderClearCallingIdentity();
             try {
@@ -11072,7 +11380,7 @@
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.ADD_CROSS_PROFILE_INTENT_FILTER)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .setStrings(getIntentFilterActions(filter))
                 .setInt(flags)
                 .write();
@@ -11091,13 +11399,21 @@
     }
 
     @Override
-    public void clearCrossProfileIntentFilters(ComponentName who) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
-
+    public void clearCrossProfileIntentFilters(ComponentName who, String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         int callingUserId = caller.getUserId();
+
+        if (isPermissionCheckFlagEnabled()) {
+            enforcePermission(
+                    MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                    caller.getPackageName(),
+                    callingUserId);
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        }
+
         synchronized (getLockObject()) {
             long id = mInjector.binderClearCallingIdentity();
             try {
@@ -12166,24 +12482,29 @@
     public Bundle getApplicationRestrictions(ComponentName who, String callerPackage,
             String packageName) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS)));
 
         if (useDevicePolicyEngine(caller, DELEGATION_APP_RESTRICTIONS)) {
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    who != null ? who : new ComponentName(callerPackage, "Delegate"),
-                    caller.getUserId());
+            EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
+                    caller.getPackageName(),
+                    caller.getUserId()
+            );
 
             LinkedHashMap<EnforcingAdmin, PolicyValue<Bundle>> policies =
                     mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
                             PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
                             caller.getUserId());
-            if (policies.isEmpty() || !policies.containsKey(admin)) {
+            if (policies.isEmpty() || !policies.containsKey(enforcingAdmin)) {
                 return Bundle.EMPTY;
             }
-            return policies.get(admin).getValue();
+            return policies.get(enforcingAdmin).getValue();
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_APP_RESTRICTIONS)));
             return mInjector.binderWithCleanCallingIdentity(() -> {
                 Bundle bundle = mUserManager.getApplicationRestrictions(packageName,
                         caller.getUserHandle());
@@ -12230,11 +12551,25 @@
     @Override
     public String[] setPackagesSuspended(ComponentName who, String callerPackage,
             String[] packageNames, boolean suspended) {
-        Objects.requireNonNull(packageNames, "array of packages cannot be null");
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
+        ActiveAdmin admin;
+
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            admin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_PACKAGE_ACCESS)));
+            synchronized (getLockObject()) {
+                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
+            }
+        }
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PACKAGES_SUSPENDED);
 
         // Must remove the exempt apps from the input before calling PM, then add them back to
@@ -12276,7 +12611,6 @@
         }
 
         synchronized (getLockObject()) {
-            ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
             ArraySet<String> current = new ArraySet<>(admin.suspendedPackages);
             if (suspended) {
                 current.addAll(changed);
@@ -12316,9 +12650,18 @@
     @Override
     public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
+
+        if (isPermissionCheckFlagEnabled()) {
+            enforcePermission(
+                    MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                    caller.getPackageName(),
+                    caller.getUserId());
+        } else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_PACKAGE_ACCESS)));
+        }
 
         synchronized (getLockObject()) {
             long id = mInjector.binderClearCallingIdentity();
@@ -12368,52 +12711,21 @@
     public void setUserRestriction(
             ComponentName who, String callerPackage, String key, boolean enabledFromThisOwner,
             boolean parent) {
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+        int userId = caller.getUserId();
 
         if (!UserRestrictionsUtils.isValidRestriction(key)) {
             return;
         }
-        if (parent) {
-            Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
-        } else {
-            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
-        }
-        int userId = caller.getUserId();
-        synchronized (getLockObject()) {
-            if (isDefaultDeviceOwner(caller)) {
-                if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
-                    throw new SecurityException("Device owner cannot set user restriction " + key);
-                }
-                Preconditions.checkArgument(!parent,
-                        "Cannot use the parent instance in Device Owner mode");
-            } else if (isFinancedDeviceOwner(caller)) {
-                if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
-                    throw new SecurityException("Cannot set user restriction " + key
-                            + " when managing a financed device");
-                }
-                Preconditions.checkArgument(!parent,
-                        "Cannot use the parent instance in Financed Device Owner mode");
-            } else {
-                boolean profileOwnerCanChangeOnItself = !parent
-                        && UserRestrictionsUtils.canProfileOwnerChange(
-                                key, userId == getMainUserId());
-                boolean orgOwnedProfileOwnerCanChangeGlobally = parent
-                        && isProfileOwnerOfOrganizationOwnedDevice(caller)
-                        && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
-                        key);
-
-                if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
-                    throw new SecurityException("Profile owner cannot set user restriction " + key);
-                }
-            }
-        }
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    who, caller.getUserId());
+            EnforcingAdmin admin = enforcePermissionForUserRestriction(
+                    who,
+                    key,
+                    caller.getPackageName(),
+                    userId);
             PolicyDefinition<Boolean> policyDefinition =
                     PolicyDefinition.getPolicyDefinitionForUserRestriction(key);
             if (enabledFromThisOwner) {
@@ -12445,6 +12757,45 @@
                 }
             }
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            if (parent) {
+                Preconditions.checkCallAuthorization(
+                        isProfileOwnerOfOrganizationOwnedDevice(caller));
+            } else {
+                Preconditions.checkCallAuthorization(
+                        isDeviceOwner(caller) || isProfileOwner(caller));
+            }
+            synchronized (getLockObject()) {
+                if (isDefaultDeviceOwner(caller)) {
+                    if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
+                        throw new SecurityException("Device owner cannot set user restriction "
+                                + key);
+                    }
+                    Preconditions.checkArgument(!parent,
+                            "Cannot use the parent instance in Device Owner mode");
+                } else if (isFinancedDeviceOwner(caller)) {
+                    if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
+                        throw new SecurityException("Cannot set user restriction " + key
+                                + " when managing a financed device");
+                    }
+                    Preconditions.checkArgument(!parent,
+                            "Cannot use the parent instance in Financed Device Owner"
+                                    + " mode");
+                } else {
+                    boolean profileOwnerCanChangeOnItself = !parent
+                            && UserRestrictionsUtils.canProfileOwnerChange(
+                            key, userId == getMainUserId());
+                    boolean orgOwnedProfileOwnerCanChangeGlobally = parent
+                            && isProfileOwnerOfOrganizationOwnedDevice(caller)
+                            && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
+                            key);
+
+                    if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
+                        throw new SecurityException("Profile owner cannot set user restriction "
+                                + key);
+                    }
+                }
+            }
             synchronized (getLockObject()) {
                 final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
                         getProfileOwnerOrDeviceOwnerLocked(userId), parent);
@@ -12464,42 +12815,22 @@
     @Override
     public void setUserRestrictionGlobally(String callerPackage, String key) {
         final CallerIdentity caller = getCallerIdentity(callerPackage);
-        // TODO: Replace with new permission checks, for now copying this over from
-        //  setUserRestriction
         if (!UserRestrictionsUtils.isValidRestriction(key)) {
             return;
         }
-        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
 
         int userHandle = caller.getUserId();
-        if (isDefaultDeviceOwner(caller)) {
-            if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
-                throw new SecurityException("Device owner cannot set user restriction " + key);
-            }
-        } else if (isFinancedDeviceOwner(caller)) {
-            if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
-                throw new SecurityException("Cannot set user restriction " + key
-                        + " when managing a financed device");
-            }
-        } else {
-            boolean profileOwnerCanChangeOnItself =
-                    UserRestrictionsUtils.canProfileOwnerChange(key, userHandle == getMainUserId());
-            boolean orgOwnedProfileOwnerCanChangeGlobally =
-                    isProfileOwnerOfOrganizationOwnedDevice(caller)
-                    && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
-                    key);
-
-            if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
-                throw new SecurityException("Profile owner cannot set user restriction " + key);
-            }
-        }
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
 
         if (!useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
             throw new IllegalStateException("One or more admins are not targeting Android 14.");
         }
-        EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                caller.getPackageName(), caller.getUserId());
+        EnforcingAdmin admin = enforcePermissionForUserRestriction(
+                /*who=*/ null,
+                key,
+                caller.getPackageName(),
+                caller.getUserId()
+        );
 
         mDevicePolicyEngine.setGlobalPolicy(
                 PolicyDefinition.getPolicyDefinitionForUserRestriction(key),
@@ -12597,19 +12928,20 @@
         if (!mHasFeature) {
             return null;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                || isFinancedDeviceOwner(caller)
-                || isProfileOwner(caller)
-                || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
+        final CallerIdentity caller = getCallerIdentity(who, callerPackage);
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
             return getUserRestrictionsFromPolicyEngine(
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(who, caller.getUserId()),
+                    admin,
                     parent ? getProfileParentId(caller.getUserId()) : caller.getUserId());
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                    || isFinancedDeviceOwner(caller)
+                    || isProfileOwner(caller)
+                    || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
             synchronized (getLockObject()) {
                 final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
                         getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent);
@@ -12618,6 +12950,169 @@
         }
     }
 
+    // Map of user restriction to permission.
+    private static final HashMap<String, String> USER_RESTRICTION_PERMISSIONS = new HashMap<>();
+    {
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.ENSURE_VERIFY_APPS, MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_WIFI_TETHERING, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_WIFI_DIRECT, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_USER_SWITCH, MANAGE_DEVICE_POLICY_USERS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_USB_FILE_TRANSFER, MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_UNMUTE_MICROPHONE, MANAGE_DEVICE_POLICY_MICROPHONE);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_UNMUTE_DEVICE, MANAGE_DEVICE_POLICY_AUDIO_OUTPUT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_UNINSTALL_APPS, MANAGE_DEVICE_POLICY_APPS_CONTROL);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_UNIFIED_PASSWORD, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SMS, MANAGE_DEVICE_POLICY_SMS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SHARE_LOCATION, MANAGE_DEVICE_POLICY_LOCATION);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,
+                MANAGE_DEVICE_POLICY_PROFILE_INTERACTION);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SET_WALLPAPER, MANAGE_DEVICE_POLICY_WALLPAPER);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SET_USER_ICON, MANAGE_DEVICE_POLICY_USERS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_SAFE_BOOT, MANAGE_DEVICE_POLICY_SAFE_BOOT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_RUN_IN_BACKGROUND, MANAGE_DEVICE_POLICY_SAFE_BOOT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_REMOVE_USER, MANAGE_DEVICE_POLICY_USERS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_PRINTING, MANAGE_DEVICE_POLICY_PRINTING);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_OUTGOING_CALLS, MANAGE_DEVICE_POLICY_CALLS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_OUTGOING_BEAM, MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_NETWORK_RESET, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_MODIFY_ACCOUNTS, MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_MICROPHONE_TOGGLE, MANAGE_DEVICE_POLICY_MICROPHONE);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+                MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_INSTALL_APPS, MANAGE_DEVICE_POLICY_APPS_CONTROL);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_FUN, MANAGE_DEVICE_POLICY_FUN);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_FACTORY_RESET, MANAGE_DEVICE_POLICY_FACTORY_RESET);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_DEBUGGING_FEATURES, MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_DATA_ROAMING, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
+                MANAGE_DEVICE_POLICY_PROFILE_INTERACTION);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CREATE_WINDOWS, MANAGE_DEVICE_POLICY_WINDOWS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONTENT_SUGGESTIONS, MANAGE_DEVICE_POLICY_SCREEN_CONTENT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONTENT_CAPTURE, MANAGE_DEVICE_POLICY_SCREEN_CONTENT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_WIFI, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_VPN, MANAGE_DEVICE_POLICY_VPN);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_TETHERING, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, MANAGE_DEVICE_POLICY_DISPLAY);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_PRIVATE_DNS, MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_LOCATION, MANAGE_DEVICE_POLICY_LOCATION);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_LOCALE, MANAGE_DEVICE_POLICY_LOCALE);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_DATE_TIME, MANAGE_DEVICE_POLICY_TIME);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_CREDENTIALS, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_BRIGHTNESS, MANAGE_DEVICE_POLICY_DISPLAY);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_BLUETOOTH, MANAGE_DEVICE_POLICY_BLUETOOTH);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CHANGE_WIFI_STATE, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CAMERA_TOGGLE, MANAGE_DEVICE_POLICY_CAMERA);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CAMERA, MANAGE_DEVICE_POLICY_CAMERA);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_BLUETOOTH_SHARING, MANAGE_DEVICE_POLICY_BLUETOOTH);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_BLUETOOTH, MANAGE_DEVICE_POLICY_BLUETOOTH);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_BIOMETRIC, MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_AUTOFILL, MANAGE_DEVICE_POLICY_AUTOFILL);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_APPS_CONTROL, MANAGE_DEVICE_POLICY_APPS_CONTROL);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_AMBIENT_DISPLAY, MANAGE_DEVICE_POLICY_DISPLAY);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_AIRPLANE_MODE, MANAGE_DEVICE_POLICY_AIRPLANE_MODE);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_ADJUST_VOLUME, MANAGE_DEVICE_POLICY_AUDIO_OUTPUT);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_ADD_WIFI_CONFIG, MANAGE_DEVICE_POLICY_WIFI);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_ADD_USER, MANAGE_DEVICE_POLICY_USERS);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_ADD_CLONE_PROFILE, MANAGE_DEVICE_POLICY_PROFILES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.ALLOW_PARENT_PROFILE_APP_LINKING, MANAGE_DEVICE_POLICY_PROFILES);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CELLULAR_2G, MANAGE_DEVICE_POLICY_MOBILE_NETWORK);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,
+                MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION);
+
+        // Restrictions not allowed to be set by admins.
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_RECORD_AUDIO, null);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_WALLPAPER, null);
+        USER_RESTRICTION_PERMISSIONS.put(
+                UserManager.DISALLOW_CONFIG_DEFAULT_APPS, null);
+    }
+
+    private EnforcingAdmin enforcePermissionForUserRestriction(ComponentName who,
+            String userRestriction, String callerPackageName, int userId) {
+        String permission = USER_RESTRICTION_PERMISSIONS.get(userRestriction);
+        if (permission != null) {
+            return enforcePermissionAndGetEnforcingAdmin(who, permission, callerPackageName,
+                    userId);
+        }
+        throw new SecurityException("Admins are not permitted to set User Restriction: "
+                + userRestriction);
+    }
+
     @Override
     public Bundle getUserRestrictionsGlobally(String callerPackage) {
         if (!mHasFeature) {
@@ -12627,15 +13122,10 @@
         if (!useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
             throw new IllegalStateException("One or more admins are not targeting Android 14.");
         }
-        // TODO: Replace with new permission checks, for now copying this over from
-        //  setUserRestriction
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
-                || isFinancedDeviceOwner(caller)
-                || isProfileOwner(caller));
 
-        return getUserRestrictionsFromPolicyEngine(
-                EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                        caller.getPackageName(), caller.getUserId()),
+        EnforcingAdmin admin = getEnforcingAdminForCaller(/*who=*/ null, caller.getPackageName());
+
+        return getUserRestrictionsFromPolicyEngine(admin,
                 UserHandle.USER_ALL);
     }
 
@@ -12664,7 +13154,7 @@
         int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
         if (isPermissionCheckFlagEnabled()) {
             // TODO: We need to ensure the delegate with DELEGATION_PACKAGE_ACCESS can do this
-            enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, userId);
+            enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
         } else {
             Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                     && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -12718,7 +13208,7 @@
         int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
         if (isPermissionCheckFlagEnabled()) {
             // TODO: Also support DELEGATION_PACKAGE_ACCESS
-            enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, userId);
+            enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
         } else {
             Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                     && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -12911,31 +13401,40 @@
     }
 
     @Override
-    public void setAccountManagementDisabled(ComponentName who, String accountType,
-            boolean disabled, boolean parent) {
+    public void setAccountManagementDisabled(ComponentName who, String callerPackageName,
+            String accountType, boolean disabled, boolean parent) {
         if (!mHasFeature) {
             return;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         synchronized (getLockObject()) {
-            /*
-             * When called on the parent DPM instance (parent == true), affects active admin
-             * selection in two ways:
-             * * The ActiveAdmin must be of an org-owned profile owner.
-             * * The parent ActiveAdmin instance should be used for managing the restriction.
-             */
             final ActiveAdmin ap;
-            if (parent) {
-                ap = getParentOfAdminIfRequired(getOrganizationOwnedProfileOwnerLocked(caller),
-                        parent);
+            if (isPermissionCheckFlagEnabled()) {
+                EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                        who,
+                        MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+                        caller.getPackageName(),
+                        getAffectedUser(parent)
+                );
+                ap = enforcingAdmin.getActiveAdmin();
             } else {
-                Preconditions.checkCallAuthorization(
-                        isDefaultDeviceOwner(caller) || isProfileOwner(caller));
-                ap = getParentOfAdminIfRequired(
-                        getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent);
+                Objects.requireNonNull(who, "ComponentName is null");
+                /*
+                 * When called on the parent DPM instance (parent == true), affects active admin
+                 * selection in two ways:
+                 * * The ActiveAdmin must be of an org-owned profile owner.
+                 * * The parent ActiveAdmin instance should be used for managing the restriction.
+                 */
+                if (parent) {
+                    ap = getParentOfAdminIfRequired(getOrganizationOwnedProfileOwnerLocked(caller),
+                            parent);
+                } else {
+                    Preconditions.checkCallAuthorization(
+                            isDefaultDeviceOwner(caller) || isProfileOwner(caller));
+                    ap = getParentOfAdminIfRequired(
+                            getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), parent);
+                }
             }
-
             if (disabled) {
                 ap.accountTypesWithManagementDisabled.add(accountType);
             } else {
@@ -12946,19 +13445,24 @@
     }
 
     @Override
-    public String[] getAccountTypesWithManagementDisabled() {
-        return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId(), false);
+    public String[] getAccountTypesWithManagementDisabled(String callerPackageName) {
+        return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId(),
+                callerPackageName, false);
     }
 
     @Override
-    public String[] getAccountTypesWithManagementDisabledAsUser(int userId, boolean parent) {
+    public String[] getAccountTypesWithManagementDisabledAsUser(int userId,
+            String callerPackageName, boolean parent) {
         if (!mHasFeature) {
             return null;
         }
         Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
-
-        final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
+        final CallerIdentity caller = getCallerIdentity(callerPackageName);
+        if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, caller.getPackageName(), userId)
+                && !hasFullCrossUsersPermission(caller, userId)) {
+            throw new SecurityException("Caller does not have permission to call this on user: "
+                    + userId);
+        }
 
         synchronized (getLockObject()) {
             final ArraySet<String> resultSet = new ArraySet<>();
@@ -12988,24 +13492,25 @@
     public void setUninstallBlocked(ComponentName who, String callerPackage, String packageName,
             boolean uninstallBlocked) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
-                || isFinancedDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL)));
 
         if (useDevicePolicyEngine(caller, DELEGATION_BLOCK_UNINSTALL)) {
-            // TODO(b/260573124): Add correct enforcing admin when permission changes are
-            //  merged, and don't forget to handle delegates! Enterprise admins assume
-            //  component name isn't null.
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    who != null ? who : new ComponentName(callerPackage, "delegate"),
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_APPS_CONTROL,
+                    caller.getPackageName(),
                     caller.getUserId());
             mDevicePolicyEngine.setLocalPolicy(
                     PolicyDefinition.PACKAGE_UNINSTALL_BLOCKED(packageName),
-                    admin,
+                    enforcingAdmin,
                     new BooleanPolicyValue(uninstallBlocked),
                     caller.getUserId());
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+                    || isFinancedDeviceOwner(caller)))
+                    || (caller.hasPackage()
+                    && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL)));
             final int userId = caller.getUserId();
             synchronized (getLockObject()) {
                 long id = mInjector.binderClearCallingIdentity();
@@ -13056,20 +13561,13 @@
     }
 
     @Override
-    public boolean isUninstallBlocked(ComponentName who, String packageName) {
+    public boolean isUninstallBlocked(String packageName) {
         // This function should return true if and only if the package is blocked by
         // setUninstallBlocked(). It should still return false for other cases of blocks, such as
         // when the package is a system app, or when it is an active device admin.
         final int userId = UserHandle.getCallingUserId();
 
         synchronized (getLockObject()) {
-            //TODO: This is a silly access control check. Remove.
-            if (who != null) {
-                final CallerIdentity caller = getCallerIdentity(who);
-                Preconditions.checkCallAuthorization(
-                        isProfileOwner(caller) || isDefaultDeviceOwner(caller)
-                                || isFinancedDeviceOwner(caller));
-            }
             try {
                 return mIPackageManager.getBlockUninstallForUser(packageName, userId);
             } catch (RemoteException re) {
@@ -13546,29 +14044,29 @@
     }
 
     @Override
-    public void setLockTaskPackages(ComponentName who, String[] packages)
+    public void setLockTaskPackages(ComponentName who, String callerPackageName, String[] packages)
             throws SecurityException {
-        Objects.requireNonNull(who, "ComponentName is null");
         Objects.requireNonNull(packages, "packages is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_PACKAGES);
         synchronized (getLockObject()) {
             enforceCanCallLockTaskLocked(caller);
-            checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_PACKAGES);
         }
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    who, caller.getUserId());
+            EnforcingAdmin enforcingAdmin;
+            synchronized (getLockObject()) {
+                enforcingAdmin = enforceCanCallLockTaskLocked(who, callerPackageName);
+            }
             if (packages.length == 0) {
                 mDevicePolicyEngine.removeLocalPolicy(
                         PolicyDefinition.LOCK_TASK,
-                        admin,
+                        enforcingAdmin,
                         caller.getUserId());
             } else {
                 LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                         PolicyDefinition.LOCK_TASK,
-                        admin,
+                        enforcingAdmin,
                         caller.getUserId());
                 LockTaskPolicy policy;
                 if (currentPolicy == null) {
@@ -13585,7 +14083,9 @@
                         caller.getUserId());
             }
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             synchronized (getLockObject()) {
+                enforceCanCallLockTaskLocked(caller);
                 final int userHandle = caller.getUserId();
                 setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages)));
             }
@@ -13602,16 +14102,14 @@
     }
 
     @Override
-    public String[] getLockTaskPackages(ComponentName who) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
+    public String[] getLockTaskPackages(ComponentName who, String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         final int userHandle = caller.getUserId();
 
-        synchronized (getLockObject()) {
-            enforceCanCallLockTaskLocked(caller);
-        }
-
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            synchronized (getLockObject()) {
+                enforceCanQueryLockTaskLocked(who, caller.getPackageName());
+            }
             LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy(
                     PolicyDefinition.LOCK_TASK, userHandle);
             if (policy == null) {
@@ -13620,7 +14118,9 @@
                 return policy.getPackages().toArray(new String[policy.getPackages().size()]);
             }
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             synchronized (getLockObject()) {
+                enforceCanCallLockTaskLocked(caller);
                 final List<String> packages = getUserData(userHandle).mLockTaskPackages;
                 return packages.toArray(new String[packages.size()]);
             }
@@ -13655,9 +14155,7 @@
     }
 
     @Override
-    public void setLockTaskFeatures(ComponentName who, int flags) {
-        Objects.requireNonNull(who, "ComponentName is null");
-
+    public void setLockTaskFeatures(ComponentName who, String callerPackageName, int flags) {
         // Throw if Overview is used without Home.
         boolean hasHome = (flags & LOCK_TASK_FEATURE_HOME) != 0;
         boolean hasOverview = (flags & LOCK_TASK_FEATURE_OVERVIEW) != 0;
@@ -13667,18 +14165,20 @@
         Preconditions.checkArgument(hasHome || !hasNotification,
             "Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME");
 
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         final int userHandle = caller.getUserId();
-        synchronized (getLockObject()) {
-            enforceCanCallLockTaskLocked(caller);
-            enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags);
-            checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
-        }
+        checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
+
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle);
+            EnforcingAdmin enforcingAdmin;
+            synchronized (getLockObject()) {
+                enforcingAdmin = enforceCanCallLockTaskLocked(who,
+                        callerPackageName);
+                enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags);
+            }
             LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                     PolicyDefinition.LOCK_TASK,
-                    admin,
+                    enforcingAdmin,
                     caller.getUserId());
             if (currentPolicy == null) {
                 throw new IllegalArgumentException("Can't set a lock task flags without setting "
@@ -13689,11 +14189,14 @@
 
             mDevicePolicyEngine.setLocalPolicy(
                     PolicyDefinition.LOCK_TASK,
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle),
+                    enforcingAdmin,
                     policy,
                     caller.getUserId());
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             synchronized (getLockObject()) {
+                enforceCanCallLockTaskLocked(caller);
+                enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags);
                 setLockTaskFeaturesLocked(userHandle, flags);
             }
         }
@@ -13707,15 +14210,14 @@
     }
 
     @Override
-    public int getLockTaskFeatures(ComponentName who) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
+    public int getLockTaskFeatures(ComponentName who, String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         final int userHandle = caller.getUserId();
-        synchronized (getLockObject()) {
-            enforceCanCallLockTaskLocked(caller);
-        }
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            synchronized (getLockObject()) {
+                enforceCanQueryLockTaskLocked(who, caller.getPackageName());
+            }
             LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy(
                     PolicyDefinition.LOCK_TASK, userHandle);
             if (policy == null) {
@@ -13725,7 +14227,9 @@
             }
             return policy.getFlags();
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             synchronized (getLockObject()) {
+                enforceCanCallLockTaskLocked(caller);
                 return getUserData(userHandle).mLockTaskFeatures;
             }
         }
@@ -13879,7 +14383,8 @@
         CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             Preconditions.checkNotNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(
@@ -13905,7 +14410,8 @@
         }
         CallerIdentity caller = getCallerIdentity(who);
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, /*callerPackageName=*/ null,
+                    UserHandle.USER_ALL);
         } else {
             Preconditions.checkNotNull(who, "ComponentName is null");
 
@@ -13999,14 +14505,13 @@
     }
 
     @Override
-    public boolean setTime(ComponentName who, long millis) {
-        Objects.requireNonNull(who, "ComponentName is null");
-
-        final CallerIdentity caller = getCallerIdentity(who);
+    public boolean setTime(@Nullable ComponentName who, String callerPackageName, long millis) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         if (isPermissionCheckFlagEnabled()) {
             // This is a global action.
-            enforcePermission(SET_TIME, UserHandle.USER_ALL);
+            enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
                             || isProfileOwnerOfOrganizationOwnedDevice(caller));
@@ -14018,21 +14523,21 @@
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_TIME)
-                .setAdmin(caller.getComponentName())
+                .setAdmin(caller.getPackageName())
                 .write();
         mInjector.binderWithCleanCallingIdentity(() -> mInjector.getAlarmManager().setTime(millis));
         return true;
     }
 
     @Override
-    public boolean setTimeZone(ComponentName who, String timeZone) {
-        Objects.requireNonNull(who, "ComponentName is null");
-
-        final CallerIdentity caller = getCallerIdentity(who);
+    public boolean setTimeZone(@Nullable ComponentName who, String callerPackageName,
+            String timeZone) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         if (isPermissionCheckFlagEnabled()) {
             // This is a global action.
-            enforcePermission(SET_TIME_ZONE, UserHandle.USER_ALL);
+            enforcePermission(SET_TIME_ZONE, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
                             || isProfileOwnerOfOrganizationOwnedDevice(caller));
@@ -14049,7 +14554,7 @@
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_TIME_ZONE)
-                .setAdmin(caller.getComponentName())
+                .setAdmin(caller.getPackageName())
                 .write();
         return true;
     }
@@ -14238,10 +14743,17 @@
     }
 
     @Override
-    public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+    public boolean setStatusBarDisabled(ComponentName who, String callerPackageName,
+            boolean disabled) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        if (isPermissionCheckFlagEnabled()) {
+            enforcePermission(MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(),
+                    UserHandle.USER_ALL);
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        }
 
         int userId = caller.getUserId();
         synchronized (getLockObject()) {
@@ -14273,7 +14785,7 @@
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_STATUS_BAR_DISABLED)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .setBoolean(disabled)
                 .write();
         return true;
@@ -14674,13 +15186,15 @@
         }
 
         @Override
-        public void enforcePermission(String permission, int targetUserId) {
-            DevicePolicyManagerService.this.enforcePermission(permission, targetUserId);
+        public void enforcePermission(String callerPackage, String permission, int targetUserId) {
+            DevicePolicyManagerService.this.enforcePermission(permission, callerPackage,
+                    targetUserId);
         }
 
         @Override
-        public boolean hasPermission(String permission, int targetUserId) {
-            return DevicePolicyManagerService.this.hasPermission(permission, targetUserId);
+        public boolean hasPermission(String callerPackage, String permission, int targetUserId) {
+            return DevicePolicyManagerService.this.hasPermission(permission, callerPackage,
+                    targetUserId);
         }
 
         private void broadcastIntentToCrossProfileManifestReceivers(
@@ -14910,33 +15424,38 @@
         }
 
         @Override
-        public Map<String, Bundle> getApplicationRestrictionsPerAdmin(
-                String packageName, int userId) {
+        public List<Bundle> getApplicationRestrictionsPerAdminForUser(
+                String packageName, @UserIdInt int userId) {
+            if (UserHandle.getCallingUserId() != userId
+                    || !UserHandle.isSameApp(
+                    Binder.getCallingUid(), getUidForPackage(packageName, userId))) {
+                final int uid = Binder.getCallingUid();
+                if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
+                    throw new SecurityException("Only system may: get application restrictions for "
+                            + "other user/app " + packageName);
+                }
+            }
             LinkedHashMap<EnforcingAdmin, PolicyValue<Bundle>> policies =
                     mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
                             PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
                             userId);
-            Map<String, Bundle> restrictions = new HashMap<>();
+            List<Bundle> restrictions = new ArrayList<>();
             for (EnforcingAdmin admin : policies.keySet()) {
-                restrictions.put(admin.getPackageName(), policies.get(admin).getValue());
+                restrictions.add(policies.get(admin).getValue());
             }
             if (!restrictions.isEmpty()) {
                 return restrictions;
             }
 
             return mInjector.binderWithCleanCallingIdentity(() -> {
-                // Could be a device that hasn't migrated yet, so just return any restrictions saved
-                // in userManager.
+                // Could be a device that has a DPC that hasn't migrated yet, so just return any
+                // restrictions saved in userManager.
                 Bundle bundle = mUserManager.getApplicationRestrictions(
                         packageName, UserHandle.of(userId));
                 if (bundle == null || bundle.isEmpty()) {
-                    return new HashMap<>();
+                    return new ArrayList<>();
                 }
-                ActiveAdmin admin = getMostProbableDPCAdminForLocalPolicy(userId);
-                if (admin == null) {
-                    return new HashMap<>();
-                }
-                return Map.of(admin.info.getPackageName(), bundle);
+                return List.of(bundle);
             });
         }
     }
@@ -15207,7 +15726,8 @@
 
         synchronized (getLockObject()) {
             if (isPermissionCheckFlagEnabled()) {
-                enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, UserHandle.USER_ALL);
+                enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, caller.getPackageName(),
+                        UserHandle.USER_ALL);
             } else {
                 Preconditions.checkCallAuthorization(
                         isProfileOwnerOfOrganizationOwnedDevice(caller)
@@ -15422,7 +15942,8 @@
         final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
         Preconditions.checkCallAuthorization((caller.hasAdminComponent()
                 && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+                || (caller.hasPackage() && isCallerDelegate(caller,
+                DELEGATION_PERMISSION_GRANT)));
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_POLICY);
 
         final int forUser = caller.getUserId();
@@ -15462,10 +15983,6 @@
         Objects.requireNonNull(callback);
 
         final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
-        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
-                || isFinancedDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_GRANT_STATE);
 
         synchronized (getLockObject()) {
@@ -15474,22 +15991,28 @@
             }
         }
         if (useDevicePolicyEngine(caller, DELEGATION_PERMISSION_GRANT)) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+                    callerPackage,
+                    caller.getUserId());
             // TODO(b/266924257): decide how to handle the internal state if the package doesn't
             //  exist, or the permission isn't requested by the app, because we could end up with
             //  inconsistent state between the policy engine and package manager. Also a package
             //  might get removed or has it's permission updated after we've set the policy.
             mDevicePolicyEngine.setLocalPolicy(
                     PolicyDefinition.PERMISSION_GRANT(packageName, permission),
-                    // TODO(b/260573124): Add correct enforcing admin when permission changes are
-                    //  merged, and don't forget to handle delegates! Enterprise admins assume
-                    //  component name isn't null.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()),
+                    enforcingAdmin,
                     new IntegerPolicyValue(grantState),
                     caller.getUserId());
             // TODO: update javadoc to reflect that callback no longer return success/failure
             callback.sendResult(Bundle.EMPTY);
         } else {
+            Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+                    || isFinancedDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_PERMISSION_GRANT)));
             synchronized (getLockObject()) {
             long ident = mInjector.binderClearCallingIdentity();
             try {
@@ -15562,10 +16085,16 @@
     public int getPermissionGrantState(ComponentName admin, String callerPackage,
             String packageName, String permission) throws RemoteException {
         final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
-        Preconditions.checkCallAuthorization(isSystemUid(caller) || (caller.hasAdminComponent()
-                && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
-                || isFinancedDeviceOwner(caller)))
-                || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+        if (isPermissionCheckFlagEnabled()) {
+            enforceCanQuery(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, caller.getPackageName(),
+                    caller.getUserId());
+        } else {
+            Preconditions.checkCallAuthorization(isSystemUid(caller) || (caller.hasAdminComponent()
+                    && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+                    || isFinancedDeviceOwner(caller)))
+                    || (caller.hasPackage() && isCallerDelegate(caller,
+                    DELEGATION_PERMISSION_GRANT)));
+        }
 
         synchronized (getLockObject()) {
             if (isFinancedDeviceOwner(caller)) {
@@ -15981,14 +16510,29 @@
     }
 
     @Override
-    public void setShortSupportMessage(@NonNull ComponentName who, CharSequence message) {
+    public void setShortSupportMessage(@Nullable ComponentName who, String callerPackageName,
+            CharSequence message) {
         if (!mHasFeature) {
             return;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        ActiveAdmin admin;
+
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            admin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            synchronized (getLockObject()) {
+                admin = getActiveAdminForUidLocked(who, caller.getUid());
+            }
+        }
+
         synchronized (getLockObject()) {
-            ActiveAdmin admin = getActiveAdminForUidLocked(who, caller.getUid());
             if (!TextUtils.equals(admin.shortSupportMessage, message)) {
                 admin.shortSupportMessage = message;
                 saveSettingsLocked(caller.getUserId());
@@ -15996,21 +16540,33 @@
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_SHORT_SUPPORT_MESSAGE)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .write();
     }
 
     @Override
-    public CharSequence getShortSupportMessage(@NonNull ComponentName who) {
+    public CharSequence getShortSupportMessage(@Nullable ComponentName who,
+            String callerPackageName) {
         if (!mHasFeature) {
             return null;
         }
-        Objects.requireNonNull(who, "ComponentName is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        synchronized (getLockObject()) {
-            ActiveAdmin admin = getActiveAdminForUidLocked(who, caller.getUid());
-            return admin.shortSupportMessage;
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        ActiveAdmin admin;
+
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            admin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            synchronized (getLockObject()) {
+                admin = getActiveAdminForUidLocked(who, caller.getUid());
+            }
         }
+        return admin.shortSupportMessage;
     }
 
     @Override
@@ -16162,7 +16718,8 @@
     }
 
     @Override
-    public void setOrganizationName(@Nullable ComponentName who, CharSequence text) {
+    public void setOrganizationName(@Nullable ComponentName who, String callerPackageName,
+            CharSequence text) {
         if (!mHasFeature) {
             return;
         }
@@ -16193,12 +16750,12 @@
     }
 
     @Override
-    public CharSequence getOrganizationName(@Nullable ComponentName who) {
+    public CharSequence getOrganizationName(@Nullable ComponentName who, String callerPackageName) {
         if (!mHasFeature) {
             return null;
         }
         CallerIdentity caller = getCallerIdentity(who);
-        ActiveAdmin admin = null;
+        ActiveAdmin admin;
 
         if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
@@ -16599,7 +17156,8 @@
         synchronized (getLockObject()) {
             if (isPermissionCheckFlagEnabled()) {
                 // TODO: add support for DELEGATION_SECURITY_LOGGING
-                enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL);
+                enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, caller.getPackageName(),
+                        UserHandle.USER_ALL);
             } else {
                 if (admin != null) {
                     Preconditions.checkCallAuthorization(
@@ -16640,7 +17198,8 @@
             if (!isSystemUid(getCallerIdentity())) {
                 final CallerIdentity caller = getCallerIdentity(admin, packageName);
                 if (isPermissionCheckFlagEnabled()) {
-                    enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL);
+                    enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
+                            caller.getPackageName(), UserHandle.USER_ALL);
                 } else {
                     if (admin != null) {
                         Preconditions.checkCallAuthorization(
@@ -16678,7 +17237,8 @@
         final CallerIdentity caller = getCallerIdentity(admin, packageName);
         if (isPermissionCheckFlagEnabled()) {
             // TODO: Restore the "affiliated users" check
-            enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             if (admin != null) {
                 Preconditions.checkCallAuthorization(
@@ -16729,7 +17289,8 @@
         final CallerIdentity caller = getCallerIdentity(admin, packageName);
         if (isPermissionCheckFlagEnabled()) {
             // TODO: Restore the "affiliated users" check
-            enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_SECURITY_LOGGING, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             if (admin != null) {
                 Preconditions.checkCallAuthorization(
@@ -17588,21 +18149,23 @@
     }
 
     @Override
-    public boolean setResetPasswordToken(ComponentName admin, byte[] token) {
+    public boolean setResetPasswordToken(ComponentName admin, String callerPackageName,
+            byte[] token) {
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
         if (token == null || token.length < 32) {
             throw new IllegalArgumentException("token must be at least 32-byte long");
         }
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
         final int userId = caller.getUserId();
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    admin, userId);
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                    caller.getPackageName(),
+                    UserHandle.USER_ALL);
             Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                     PolicyDefinition.RESET_PASSWORD_TOKEN,
                     enforcingAdmin,
@@ -17619,6 +18182,9 @@
                     userId);
             return true;
         } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
             synchronized (getLockObject()) {
                 DevicePolicyData policy = getUserData(userId);
                 policy.mPasswordTokenHandle = addEscrowToken(
@@ -17645,19 +18211,20 @@
     }
 
     @Override
-    public boolean clearResetPasswordToken(ComponentName admin) {
+    public boolean clearResetPasswordToken(ComponentName admin, String callerPackageName) {
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
         final int userId = caller.getUserId();
         boolean result = false;
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    admin, userId);
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                    caller.getPackageName(),
+                    UserHandle.USER_ALL);
             Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                     PolicyDefinition.RESET_PASSWORD_TOKEN,
                     enforcingAdmin,
@@ -17670,6 +18237,9 @@
                         userId);
             }
         } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
             synchronized (getLockObject()) {
                 DevicePolicyData policy = getUserData(userId);
                 if (policy.mPasswordTokenHandle != 0) {
@@ -17683,19 +18253,19 @@
     }
 
     @Override
-    public boolean isResetPasswordTokenActive(ComponentName admin) {
+    public boolean isResetPasswordTokenActive(ComponentName admin, String callerPackageName) {
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
-
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
         int userId = caller.getUserId();
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    admin, userId);
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                    caller.getPackageName(),
+                    UserHandle.USER_ALL);
             Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                     PolicyDefinition.RESET_PASSWORD_TOKEN,
                     enforcingAdmin,
@@ -17703,6 +18273,9 @@
             return isResetPasswordTokenActiveForUserLocked(
                     currentTokenHandle == null ? 0 : currentTokenHandle, userId);
         } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
             synchronized (getLockObject()) {
                 DevicePolicyData policy = getUserData(userId);
                 return isResetPasswordTokenActiveForUserLocked(policy.mPasswordTokenHandle, userId);
@@ -17720,24 +18293,26 @@
     }
 
     @Override
-    public boolean resetPasswordWithToken(ComponentName admin, String passwordOrNull, byte[] token,
+    public boolean resetPasswordWithToken(ComponentName admin, String callerPackageName,
+            String passwordOrNull, byte[] token,
             int flags) {
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
         Objects.requireNonNull(token);
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(
-                isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
 
         int userId = caller.getUserId();
         boolean result = false;
         final String password = passwordOrNull != null ? passwordOrNull : "";
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
-            EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                    admin, userId);
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    admin,
+                    MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                    caller.getPackageName(),
+                    UserHandle.USER_ALL);
             Long currentTokenHandle = mDevicePolicyEngine.getLocalPolicySetByAdmin(
                     PolicyDefinition.RESET_PASSWORD_TOKEN,
                     enforcingAdmin,
@@ -17748,6 +18323,9 @@
                 Slogf.w(LOG_TAG, "No saved token handle");
             }
         } else {
+            Objects.requireNonNull(admin, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isProfileOwner(caller) || isDefaultDeviceOwner(caller));
             synchronized (getLockObject()) {
                 DevicePolicyData policy = getUserData(userId);
                 if (policy.mPasswordTokenHandle != 0) {
@@ -18430,7 +19008,8 @@
 
         final CallerIdentity caller = getCallerIdentity(admin, callerPackageName);
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_SYSTEM_UPDATES, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
@@ -18827,11 +19406,11 @@
         for (int i = 0; i < exemptions.length; i++) {
             appOpExemptions[i] = APPLICATION_EXEMPTION_CONSTANTS_TO_APP_OPS.get(exemptions[i]);
         }
-//        DevicePolicyEventLogger
-//            .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS)
-//            .setAdmin(caller.getPackageName())
-//            .setStrings(packageName, appOpExemptions)
-//            .write();
+        DevicePolicyEventLogger
+            .createEvent(DevicePolicyEnums.SET_APPLICATION_EXEMPTIONS)
+            .setAdmin(caller.getPackageName())
+            .setStrings(packageName, appOpExemptions)
+            .write();
     }
 
     @Override
@@ -18901,28 +19480,34 @@
     }
 
     @Override
-    public void setUserControlDisabledPackages(ComponentName who, List<String> packages) {
-        Objects.requireNonNull(who, "ComponentName is null");
+    public void setUserControlDisabledPackages(ComponentName who, String callerPackageName,
+            List<String> packages) {
         Objects.requireNonNull(packages, "packages is null");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller)
-                || isFinancedDeviceOwner(caller));
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
         checkCanExecuteOrThrowUnsafe(
                 DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES);
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_APPS_CONTROL,
+                    caller.getPackageName(),
+                    caller.getUserId());
             Binder.withCleanCallingIdentity(() -> {
                 if (packages.isEmpty()) {
-                    removeUserControlDisabledPackages(caller);
+                    removeUserControlDisabledPackages(caller, enforcingAdmin);
                 } else {
-                    addUserControlDisabledPackages(caller, new HashSet<>(packages));
+                    addUserControlDisabledPackages(caller, enforcingAdmin, new HashSet<>(packages));
                 }
             });
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                    || isProfileOwner(caller) || isFinancedDeviceOwner(caller));
             synchronized (getLockObject()) {
-                ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
-                if (!Objects.equals(owner.protectedPackages, packages)) {
-                    owner.protectedPackages = packages.isEmpty() ? null : packages;
+                ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
+                if (!Objects.equals(admin.protectedPackages, packages)) {
+                    admin.protectedPackages = packages.isEmpty() ? null : packages;
                     saveSettingsLocked(caller.getUserId());
                     pushUserControlDisabledPackagesLocked(caller.getUserId());
                 }
@@ -18931,47 +19516,37 @@
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_USER_CONTROL_DISABLED_PACKAGES)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .setStrings(packages.toArray(new String[packages.size()]))
                 .write();
     }
 
-    private void addUserControlDisabledPackages(CallerIdentity caller, Set<String> packages) {
+    private void addUserControlDisabledPackages(CallerIdentity caller,
+            EnforcingAdmin enforcingAdmin, Set<String> packages) {
         if (isCallerDeviceOwner(caller)) {
             mDevicePolicyEngine.setGlobalPolicy(
                     PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
-                    // TODO(b/260573124): add correct enforcing admin when permission changes are
-                    //  merged.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()),
+                    enforcingAdmin,
                     new StringSetPolicyValue(packages));
         } else {
             mDevicePolicyEngine.setLocalPolicy(
                     PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
-                    // TODO(b/260573124): add correct enforcing admin when permission changes are
-                    //  merged.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()),
+                    enforcingAdmin,
                     new StringSetPolicyValue(packages),
                     caller.getUserId());
         }
     }
 
-    private void removeUserControlDisabledPackages(CallerIdentity caller) {
+    private void removeUserControlDisabledPackages(CallerIdentity caller,
+            EnforcingAdmin enforcingAdmin) {
         if (isCallerDeviceOwner(caller)) {
             mDevicePolicyEngine.removeGlobalPolicy(
                     PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
-                    // TODO(b/260573124): add correct enforcing admin when permission changes are
-                    //  merged.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()));
+                    enforcingAdmin);
         } else {
             mDevicePolicyEngine.removeLocalPolicy(
                     PolicyDefinition.USER_CONTROLLED_DISABLED_PACKAGES,
-                    // TODO(b/260573124): add correct enforcing admin when permission changes are
-                    //  merged.
-                    EnforcingAdmin.createEnterpriseEnforcingAdmin(
-                            caller.getComponentName(), caller.getUserId()),
+                    enforcingAdmin,
                     caller.getUserId());
         }
     }
@@ -18983,14 +19558,15 @@
     }
 
     @Override
-    public List<String> getUserControlDisabledPackages(ComponentName who) {
-        Objects.requireNonNull(who, "ComponentName is null");
-
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller)
-                || isFinancedDeviceOwner(caller));
+    public List<String> getUserControlDisabledPackages(ComponentName who,
+            String callerPackageName) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
 
         if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+            enforceCanQuery(
+                    caller.getPackageName(),
+                    MANAGE_DEVICE_POLICY_APPS_CONTROL,
+                    caller.getUserId());
             // This retrieves the policy for the calling user only, DOs for example can't know
             // what's enforced globally or on another user.
             Set<String> packages = mDevicePolicyEngine.getResolvedPolicy(
@@ -18998,30 +19574,47 @@
                     caller.getUserId());
             return packages == null ? Collections.emptyList() : packages.stream().toList();
         } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+                    || isProfileOwner(caller) || isFinancedDeviceOwner(caller));
             synchronized (getLockObject()) {
-                ActiveAdmin deviceOwner = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
-                return deviceOwner.protectedPackages != null
-                        ? deviceOwner.protectedPackages : Collections.emptyList();
+                ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
+                return admin.protectedPackages != null
+                        ? admin.protectedPackages : Collections.emptyList();
             }
         }
     }
 
     @Override
-    public void setCommonCriteriaModeEnabled(ComponentName who, boolean enabled) {
-        Objects.requireNonNull(who, "Admin component name must be provided");
-        final CallerIdentity caller = getCallerIdentity(who);
-        Preconditions.checkCallAuthorization(
-                isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
-                "Common Criteria mode can only be controlled by a device owner or "
-                        + "a profile owner on an organization-owned device.");
+    public void setCommonCriteriaModeEnabled(ComponentName who, String callerPackageName,
+            boolean enabled) {
+        final CallerIdentity caller = getCallerIdentity(who, callerPackageName);
+        final ActiveAdmin admin;
+
+        if (isPermissionCheckFlagEnabled()) {
+            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+                    who,
+                    MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE,
+                    caller.getPackageName(),
+                    caller.getUserId());
+            admin = enforcingAdmin.getActiveAdmin();
+        } else {
+            Objects.requireNonNull(who, "ComponentName is null");
+            Preconditions.checkCallAuthorization(
+                    isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+                    "Common Criteria mode can only be controlled by a device owner or "
+                            + "a profile owner on an organization-owned device.");
+            synchronized (getLockObject()) {
+                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
+            }
+        }
         synchronized (getLockObject()) {
-            final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
             admin.mCommonCriteriaMode = enabled;
             saveSettingsLocked(caller.getUserId());
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_COMMON_CRITERIA_MODE)
-                .setAdmin(who)
+                .setAdmin(caller.getPackageName())
                 .setBoolean(enabled)
                 .write();
     }
@@ -19040,6 +19633,7 @@
                 return admin.mCommonCriteriaMode;
             }
         }
+
         // Return aggregated state if caller is not admin (who == null).
         synchronized (getLockObject()) {
             // Only DO or COPE PO can turn on CC mode, so take a shortcut here and only look at
@@ -19863,10 +20457,14 @@
         });
     }
 
-    private boolean isDevicePolicyManagementRoleHolder(CallerIdentity caller) {
+    private boolean isCallerDevicePolicyManagementRoleHolder(CallerIdentity caller) {
+        int callerUid = caller.getUid();
         String devicePolicyManagementRoleHolderPackageName =
                 getDevicePolicyManagementRoleHolderPackageName(mContext);
-        return caller.getPackageName().equals(devicePolicyManagementRoleHolderPackageName);
+        int roleHolderUid = mInjector.getPackageManagerInternal().getPackageUid(
+                devicePolicyManagementRoleHolderPackageName, 0, caller.getUserId());
+
+        return callerUid == roleHolderUid;
     }
 
     private void resetInteractAcrossProfilesAppOps(@UserIdInt int userId) {
@@ -20646,7 +21244,8 @@
     public WifiSsidPolicy getWifiSsidPolicy() {
         final CallerIdentity caller = getCallerIdentity();
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, caller.getUserId());
+            enforcePermission(MANAGE_DEVICE_POLICY_WIFI, /*callerPackageName=*/ null,
+                    caller.getUserId());
         } else {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
@@ -21079,15 +21678,77 @@
             MANAGE_DEVICE_POLICY_PACKAGE_STATE,
             MANAGE_DEVICE_POLICY_LOCK,
             MANAGE_DEVICE_POLICY_FACTORY_RESET,
-            MANAGE_DEVICE_POLICY_KEYGUARD);
+            MANAGE_DEVICE_POLICY_KEYGUARD,
+            MANAGE_DEVICE_POLICY_CERTIFICATES,
+            MANAGE_DEVICE_POLICY_KEYGUARD,
+            MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+            MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+            MANAGE_DEVICE_POLICY_APPS_CONTROL,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
+            MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+            MANAGE_DEVICE_POLICY_CAMERA,
+            MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE,
+            MANAGE_DEVICE_POLICY_DEFAULT_SMS,
+            MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+            MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+            MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+            MANAGE_DEVICE_POLICY_STATUS_BAR,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
+            MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+            MANAGE_DEVICE_POLICY_AIRPLANE_MODE,
+            MANAGE_DEVICE_POLICY_AUDIO_OUTPUT,
+            MANAGE_DEVICE_POLICY_AUTOFILL,
+            MANAGE_DEVICE_POLICY_BLUETOOTH,
+            MANAGE_DEVICE_POLICY_CALLS,
+            MANAGE_DEVICE_POLICY_CAMERA,
+            MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+            MANAGE_DEVICE_POLICY_DISPLAY,
+            MANAGE_DEVICE_POLICY_FACTORY_RESET,
+            MANAGE_DEVICE_POLICY_FUN,
+            MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+            MANAGE_DEVICE_POLICY_LOCALE,
+            MANAGE_DEVICE_POLICY_LOCATION,
+            MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+            MANAGE_DEVICE_POLICY_MICROPHONE,
+            MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
+            MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
+            MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA,
+            MANAGE_DEVICE_POLICY_PRINTING,
+            MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS,
+            MANAGE_DEVICE_POLICY_PROFILES,
+            MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+            MANAGE_DEVICE_POLICY_SAFE_BOOT,
+            MANAGE_DEVICE_POLICY_SCREEN_CONTENT,
+            MANAGE_DEVICE_POLICY_SMS,
+            MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS,
+            MANAGE_DEVICE_POLICY_TIME,
+            MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER,
+            MANAGE_DEVICE_POLICY_USERS,
+            MANAGE_DEVICE_POLICY_VPN,
+            MANAGE_DEVICE_POLICY_WALLPAPER,
+            MANAGE_DEVICE_POLICY_WIFI,
+            MANAGE_DEVICE_POLICY_WINDOWS,
+            MANAGE_DEVICE_POLICY_APP_RESTRICTIONS
+    );
     private static final List<String> FINANCED_DEVICE_OWNER_PERMISSIONS = List.of(
             MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL,
             MANAGE_DEVICE_POLICY_ACROSS_USERS,
             MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
             MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
             MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
             MANAGE_DEVICE_POLICY_FACTORY_RESET,
-            MANAGE_DEVICE_POLICY_KEYGUARD);
+            MANAGE_DEVICE_POLICY_KEYGUARD,
+            MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+            MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+            MANAGE_DEVICE_POLICY_APPS_CONTROL,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
+            MANAGE_DEVICE_POLICY_CALLS,
+            MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+            MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+            MANAGE_DEVICE_POLICY_USERS,
+            MANAGE_DEVICE_POLICY_SAFE_BOOT,
+            MANAGE_DEVICE_POLICY_TIME);
     private static final List<String> PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE_PERMISSIONS =
             List.of(
                 MANAGE_DEVICE_POLICY_ACROSS_USERS,
@@ -21096,38 +21757,142 @@
                 SET_TIME_ZONE,
                 MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                 MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
-                    MANAGE_DEVICE_POLICY_WIFI,
-                    MANAGE_DEVICE_POLICY_WIPE_DATA,
-                    MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
-                    MANAGE_DEVICE_POLICY_SYSTEM_UPDATES,
-                    MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
-                    MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
-                    MANAGE_DEVICE_POLICY_MTE,
-                    MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
-                    MANAGE_DEVICE_POLICY_PACKAGE_STATE,
-                    MANAGE_DEVICE_POLICY_LOCK,
-                    MANAGE_DEVICE_POLICY_FACTORY_RESET,
-                    MANAGE_DEVICE_POLICY_KEYGUARD);
+                MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+                MANAGE_DEVICE_POLICY_APPS_CONTROL,
+                MANAGE_DEVICE_POLICY_WIFI,
+                MANAGE_DEVICE_POLICY_WIPE_DATA,
+                MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
+                MANAGE_DEVICE_POLICY_SYSTEM_UPDATES,
+                MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
+                MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
+                MANAGE_DEVICE_POLICY_MTE,
+                MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                MANAGE_DEVICE_POLICY_LOCK,
+                MANAGE_DEVICE_POLICY_FACTORY_RESET,
+                MANAGE_DEVICE_POLICY_KEYGUARD,
+                MANAGE_DEVICE_POLICY_AIRPLANE_MODE,
+                MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+                MANAGE_DEVICE_POLICY_AUDIO_OUTPUT,
+                MANAGE_DEVICE_POLICY_AUTOFILL,
+                MANAGE_DEVICE_POLICY_BLUETOOTH,
+                MANAGE_DEVICE_POLICY_CALLS,
+                MANAGE_DEVICE_POLICY_CAMERA,
+                MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+                MANAGE_DEVICE_POLICY_DISPLAY,
+                MANAGE_DEVICE_POLICY_FACTORY_RESET,
+                MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+                MANAGE_DEVICE_POLICY_LOCALE,
+                MANAGE_DEVICE_POLICY_LOCATION,
+                MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                MANAGE_DEVICE_POLICY_MICROPHONE,
+                MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
+                MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
+                MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA,
+                MANAGE_DEVICE_POLICY_PRINTING,
+                MANAGE_DEVICE_POLICY_PROFILES,
+                MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS,
+                MANAGE_DEVICE_POLICY_SAFE_BOOT,
+                MANAGE_DEVICE_POLICY_SCREEN_CONTENT,
+                MANAGE_DEVICE_POLICY_SMS,
+                MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS,
+                MANAGE_DEVICE_POLICY_TIME,
+                MANAGE_DEVICE_POLICY_VPN,
+                MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER,
+                MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE,
+                MANAGE_DEVICE_POLICY_DEFAULT_SMS,
+                MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
+                MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER,
+                MANAGE_DEVICE_POLICY_KEYGUARD,
+                MANAGE_DEVICE_POLICY_WIFI,
+                MANAGE_DEVICE_POLICY_WIPE_DATA,
+                MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
+                MANAGE_DEVICE_POLICY_SYSTEM_UPDATES,
+                MANAGE_DEVICE_POLICY_SECURITY_LOGGING,
+                MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING,
+                MANAGE_DEVICE_POLICY_MTE,
+                MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                MANAGE_DEVICE_POLICY_LOCK,
+                MANAGE_DEVICE_POLICY_FACTORY_RESET,
+                MANAGE_DEVICE_POLICY_KEYGUARD,
+                MANAGE_DEVICE_POLICY_CERTIFICATES);
     private static final List<String> PROFILE_OWNER_ON_USER_0_PERMISSIONS  = List.of(
             SET_TIME,
             SET_TIME_ZONE,
             MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
-            MANAGE_DEVICE_POLICY_WIPE_DATA,
-            MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
-            MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
-            MANAGE_DEVICE_POLICY_PACKAGE_STATE,
-            MANAGE_DEVICE_POLICY_LOCK,
-            MANAGE_DEVICE_POLICY_KEYGUARD);
-    private static final List<String> PROFILE_OWNER_PERMISSIONS  = List.of(
-            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
-            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
+            MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+            MANAGE_DEVICE_POLICY_APPS_CONTROL,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
             MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
             MANAGE_DEVICE_POLICY_WIPE_DATA,
             MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
             MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
             MANAGE_DEVICE_POLICY_PACKAGE_STATE,
             MANAGE_DEVICE_POLICY_LOCK,
-            MANAGE_DEVICE_POLICY_KEYGUARD);
+            MANAGE_DEVICE_POLICY_KEYGUARD,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
+            MANAGE_DEVICE_POLICY_AIRPLANE_MODE,
+            MANAGE_DEVICE_POLICY_BLUETOOTH,
+            MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+            MANAGE_DEVICE_POLICY_FACTORY_RESET,
+            MANAGE_DEVICE_POLICY_FUN,
+            MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+            MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
+            MANAGE_DEVICE_POLICY_USERS,
+            MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA,
+            MANAGE_DEVICE_POLICY_SAFE_BOOT,
+            MANAGE_DEVICE_POLICY_SMS,
+            MANAGE_DEVICE_POLICY_TIME,
+            MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER,
+            MANAGE_DEVICE_POLICY_WINDOWS,
+            MANAGE_DEVICE_POLICY_LOCK_TASK,
+            MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+            MANAGE_DEVICE_POLICY_CAMERA,
+            MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+            MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+            MANAGE_DEVICE_POLICY_STATUS_BAR,
+            MANAGE_DEVICE_POLICY_APP_RESTRICTIONS);
+    private static final List<String> PROFILE_OWNER_PERMISSIONS  = List.of(
+            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
+            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
+            MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+            MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+            MANAGE_DEVICE_POLICY_APPS_CONTROL,
+            MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+            MANAGE_DEVICE_POLICY_WIPE_DATA,
+            MANAGE_DEVICE_POLICY_SCREEN_CAPTURE,
+            MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+            MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+            MANAGE_DEVICE_POLICY_LOCK,
+            MANAGE_DEVICE_POLICY_KEYGUARD,
+            MANAGE_DEVICE_POLICY_APPS_CONTROL,
+            MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+            MANAGE_DEVICE_POLICY_AUDIO_OUTPUT,
+            MANAGE_DEVICE_POLICY_AUTOFILL,
+            MANAGE_DEVICE_POLICY_CALLS,
+            MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+            MANAGE_DEVICE_POLICY_DISPLAY,
+            MANAGE_DEVICE_POLICY_FACTORY_RESET,
+            MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+            MANAGE_DEVICE_POLICY_LOCALE,
+            MANAGE_DEVICE_POLICY_LOCATION,
+            MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+            MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
+            MANAGE_DEVICE_POLICY_PRINTING,
+            MANAGE_DEVICE_POLICY_PROFILES,
+            MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+            MANAGE_DEVICE_POLICY_SCREEN_CONTENT,
+            MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS,
+            MANAGE_DEVICE_POLICY_TIME,
+            MANAGE_DEVICE_POLICY_VPN,
+            MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+            MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+            MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+            MANAGE_DEVICE_POLICY_APP_RESTRICTIONS
+            );
 
     private static final HashMap<Integer, List<String>> DPC_PERMISSIONS = new HashMap<>();
     {
@@ -21139,8 +21904,18 @@
         DPC_PERMISSIONS.put(PROFILE_OWNER, PROFILE_OWNER_PERMISSIONS);
     }
 
+    // Map of permission Active admin DEVICE_POLICY.
     //TODO(b/254253251) Fill this map in as new permissions are added for policies.
     private static final HashMap<String, Integer> ACTIVE_ADMIN_POLICIES = new HashMap<>();
+    {
+        //Any ActiveAdmin is able to call the support message APIs without certain policies.
+        ACTIVE_ADMIN_POLICIES.put(MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE, null);
+    }
+    //Map of Permission to Delegate Scope.
+    private static final HashMap<String, String> DELEGATE_SCOPES = new HashMap<>();
+    {
+        DELEGATE_SCOPES.put(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, DELEGATION_PERMISSION_GRANT);
+    }
 
     private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
             new HashMap<>();
@@ -21157,6 +21932,7 @@
         // mte is intrinsically global so there is no cross-user permission
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MTE, null);
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_FACTORY_RESET, null);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_STATUS_BAR, null);
         // Organisation identity policy will involve data of other organisations on the device and
         // therefore the FULL cross-user permission is required.
         CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
@@ -21175,6 +21951,94 @@
                 MANAGE_DEVICE_POLICY_LOCK, MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
         CROSS_USER_PERMISSIONS.put(
                 MANAGE_DEVICE_POLICY_KEYGUARD, MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
+        // Granting runtime permissions can grant applications significant powers therefore the FULL
+        // cross-user permission is required.
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_APPS_CONTROL,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_LOCK_TASK,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_AIRPLANE_MODE,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_AUDIO_OUTPUT,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_AUTOFILL,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_BLUETOOTH,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_CALLS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_CAMERA,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_DISPLAY,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_FACTORY_RESET,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_FUN,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_LOCALE,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_LOCATION,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MICROPHONE,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_MOBILE_NETWORK,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PRINTING,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PROFILES,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PROFILE_INTERACTION,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SAFE_BOOT,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SCREEN_CONTENT,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SMS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_TIME,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_USERS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_VPN,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_WALLPAPER,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_WIFI,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_WINDOWS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_DEFAULT_SMS,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_PACKAGE_STATE,
+                 MANAGE_DEVICE_POLICY_ACROSS_USERS);
+        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_RESET_PASSWORD,
+                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
     }
 
     /**
@@ -21182,8 +22046,10 @@
      * specific user.
      * The given permission will be checked along with its associated cross-user permission if it
      * exists and the target user is different to the calling user.
-     * Returns the {@link ActiveAdmin} of the caller.
+     * Returns an {@link EnforcingAdmin} for the caller.
      *
+     * @param admin the component name of the admin.
+     * @param callerPackageName The package name  of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      * @throws SecurityException if the caller has not been granted the given permission,
@@ -21191,7 +22057,7 @@
      */
     private EnforcingAdmin enforcePermissionAndGetEnforcingAdmin(@Nullable ComponentName admin,
             String permission, String callerPackageName, int targetUserId) {
-        enforcePermission(permission, targetUserId);
+        enforcePermission(permission, callerPackageName, targetUserId);
         return getEnforcingAdminForCaller(admin, callerPackageName);
     }
 
@@ -21208,7 +22074,7 @@
      */
     private EnforcingAdmin enforceCanQueryAndGetEnforcingAdmin(@Nullable ComponentName admin,
             String permission, String callerPackageName, int targetUserId) {
-        enforceCanQuery(permission, targetUserId);
+        enforceCanQuery(permission, callerPackageName, targetUserId);
         return getEnforcingAdminForCaller(admin, callerPackageName);
     }
 
@@ -21223,14 +22089,15 @@
      * The given permission will be checked along with its associated cross-user permission if it
      * exists and the target user is different to the calling user.
      *
+     * @param callerPackageName The package name  of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      * @throws SecurityException if the caller has not been granted the given permission,
      * the associated cross-user permission if the caller's user is different to the target user.
      */
-    private void enforcePermission(String permission, int targetUserId)
+    private void enforcePermission(String permission, String callerPackageName, int targetUserId)
             throws SecurityException {
-        if (!hasPermission(permission, targetUserId)) {
+        if (!hasPermission(permission, callerPackageName, targetUserId)) {
             throw new SecurityException("Caller does not have the required permissions for "
                     + "this user. Permissions required: {"
                     + permission
@@ -21246,31 +22113,36 @@
      * The given permission will be checked along with its associated cross-user permission if it
      * exists and the target user is different to the calling user.
      *
+     * @param callerPackageName The package name  of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      * @throws SecurityException if the caller has not been granted the given permission,
      * the associated cross-user permission if the caller's user is different to the target user
      * and if the user has not been granted {@link QUERY_ADMIN_POLICY}.
      */
-    private void enforceCanQuery(String permission, int targetUserId) throws SecurityException {
-        if (hasPermission(QUERY_ADMIN_POLICY)) {
+    private void enforceCanQuery(String permission, String callerPackageName, int targetUserId)
+            throws SecurityException {
+        if (hasPermission(QUERY_ADMIN_POLICY, callerPackageName)) {
             return;
         }
-        enforcePermission(permission, targetUserId);
+        enforcePermission(permission, callerPackageName, targetUserId);
     }
 
     /**
      * Return whether the calling process has been granted permission to apply a device policy on
      * a specific user.
      *
+     * @param callerPackageName The package name  of the calling application.
      * @param permission The name of the permission being checked.
      * @param targetUserId The userId of the user which the caller needs permission to act on.
      */
-    private boolean hasPermission(String permission, int targetUserId) {
-        boolean hasPermissionOnOwnUser = hasPermission(permission);
+    private boolean hasPermission(String permission, String callerPackageName, int targetUserId) {
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
+        boolean hasPermissionOnOwnUser = hasPermission(permission, callerPackageName);
         boolean hasPermissionOnTargetUser = true;
-        if (hasPermissionOnOwnUser & getCallerIdentity().getUserId() != targetUserId) {
-            hasPermissionOnTargetUser = hasPermission(CROSS_USER_PERMISSIONS.get(permission));
+        if (hasPermissionOnOwnUser & caller.getUserId() != targetUserId) {
+            hasPermissionOnTargetUser = hasPermission(CROSS_USER_PERMISSIONS.get(permission),
+                    callerPackageName);
         }
         return hasPermissionOnOwnUser && hasPermissionOnTargetUser;
     }
@@ -21278,14 +22150,16 @@
     /**
      * Return whether the calling process has been granted the given permission.
      *
+     * @param callerPackageName The package name  of the calling application.
      * @param permission The name of the permission being checked.
      */
-    private boolean hasPermission(String permission) {
+    private boolean hasPermission(String permission, @NonNull String callerPackageName) {
+        Objects.requireNonNull(callerPackageName, "callerPackageName is null");
         if (permission == null) {
             return true;
         }
 
-        CallerIdentity caller = getCallerIdentity();
+        CallerIdentity caller = getCallerIdentity(callerPackageName);
 
         // Check if the caller holds the permission
         if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
@@ -21309,14 +22183,23 @@
             return DPC_PERMISSIONS.get(PROFILE_OWNER).contains(permission);
         }
         // Check the permission for the role-holder
-        if (isDevicePolicyManagementRoleHolder(caller)) {
+        if (isCallerDevicePolicyManagementRoleHolder(caller)) {
             return anyDpcHasPermission(permission, mContext.getUserId());
         }
+        if (DELEGATE_SCOPES.containsKey(permission)) {
+            return isCallerDelegate(caller, DELEGATE_SCOPES.get(permission));
+        }
         // Check if the caller is an active admin that uses a certain policy.
         if (ACTIVE_ADMIN_POLICIES.containsKey(permission)) {
             try {
-                return getActiveAdminForCallerLocked(
-                        null, ACTIVE_ADMIN_POLICIES.get(permission), false) != null;
+                if (ACTIVE_ADMIN_POLICIES.get(permission) != null) {
+                    return getActiveAdminForCallerLocked(
+                            null, ACTIVE_ADMIN_POLICIES.get(permission), false) != null;
+                } else {
+                    // If the permission maps to no policy (null) this means that any active admin
+                    // has permission.
+                    return getActiveAdminForUidLocked(null, caller.getUid()) != null;
+                }
             } catch (SecurityException e) {
                 // A security exception means there is not an active admin with permission and
                 // therefore
@@ -21356,13 +22239,20 @@
             String callerPackageName) {
         CallerIdentity caller = getCallerIdentity(callerPackageName);
         int userId = caller.getUserId();
-        ActiveAdmin admin = null;
+        ActiveAdmin admin;
         synchronized (getLockObject()) {
             admin = getActiveAdminUncheckedLocked(who, userId);
         }
         if (isDeviceOwner(caller) || isProfileOwner(caller)) {
             return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
         }
+        if (isCallerDelegate(caller)) {
+            ComponentName profileOwner = mOwners.getProfileOwnerComponent(caller.getUserId());
+            ComponentName dpc = profileOwner != null ? profileOwner :
+                    mOwners.getDeviceOwnerComponent();
+            ActiveAdmin dpcAdmin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
+            return EnforcingAdmin.createEnterpriseEnforcingAdmin(dpc, userId, dpcAdmin);
+        }
         if (getActiveAdminUncheckedLocked(who, userId) != null) {
             return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
         }
@@ -21372,6 +22262,11 @@
         return  EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
     }
 
+    private int getAffectedUser(boolean calledOnParent) {
+        int callingUserId = mInjector.userHandleGetCallingUserId();
+        return calledOnParent ? getProfileParentId(callingUserId) : callingUserId;
+    }
+
     private boolean isPermissionCheckFlagEnabled() {
         return DeviceConfig.getBoolean(
                 NAMESPACE_DEVICE_POLICY_MANAGER,
@@ -21428,7 +22323,8 @@
         }
 
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_MTE, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
@@ -21468,7 +22364,8 @@
     public int getMtePolicy(String callerPackageName) {
         final CallerIdentity caller = getCallerIdentity(callerPackageName);
         if (isPermissionCheckFlagEnabled()) {
-            enforcePermission(MANAGE_DEVICE_POLICY_MTE, UserHandle.USER_ALL);
+            enforcePermission(MANAGE_DEVICE_POLICY_MTE, caller.getPackageName(),
+                    UserHandle.USER_ALL);
         } else {
             Preconditions.checkCallAuthorization(
                     isDefaultDeviceOwner(caller)
@@ -21938,7 +22835,8 @@
     }
 
     private boolean isDevicePolicyEngineEnabled() {
-        return isDevicePolicyEngineFlagEnabled() && !hasDPCsNotSupportingCoexistence();
+        return isDevicePolicyEngineFlagEnabled() && !hasDPCsNotSupportingCoexistence()
+                && isPermissionCheckFlagEnabled();
     }
 
     private boolean isDevicePolicyEngineFlagEnabled() {
diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
index 8ceac79..de7dc3b 100644
--- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt
@@ -1394,6 +1394,22 @@
         return false
     }
 
+    private fun addAllowlistedRestrictedPermissionsUnchecked(
+        androidPackage: AndroidPackage,
+        appId: Int,
+        permissionNames: List<String>,
+        userId: Int
+    ) {
+        val newPermissionNames = getAllowlistedRestrictedPermissionsUnchecked(appId,
+            PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId
+        )?.let {
+            IndexedSet(permissionNames).apply { this += it }.toList()
+        } ?: permissionNames
+
+        setAllowlistedRestrictedPermissionsUnchecked(androidPackage, appId, newPermissionNames,
+            PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId)
+    }
+
     override fun removeAllowlistedRestrictedPermission(
         packageName: String,
         permissionName: String,
@@ -1445,7 +1461,7 @@
 
     private fun setAllowlistedRestrictedPermissions(
         packageName: String,
-        allowlistedPermissions: List<String>,
+        permissionNames: List<String>,
         allowlistedFlags: Int,
         userId: Int,
         isAddingPermission: Boolean
@@ -1480,7 +1496,7 @@
         }
 
         setAllowlistedRestrictedPermissionsUnchecked(
-            androidPackage, packageState.appId, allowlistedPermissions, allowlistedFlags, userId
+            androidPackage, packageState.appId, permissionNames, allowlistedFlags, userId
         )
 
         return true
@@ -1493,7 +1509,7 @@
     private fun setAllowlistedRestrictedPermissionsUnchecked(
         androidPackage: AndroidPackage,
         appId: Int,
-        allowlistedPermissions: List<String>,
+        permissionNames: List<String>,
         allowlistedFlags: Int,
         userId: Int
     ) {
@@ -1522,7 +1538,7 @@
                             PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM -> {
                                 mask = mask or PermissionFlags.SYSTEM_EXEMPT
                                 newFlags =
-                                    if (allowlistedPermissions.contains(requestedPermission)) {
+                                    if (permissionNames.contains(requestedPermission)) {
                                         newFlags or PermissionFlags.SYSTEM_EXEMPT
                                     } else {
                                         newFlags andInv PermissionFlags.SYSTEM_EXEMPT
@@ -1531,7 +1547,7 @@
                             PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE -> {
                                 mask = mask or PermissionFlags.UPGRADE_EXEMPT
                                 newFlags =
-                                    if (allowlistedPermissions.contains(requestedPermission)) {
+                                    if (permissionNames.contains(requestedPermission)) {
                                         newFlags or PermissionFlags.UPGRADE_EXEMPT
                                     } else {
                                         newFlags andInv PermissionFlags.UPGRADE_EXEMPT
@@ -1540,7 +1556,7 @@
                             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER -> {
                                 mask = mask or PermissionFlags.INSTALLER_EXEMPT
                                 newFlags =
-                                    if (allowlistedPermissions.contains(requestedPermission)) {
+                                    if (permissionNames.contains(requestedPermission)) {
                                         newFlags or PermissionFlags.INSTALLER_EXEMPT
                                     } else {
                                         newFlags andInv PermissionFlags.INSTALLER_EXEMPT
@@ -1856,10 +1872,15 @@
         @Suppress("NAME_SHADOWING")
         userIds.forEach { userId ->
             service.onPackageInstalled(androidPackage.packageName, userId)
+        }
+
+        @Suppress("NAME_SHADOWING")
+        userIds.forEach { userId ->
             // TODO: Remove when this callback receives packageState directly.
             val packageState =
                 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)!!
-            // TODO: Add allowlisting
+            addAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId,
+                params.allowlistedRestrictedPermissions, userId)
             setRequestedPermissionStates(packageState, userId, params.permissionStates)
         }
     }
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
index 59551a3..5a7b37a 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
@@ -962,7 +962,7 @@
         if (packageState.packageName == PLATFORM_PACKAGE_NAME) {
             return true
         }
-        if (!packageState.isPrivileged) {
+        if (!(packageState.isSystem && packageState.isPrivileged)) {
             return true
         }
         if (permission.packageName !in newState.systemState.privilegedPermissionAllowlistPackages) {
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
index 62dbd89..9f0e2f5 100644
--- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
+++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
@@ -16,12 +16,14 @@
 
 package com.android.server.restrictions;
 
+import android.annotation.UserIdInt;
 import android.app.AppGlobals;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.IRestrictionsManager;
+import android.content.Intent;
 import android.content.RestrictionsManager;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
@@ -35,6 +37,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemService;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * SystemService wrapper for the RestrictionsManager implementation. Publishes the
  * Context.RESTRICTIONS_SERVICE.
@@ -60,19 +65,31 @@
         final Context mContext;
         private final IUserManager mUm;
         private final IDevicePolicyManager mDpm;
+        private final DevicePolicyManagerInternal mDpmInternal;
 
         public RestrictionsManagerImpl(Context context) {
             mContext = context;
             mUm = (IUserManager) getBinderService(Context.USER_SERVICE);
             mDpm = (IDevicePolicyManager) getBinderService(Context.DEVICE_POLICY_SERVICE);
+            mDpmInternal = getLocalService(DevicePolicyManagerInternal.class);
         }
 
         @Override
+        @Deprecated
         public Bundle getApplicationRestrictions(String packageName) throws RemoteException {
             return mUm.getApplicationRestrictions(packageName);
         }
 
         @Override
+        public List<Bundle> getApplicationRestrictionsPerAdminForUser(
+                @UserIdInt int userId, String packageName) throws RemoteException {
+            if (mDpmInternal != null) {
+                return mDpmInternal.getApplicationRestrictionsPerAdminForUser(packageName, userId);
+            }
+            return new ArrayList<>();
+        }
+
+        @Override
         public boolean hasRestrictionsProvider() throws RemoteException {
             int userHandle = UserHandle.getCallingUserId();
             if (mDpm != null) {
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
index e2f56ba..94ee0a8 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -1584,11 +1584,7 @@
     @Test
     public void testConstructor_withNullContext_throws() throws Exception {
         expectThrows(
-                NullPointerException.class,
-                () ->
-                        new BackupManagerService(
-                                /* context */ null,
-                                new SparseArray<>()));
+                NullPointerException.class, () -> new BackupManagerService(/* context */ null));
     }
 
     /** Test that the constructor does not create {@link UserBackupManagerService} instances. */
@@ -1616,18 +1612,6 @@
         verify(lifecycle).publishService(Context.BACKUP_SERVICE, backupManagerService);
     }
 
-    /** testOnUnlockUser_forwards */
-    @Test
-    public void testOnUnlockUser_forwards() {
-        BackupManagerService backupManagerService = mock(BackupManagerService.class);
-        BackupManagerService.Lifecycle lifecycle =
-                new BackupManagerService.Lifecycle(mContext, backupManagerService);
-
-        lifecycle.onUserUnlocking(new TargetUser(new UserInfo(UserHandle.USER_SYSTEM, null, 0)));
-
-        verify(backupManagerService).onUnlockUser(UserHandle.USER_SYSTEM);
-    }
-
     /** testOnStopUser_forwards */
     @Test
     public void testOnStopUser_forwards() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 2583f44..bcd69fda 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -875,7 +875,7 @@
     @Test
     public void testLightStepIdleStateLocked_InvalidStates() {
         mDeviceIdleController.becomeActiveLocked("testing", 0);
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         // stepLightIdleStateLocked doesn't handle the ACTIVE case, so the state
         // should stay as ACTIVE.
         verifyLightStateConditions(LIGHT_STATE_ACTIVE);
@@ -888,7 +888,7 @@
     @Test
     public void testLightStepIdleStateLocked_Overriden() {
         enterLightState(LIGHT_STATE_OVERRIDE);
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
     }
 
@@ -906,18 +906,18 @@
         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
 
         // No active ops means INACTIVE should go straight to IDLE.
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
     }
 
@@ -934,18 +934,18 @@
         mDeviceIdleController.setJobsActive(true);
         mDeviceIdleController.setAlarmsActive(true);
         mDeviceIdleController.setActiveIdleOpsForTest(1);
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
     }
 
@@ -963,24 +963,24 @@
         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
 
         // No active ops means INACTIVE should go straight to IDLE.
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
         // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
     }
 
@@ -997,83 +997,24 @@
         mDeviceIdleController.setJobsActive(true);
         mDeviceIdleController.setAlarmsActive(true);
         mDeviceIdleController.setActiveIdleOpsForTest(1);
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
         // Should cycle between IDLE, WAITING_FOR_NETWORK, and IDLE_MAINTENANCE now.
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_WAITING_FOR_NETWORK);
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
-        verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
-    }
-
-    @Test
-    public void testLightStepIdleStateSkippedAlarms() {
-        setNetworkConnected(true);
-        mDeviceIdleController.setJobsActive(false);
-        mDeviceIdleController.setAlarmsActive(false);
-        mDeviceIdleController.setActiveIdleOpsForTest(0);
-
-        final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = ArgumentCaptor
-                .forClass(AlarmManager.OnAlarmListener.class);
-        doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
-                eq("DeviceIdleController.light"), alarmListenerCaptor.capture(), any());
-        doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
-                eq("DeviceIdleController.light"), alarmListenerCaptor.capture(), any());
-
-        // Set state to INACTIVE.
-        mDeviceIdleController.becomeActiveLocked("testing", 0);
-        setChargingOn(false);
-        setScreenOn(false);
-        verifyLightStateConditions(LIGHT_STATE_INACTIVE);
-
-        final AlarmManager.OnAlarmListener progressionListener =
-                alarmListenerCaptor.getAllValues().get(0);
-        final AlarmManager.OnAlarmListener maintenanceListener =
-                alarmListenerCaptor.getAllValues().get(1);
-
-        // Set things to make it look like the INACTIVE -> IDLE alarm didn't fire and the
-        // MAINTENANCE alarm just fired.
-        mInjector.nowElapsed = mDeviceIdleController.getNextLightMaintenanceAlarmTimeForTesting();
-        // If the non-wakeup alarm doesn't fire in a timely manner, we would see both fire at the
-        // same time.
-        progressionListener.onAlarm();
-        verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
-        maintenanceListener.onAlarm();
-        verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
-
-        assertTrue(mInjector.nowElapsed < mDeviceIdleController.getNextLightAlarmTimeForTesting());
-
-        // MAINTENANCE->IDLE alarm goes off at correct time.
-        mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
-        progressionListener.onAlarm();
-        verifyLightStateConditions(LIGHT_STATE_IDLE);
-
-        // Go back to MAINTENANCE
-        mInjector.nowElapsed = mDeviceIdleController.getNextLightMaintenanceAlarmTimeForTesting();
-        maintenanceListener.onAlarm();
-        verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
-
-        assertTrue(mInjector.nowElapsed < mDeviceIdleController.getNextLightAlarmTimeForTesting());
-        assertTrue(mInjector.nowElapsed
-                < mDeviceIdleController.getNextLightMaintenanceAlarmTimeForTesting());
-
-        // MAINTENANCE->IDLE alarm is delayed until IDLE->MAINTENANCE alarm goes off.
-        mInjector.nowElapsed = mDeviceIdleController.getNextLightMaintenanceAlarmTimeForTesting();
-        progressionListener.onAlarm();
-        verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
-        maintenanceListener.onAlarm();
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
     }
 
@@ -1097,8 +1038,6 @@
                 .forClass(AlarmManager.OnAlarmListener.class);
         doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
                 eq("DeviceIdleController.light"), alarmListenerCaptor.capture(), any());
-        doNothing().when(mAlarmManager).setWindow(anyInt(), anyLong(), anyLong(),
-                eq("DeviceIdleController.light"), alarmListenerCaptor.capture(), any());
 
         // Set state to INACTIVE.
         mDeviceIdleController.becomeActiveLocked("testing", 0);
@@ -1109,23 +1048,16 @@
         final long idleAfterInactiveExpiryTime =
                 mInjector.nowElapsed + mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
         alarmManagerInOrder.verify(mAlarmManager).setWindow(
-                eq(AlarmManager.ELAPSED_REALTIME),
+                eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
                 eq(idleAfterInactiveExpiryTime),
                 anyLong(), anyString(), any(), any(Handler.class));
-        // Maintenance alarm
-        alarmManagerInOrder.verify(mAlarmManager).setWindow(
-                eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
-                eq(idleAfterInactiveExpiryTime + idlingTimeMs),
-                anyLong(), anyString(), any(), any(Handler.class));
 
-        final AlarmManager.OnAlarmListener progressionListener =
+        final AlarmManager.OnAlarmListener alarmListener =
                 alarmListenerCaptor.getAllValues().get(0);
-        final AlarmManager.OnAlarmListener maintenanceListener =
-                alarmListenerCaptor.getAllValues().get(1);
 
         // INACTIVE -> IDLE alarm
         mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
-        progressionListener.onAlarm();
+        alarmListener.onAlarm();
         verifyLightStateConditions(LIGHT_STATE_IDLE);
         alarmManagerInOrder.verify(mAlarmManager).setWindow(
                 eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
@@ -1134,26 +1066,20 @@
 
         for (int i = 0; i < 2; ++i) {
             // IDLE->MAINTENANCE alarm
-            mInjector.nowElapsed =
-                    mDeviceIdleController.getNextLightMaintenanceAlarmTimeForTesting();
-            maintenanceListener.onAlarm();
+            mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
+            alarmListener.onAlarm();
             verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
             long maintenanceExpiryTime = mInjector.nowElapsed + maintenanceTimeMs;
             idlingTimeMs *= mConstants.LIGHT_IDLE_FACTOR;
             // Set MAINTENANCE->IDLE
             alarmManagerInOrder.verify(mAlarmManager).setWindow(
-                    eq(AlarmManager.ELAPSED_REALTIME),
-                    eq(maintenanceExpiryTime),
-                    anyLong(), anyString(), any(), any(Handler.class));
-            // Set IDLE->MAINTENANCE
-            alarmManagerInOrder.verify(mAlarmManager).setWindow(
                     eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
-                    eq(maintenanceExpiryTime + idlingTimeMs),
+                    eq(maintenanceExpiryTime),
                     anyLong(), anyString(), any(), any(Handler.class));
 
             // MAINTENANCE->IDLE alarm
             mInjector.nowElapsed = mDeviceIdleController.getNextLightAlarmTimeForTesting();
-            progressionListener.onAlarm();
+            alarmListener.onAlarm();
             verifyLightStateConditions(LIGHT_STATE_IDLE);
             // Set IDLE->MAINTENANCE again
             alarmManagerInOrder.verify(mAlarmManager).setWindow(
@@ -1180,37 +1106,45 @@
         verifyLightStateConditions(LIGHT_STATE_INACTIVE);
 
         // No active ops means INACTIVE should go straight to IDLE.
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
-        inOrder.verify(mDeviceIdleController).scheduleLightMaintenanceAlarmLocked(
-                longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT));
+        inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
+                longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT),
+                longThat(l -> l == mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX),
+                eq(true));
 
         // Should just alternate between IDLE and IDLE_MAINTENANCE now.
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
                 longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
-                longThat(l -> l == mConstants.FLEX_TIME_SHORT));
+                longThat(l -> l == mConstants.FLEX_TIME_SHORT),
+                eq(true));
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
-        inOrder.verify(mDeviceIdleController).scheduleLightMaintenanceAlarmLocked(
-                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT));
+        inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
+                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
+                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX),
+                eq(true));
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE_MAINTENANCE);
         inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
                 longThat(l -> l >= mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET),
-                longThat(l -> l == mConstants.FLEX_TIME_SHORT));
+                longThat(l -> l == mConstants.FLEX_TIME_SHORT),
+                eq(true));
 
         // Test that motion doesn't reset the idle timeout.
         mDeviceIdleController.handleMotionDetectedLocked(50, "test");
 
-        mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+        mDeviceIdleController.stepLightIdleStateLocked("testing");
         verifyLightStateConditions(LIGHT_STATE_IDLE);
-        inOrder.verify(mDeviceIdleController).scheduleLightMaintenanceAlarmLocked(
-                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT));
+        inOrder.verify(mDeviceIdleController).scheduleLightAlarmLocked(
+                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT),
+                longThat(l -> l > mConstants.LIGHT_IDLE_TIMEOUT_INITIAL_FLEX),
+                eq(true));
     }
 
     ///////////////// EXIT conditions ///////////////////
@@ -2230,7 +2164,7 @@
                 while (mDeviceIdleController.getLightState() != lightState) {
                     // Stepping through each state ensures that the proper features are turned
                     // on/off.
-                    mDeviceIdleController.stepLightIdleStateLocked("testing", true);
+                    mDeviceIdleController.stepLightIdleStateLocked("testing");
 
                     count++;
                     if (count > 10) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
index cd9d8a9..b203cf6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -37,7 +37,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-
 import android.Manifest;
 import android.annotation.UserIdInt;
 import android.app.backup.BackupManager;
@@ -54,13 +53,13 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
-import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.SystemService;
 import com.android.server.backup.utils.RandomAccessFileUtils;
 
 import org.junit.After;
@@ -104,8 +103,8 @@
     private FileDescriptor mFileDescriptorStub = new FileDescriptor();
 
     private BackupManagerServiceTestable mService;
+    private BackupManagerService.Lifecycle mServiceLifecycle;
     private static File sTestDir;
-    private SparseArray<UserBackupManagerService> mUserServices;
     private MockitoSession mSession;
 
     @Before
@@ -125,8 +124,6 @@
 
         mUserId = UserHandle.USER_SYSTEM;
 
-        mUserServices = new SparseArray<>();
-
         when(mUserManagerMock.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(mUserInfoMock);
         when(mUserManagerMock.getUserInfo(NON_SYSTEM_USER)).thenReturn(mUserInfoMock);
         // Null main user means there is no main user on the device.
@@ -142,8 +139,6 @@
 
         when(mContextMock.getSystemService(Context.JOB_SCHEDULER_SERVICE))
                 .thenReturn(mock(JobScheduler.class));
-        mService = new BackupManagerServiceTestable(mContextMock, mUserServices);
-        simulateUserUnlocked(UserHandle.USER_SYSTEM);
     }
 
     @After
@@ -154,21 +149,20 @@
 
     @Test
     public void onUnlockUser_startsUserService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
         ConditionVariable unlocked = new ConditionVariable(false);
 
-        mService.onUnlockUser(NON_SYSTEM_USER);
-        mService.getBackupHandler().post(unlocked::open);
-        unlocked.block();
+        simulateUserUnlocked(NON_SYSTEM_USER);
 
         assertNotNull(mService.getUserService(NON_SYSTEM_USER));
     }
 
     @Test
     public void startServiceForUser_backupDisabledGlobally_doesNotStartUserService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sBackupDisabled = true;
-        BackupManagerServiceTestable service =
-                new BackupManagerServiceTestable(mContextMock, new SparseArray<>());
+        BackupManagerServiceTestable service = new BackupManagerServiceTestable(mContextMock);
 
         service.startServiceForUser(UserHandle.USER_SYSTEM);
 
@@ -177,6 +171,7 @@
 
     @Test
     public void startServiceForUser_backupNotActiveForUser_doesNotStartUserService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
 
         mService.startServiceForUser(UserHandle.USER_SYSTEM);
@@ -186,7 +181,8 @@
 
     @Test
     public void startServiceForUser_backupEnabledGloballyAndActiveForUser_startsUserService() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
+
         mService.startServiceForUser(NON_SYSTEM_USER);
 
         assertNotNull(mService.getUserService(NON_SYSTEM_USER));
@@ -194,9 +190,9 @@
 
     @Test
     public void isBackupServiceActive_backupDisabledGlobally_returnFalse() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sBackupDisabled = true;
-        BackupManagerService service =
-                new BackupManagerServiceTestable(mContextMock, mUserServices);
+        BackupManagerService service = new BackupManagerServiceTestable(mContextMock);
         service.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
 
         assertFalse(service.isBackupServiceActive(UserHandle.USER_SYSTEM));
@@ -204,6 +200,7 @@
 
     @Test
     public void isBackupServiceActive_systemUser_isDefault_deactivated_returnsFalse() {
+        createBackupManagerServiceAndUnlockSystemUser();
         // If there's no 'main' user on the device, the default user is the system user.
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
 
@@ -212,20 +209,23 @@
 
     @Test
     public void isBackupServiceActive_systemUser_isNotDefault_returnsFalse() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        createBackupManagerServiceAndUnlockSystemUser();
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
 
         assertFalse(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
     }
 
     @Test
     public void isBackupServiceActive_systemUser_isDefault_returnsTrue() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         // If there's no 'main' user on the device, the default user is the system user.
         assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
     }
 
     @Test
     public void isBackupServiceActive_nonSystemUser_isDefault_systemUserDeactivated_returnsFalse() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
 
         assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
@@ -233,7 +233,7 @@
 
     @Test
     public void isBackupServiceActive_nonSystemUser_isDefault_deactivated_returnsFalse() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
         assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
@@ -241,19 +241,24 @@
 
     @Test
     public void isBackupServiceActive_nonSystemUser_isDefault_returnsTrue() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        createBackupManagerServiceAndUnlockSystemUser();
+
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
 
         assertTrue(mService.isBackupServiceActive(NON_SYSTEM_USER));
     }
 
     @Test
     public void isBackupServiceActive_nonSystemUser_isNotDefault_notActivated_returnsFalse() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         // By default non-system non-default users are not activated.
         assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
     }
 
     @Test
     public void isBackupServiceActive_nonSystemUser_isNotDefault_activated_returnsTrue() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
 
         assertTrue(mService.isBackupServiceActive(NON_SYSTEM_USER));
@@ -261,6 +266,7 @@
 
     @Test
     public void setBackupServiceActive_forSystemUserAndCallerSystemUid_createsService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sCallingUid = Process.SYSTEM_UID;
 
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
@@ -270,6 +276,7 @@
 
     @Test
     public void setBackupServiceActive_forSystemUserAndCallerRootUid_createsService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sCallingUid = Process.ROOT_UID;
 
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
@@ -279,6 +286,7 @@
 
     @Test
     public void setBackupServiceActive_forSystemUserAndCallerNonRootNonSystem_throws() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sCallingUid = Process.FIRST_APPLICATION_UID;
 
         try {
@@ -290,6 +298,7 @@
 
     @Test
     public void setBackupServiceActive_forManagedProfileAndCallerSystemUid_createsService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         simulateUserUnlocked(NON_SYSTEM_USER);
         when(mUserInfoMock.isManagedProfile()).thenReturn(true);
         BackupManagerServiceTestable.sCallingUid = Process.SYSTEM_UID;
@@ -301,6 +310,7 @@
 
     @Test
     public void setBackupServiceActive_forManagedProfileAndCallerRootUid_createsService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         simulateUserUnlocked(NON_SYSTEM_USER);
         when(mUserInfoMock.isManagedProfile()).thenReturn(true);
         BackupManagerServiceTestable.sCallingUid = Process.ROOT_UID;
@@ -312,6 +322,7 @@
 
     @Test
     public void setBackupServiceActive_forManagedProfileAndCallerNonRootNonSystem_throws() {
+        createBackupManagerServiceAndUnlockSystemUser();
         when(mUserInfoMock.isManagedProfile()).thenReturn(true);
         BackupManagerServiceTestable.sCallingUid = Process.FIRST_APPLICATION_UID;
 
@@ -324,6 +335,7 @@
 
     @Test
     public void setBackupServiceActive_forNonSystemUserAndCallerWithoutBackupPermission_throws() {
+        createBackupManagerServiceAndUnlockSystemUser();
         doThrow(new SecurityException())
                 .when(mContextMock)
                 .enforceCallingOrSelfPermission(eq(Manifest.permission.BACKUP), anyString());
@@ -337,6 +349,7 @@
 
     @Test
     public void setBackupServiceActive_forNonSystemUserAndCallerWithoutUserPermission_throws() {
+        createBackupManagerServiceAndUnlockSystemUser();
         doThrow(new SecurityException())
                 .when(mContextMock)
                 .enforceCallingOrSelfPermission(
@@ -351,9 +364,9 @@
 
     @Test
     public void setBackupServiceActive_backupDisabledGlobally_ignored() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sBackupDisabled = true;
-        BackupManagerServiceTestable service =
-                new BackupManagerServiceTestable(mContextMock, mUserServices);
+        BackupManagerServiceTestable service = new BackupManagerServiceTestable(mContextMock);
 
         service.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
 
@@ -362,6 +375,7 @@
 
     @Test
     public void setBackupServiceActive_alreadyActive_ignored() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
         assertTrue(mService.isBackupServiceActive(UserHandle.USER_SYSTEM));
 
@@ -371,6 +385,7 @@
 
     @Test
     public void setBackupServiceActive_systemUser_makeActive_deletesSuppressFile() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
 
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
@@ -380,6 +395,7 @@
 
     @Test
     public void setBackupServiceActive_systemUser_makeNonActive_createsSuppressFile() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
 
         assertTrue(getFakeSuppressFileForUser(UserHandle.USER_SYSTEM).exists());
@@ -387,6 +403,7 @@
 
     @Test
     public void setBackupServiceActive_systemUser_makeNonActive_stopsUserService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         assertTrue(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
 
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
@@ -396,7 +413,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isDefault_makeActive_createsService() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         simulateUserUnlocked(NON_SYSTEM_USER);
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
@@ -407,7 +424,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isDefault_makeActive_deletesSuppressFile() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         simulateUserUnlocked(NON_SYSTEM_USER);
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
@@ -418,7 +435,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isDefault_makeNonActive_createsSuppressFile() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
         assertTrue(getFakeSuppressFileForUser(NON_SYSTEM_USER).exists());
@@ -426,7 +443,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isDefault_makeNonActive_stopsUserService() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         simulateUserUnlocked(NON_SYSTEM_USER);
         assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
 
@@ -437,6 +454,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_createsService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         simulateUserUnlocked(NON_SYSTEM_USER);
 
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
@@ -446,6 +464,8 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_createActivatedFile() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
 
         assertTrue(getFakeActivatedFileForUser(NON_SYSTEM_USER).exists());
@@ -453,6 +473,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isNotDefault_makeNonActive_stopsUserService() {
+        createBackupManagerServiceAndUnlockSystemUser();
         simulateUserUnlocked(NON_SYSTEM_USER);
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
 
@@ -463,6 +484,7 @@
 
     @Test
     public void setBackupServiceActive_nonSystemUser_isNotDefault_makeActive_deleteActivatedFile() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
 
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
@@ -472,6 +494,7 @@
 
     @Test
     public void setBackupServiceActive_forOneNonSystemUser_doesNotActivateForAllNonSystemUsers() {
+        createBackupManagerServiceAndUnlockSystemUser();
         int otherUser = NON_SYSTEM_USER + 1;
         mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
 
@@ -482,6 +505,8 @@
 
     @Test
     public void setBackupServiceActive_forNonSystemUser_remembersActivated() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
 
         assertTrue(RandomAccessFileUtils.readBoolean(
@@ -490,6 +515,8 @@
 
     @Test
     public void setBackupServiceActiveFalse_forNonSystemUser_remembersActivated() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
         assertFalse(RandomAccessFileUtils.readBoolean(
@@ -498,6 +525,8 @@
 
     @Test
     public void setBackupServiceActiveTwice_forNonSystemUser_remembersLastActivated() {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
         mService.setBackupServiceActive(NON_SYSTEM_USER, false);
 
@@ -508,7 +537,7 @@
     @Test
     public void selectBackupTransportAsyncForUser_beforeUserUnlocked_notifiesBackupNotAllowed()
             throws Exception {
-        mUserServices.clear();
+        mService = new BackupManagerServiceTestable(mContextMock);
         CompletableFuture<Integer> future = new CompletableFuture<>();
         ISelectBackupTransportCallback listener =
                 new ISelectBackupTransportCallback.Stub() {
@@ -531,6 +560,8 @@
     @Test
     public void selectBackupTransportAsyncForUser_beforeUserUnlockedWithNullListener_doesNotThrow()
             throws Exception {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         mService.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, null);
 
         // No crash.
@@ -539,6 +570,8 @@
     @Test
     public void selectBackupTransportAsyncForUser_beforeUserUnlockedListenerThrowing_doesNotThrow()
             throws Exception {
+        createBackupManagerServiceAndUnlockSystemUser();
+
         ISelectBackupTransportCallback.Stub listener =
                 new ISelectBackupTransportCallback.Stub() {
                     @Override
@@ -558,6 +591,7 @@
 
     @Test
     public void dump_callerDoesNotHaveDumpPermission_ignored() {
+        createBackupManagerServiceAndUnlockSystemUser();
         when(mContextMock.checkCallingOrSelfPermission(
                 Manifest.permission.DUMP)).thenReturn(
                 PackageManager.PERMISSION_DENIED);
@@ -570,6 +604,7 @@
 
     @Test
     public void dump_callerDoesNotHavePackageUsageStatsPermission_ignored() {
+        createBackupManagerServiceAndUnlockSystemUser();
         when(mContextMock.checkCallingOrSelfPermission(
                 Manifest.permission.PACKAGE_USAGE_STATS)).thenReturn(
                 PackageManager.PERMISSION_DENIED);
@@ -586,6 +621,7 @@
      */
     @Test
     public void testDump_systemUserFirst() {
+        createBackupManagerServiceAndUnlockSystemUser();
         mService.setBackupServiceActive(NON_SYSTEM_USER, true);
         simulateUserUnlocked(NON_SYSTEM_USER);
         String[] args = new String[0];
@@ -602,6 +638,7 @@
 
     @Test
     public void testGetUserForAncestralSerialNumber_forSystemUser() {
+        createBackupManagerServiceAndUnlockSystemUser();
         simulateUserUnlocked(NON_SYSTEM_USER);
         when(mUserManagerMock.getProfileIds(UserHandle.getCallingUserId(), false))
                 .thenReturn(new int[]{UserHandle.USER_SYSTEM, NON_SYSTEM_USER});
@@ -614,10 +651,10 @@
 
     @Test
     public void testGetUserForAncestralSerialNumber_forNonSystemUser() {
-        setMockMainUserAndStartNewBackupManagerService(NON_SYSTEM_USER);
+        setMockMainUserAndCreateBackupManagerService(NON_SYSTEM_USER);
         simulateUserUnlocked(NON_SYSTEM_USER);
         when(mUserManagerMock.getProfileIds(UserHandle.getCallingUserId(), false))
-                .thenReturn(new int[]{UserHandle.USER_SYSTEM, NON_SYSTEM_USER});
+                .thenReturn(new int[] {UserHandle.USER_SYSTEM, NON_SYSTEM_USER});
         when(mNonSystemUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
 
         UserHandle user = mService.getUserForAncestralSerialNumber(11L);
@@ -627,9 +664,9 @@
 
     @Test
     public void testGetUserForAncestralSerialNumber_whenDisabled() {
+        createBackupManagerServiceAndUnlockSystemUser();
         BackupManagerServiceTestable.sBackupDisabled = true;
-        BackupManagerService backupManagerService =
-                new BackupManagerServiceTestable(mContextMock, mUserServices);
+        BackupManagerService backupManagerService = new BackupManagerServiceTestable(mContextMock);
         when(mSystemUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
 
         UserHandle user = backupManagerService.getUserForAncestralSerialNumber(11L);
@@ -637,18 +674,68 @@
         assertThat(user).isNull();
     }
 
+    @Test
+    public void onUserUnlocking_mainUserChanged_firstUnlockAfterReboot_updatesDefaultUser() {
+        // Create BMS *before* setting a main user to simulate the main user being created after
+        // BMS, which can happen for the first ever boot of a new device.
+        mService = new BackupManagerServiceTestable(mContextMock);
+        mServiceLifecycle = new BackupManagerService.Lifecycle(mContextMock, mService);
+        when(mUserManagerMock.getMainUser()).thenReturn(UserHandle.of(NON_SYSTEM_USER));
+        assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
+
+        simulateUserUnlocked(UserHandle.USER_SYSTEM);
+
+        assertTrue(mService.isBackupServiceActive(NON_SYSTEM_USER));
+    }
+
+    @Test
+    public void onUserUnlocking_mainUserChanged_firstUnlockAfterReboot_doesNotStartForSystemUser() {
+        // Create BMS *before* setting a main user to simulate the main user being created after
+        // BMS, which can happen for the first ever boot of a new device.
+        mService = new BackupManagerServiceTestable(mContextMock);
+        mServiceLifecycle = new BackupManagerService.Lifecycle(mContextMock, mService);
+        when(mUserManagerMock.getMainUser()).thenReturn(UserHandle.of(NON_SYSTEM_USER));
+        assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
+
+        simulateUserUnlocked(UserHandle.USER_SYSTEM);
+
+        assertFalse(mService.isUserReadyForBackup(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void onUserUnlocking_mainUserChanged_secondUnlockAfterReboot_doesNotUpdateDefaultUser() {
+        // Create BMS *before* setting a main user to simulate the main user being created after
+        // BMS, which can happen for the first ever boot of a new device.
+        createBackupManagerServiceAndUnlockSystemUser();
+        when(mUserManagerMock.getMainUser()).thenReturn(UserHandle.of(NON_SYSTEM_USER));
+        assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
+
+        simulateUserUnlocked(NON_SYSTEM_USER);
+
+        assertFalse(mService.isBackupServiceActive(NON_SYSTEM_USER));
+    }
+
+    private void createBackupManagerServiceAndUnlockSystemUser() {
+        mService = new BackupManagerServiceTestable(mContextMock);
+        mServiceLifecycle = new BackupManagerService.Lifecycle(mContextMock, mService);
+        simulateUserUnlocked(UserHandle.USER_SYSTEM);
+    }
+
     /**
      * The 'default' user is set in the constructor of {@link BackupManagerService} so we need to
      * start a new service after mocking the 'main' user.
      */
-    private void setMockMainUserAndStartNewBackupManagerService(int userId) {
+    private void setMockMainUserAndCreateBackupManagerService(int userId) {
         when(mUserManagerMock.getMainUser()).thenReturn(UserHandle.of(userId));
-        mService = new BackupManagerServiceTestable(mContextMock, mUserServices);
+        mService = new BackupManagerServiceTestable(mContextMock);
+        mServiceLifecycle = new BackupManagerService.Lifecycle(mContextMock, mService);
     }
 
     private void simulateUserUnlocked(int userId) {
         ConditionVariable unlocked = new ConditionVariable(false);
-        mService.onUnlockUser(userId);
+        mServiceLifecycle.onUserUnlocking(
+                new SystemService.TargetUser(
+                        new UserInfo(userId, /* name= */ "test", /* flags= */ 0)));
         mService.getBackupHandler().post(unlocked::open);
         unlocked.block();
         when(mUserManagerMock.isUserUnlocked(userId)).thenReturn(true);
@@ -672,9 +759,8 @@
         static int sCallingUid = -1;
         static UserManager sUserManagerMock = null;
 
-        BackupManagerServiceTestable(
-                Context context, SparseArray<UserBackupManagerService> userServices) {
-            super(context, userServices);
+        BackupManagerServiceTestable(Context context) {
+            super(context);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index 2d036fe..88f0c93 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -26,6 +26,7 @@
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -114,6 +115,7 @@
             null);
     private MagnificationScaleProvider mScaleProvider;
     private MockContentResolver mResolver;
+    private final MagnificationThumbnail mMockThumbnail = mock(MagnificationThumbnail.class);
 
     private final ArgumentCaptor<MagnificationConfig> mConfigCaptor = ArgumentCaptor.forClass(
             MagnificationConfig.class);
@@ -151,8 +153,14 @@
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
 
         mScaleProvider = new MagnificationScaleProvider(mMockContext);
-        mFullScreenMagnificationController = new FullScreenMagnificationController(
-                mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider);
+
+        mFullScreenMagnificationController =
+                new FullScreenMagnificationController(
+                        mMockControllerCtx,
+                        new Object(),
+                        mRequestObserver,
+                        mScaleProvider,
+                        () -> mMockThumbnail);
     }
 
     @After
@@ -191,6 +199,8 @@
         verify(mMockWindowManager).setMagnificationCallbacks(eq(DISPLAY_1), eq(null));
         assertFalse(mFullScreenMagnificationController.isRegistered(DISPLAY_0));
         assertFalse(mFullScreenMagnificationController.isRegistered(DISPLAY_1));
+
+        verify(mMockThumbnail, times(2)).hideThumbNail();
     }
 
     @Test
@@ -527,6 +537,8 @@
         verify(mRequestObserver).onFullScreenMagnificationChanged(eq(displayId), eq(OTHER_REGION),
                 mConfigCaptor.capture());
         assertConfigEquals(config, mConfigCaptor.getValue());
+
+        verify(mMockThumbnail).setThumbNailBounds(any(), anyFloat(), anyFloat(), anyFloat());
     }
 
     @Test
@@ -849,6 +861,9 @@
         mMessageCapturingHandler.sendAllMessages();
         assertThat(getCurrentMagnificationSpec(displayId), closeTo(startSpec));
         verifyNoMoreInteractions(mMockWindowManager);
+
+        verify(mMockThumbnail)
+                .updateThumbNail(eq(scale), eq(startCenter.x), eq(startCenter.y));
     }
 
     @Test
@@ -1240,6 +1255,7 @@
 
     private void resetMockWindowManager() {
         Mockito.reset(mMockWindowManager);
+        Mockito.reset(mMockThumbnail);
         initMockWindowManager();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index a095760..51d3bae 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -163,9 +163,13 @@
         when(mockController.newValueAnimator()).thenReturn(new ValueAnimator());
         when(mockController.getAnimationDuration()).thenReturn(1000L);
         when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
-        mFullScreenMagnificationController = new FullScreenMagnificationController(mockController,
-                new Object(), mMagnificationInfoChangedCallback,
-                new MagnificationScaleProvider(mContext)) {
+        mFullScreenMagnificationController = new FullScreenMagnificationController(
+                mockController,
+                new Object(),
+                mMagnificationInfoChangedCallback,
+                new MagnificationScaleProvider(mContext),
+                () -> null
+        ) {
             @Override
             public boolean magnificationRegionContains(int displayId, float x, float y) {
                 return true;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index b4a16c2..bbcb376 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -194,8 +194,12 @@
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternal);
 
         mScreenMagnificationController = spy(new FullScreenMagnificationController(
-                mControllerCtx, new Object(),
-                mScreenMagnificationInfoChangedCallbackDelegate, mScaleProvider));
+                mControllerCtx,
+                new Object(),
+                mScreenMagnificationInfoChangedCallbackDelegate,
+                mScaleProvider,
+                () -> null
+        ));
         mScreenMagnificationController.register(TEST_DISPLAY);
 
         mWindowMagnificationManager = spy(new WindowMagnificationManager(mContext, globalLock,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java
new file mode 100644
index 0000000..60c8148
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.server.accessibility.magnification;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Rect;
+import android.os.Handler;
+import android.platform.test.annotations.LargeTest;
+import android.testing.TestableContext;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class MagnificationThumbnailTest {
+    @Rule
+    public final TestableContext mContext = new TestableContext(
+            InstrumentationRegistry.getInstrumentation().getContext());
+
+    private final WindowManager mMockWindowManager = mock(WindowManager.class);
+    private final Handler mHandler = mContext.getMainThreadHandler();
+
+    private MagnificationThumbnail mMagnificationThumbnail;
+
+    @Before
+    public void setUp() {
+        var metrics = new WindowMetrics(new Rect(), WindowInsets.CONSUMED, 1f);
+        when(mMockWindowManager.getCurrentWindowMetrics()).thenReturn(metrics);
+        mMagnificationThumbnail = new MagnificationThumbnail(
+                mContext,
+                mMockWindowManager,
+                mHandler
+        );
+    }
+
+    @Test
+    public void updateThumbnailShows() {
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2.2f,
+                /* centerX= */ 15,
+                /* centerY= */ 50
+        ));
+        idle();
+
+        verify(mMockWindowManager).addView(eq(mMagnificationThumbnail.mThumbnailLayout), any());
+        assertThat(mMagnificationThumbnail.mThumbnailLayout.getAlpha()).isGreaterThan(0.5f);
+    }
+
+    @Test
+    public void updateThumbnailLingersThenHidesAfterTimeout() throws InterruptedException {
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        // Wait for the linger delay then fade out animation
+        Thread.sleep(2000L);
+        idle();
+
+        verify(mMockWindowManager).removeView(eq(mMagnificationThumbnail.mThumbnailLayout));
+        assertThat(mMagnificationThumbnail.mThumbnailLayout.getAlpha()).isLessThan(0.1f);
+    }
+
+    @Test
+    public void hideThumbnailRemoves() throws InterruptedException {
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail());
+        idle();
+
+        // Wait for the fade out animation
+        Thread.sleep(1100L);
+
+        verify(mMockWindowManager).removeView(eq(mMagnificationThumbnail.mThumbnailLayout));
+        assertThat(mMagnificationThumbnail.mThumbnailLayout.getAlpha()).isLessThan(0.1f);
+    }
+
+    @Test
+    public void hideShowHideShowHideRemoves() throws InterruptedException {
+        runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail());
+        idle();
+
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        // Wait for the fade in animation
+        Thread.sleep(200L);
+
+        runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail());
+        idle();
+
+        runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail(
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail());
+        idle();
+
+
+        // Wait for the fade out animation
+        Thread.sleep(1100L);
+
+        verify(mMockWindowManager).removeView(eq(mMagnificationThumbnail.mThumbnailLayout));
+        assertThat(mMagnificationThumbnail.mThumbnailLayout.getAlpha()).isLessThan(0.1f);
+    }
+
+    @Test
+    public void hideWithoutShowDoesNothing() throws InterruptedException {
+        runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail());
+        idle();
+
+        // Wait for the fade out animation
+        Thread.sleep(1100L);
+
+        verify(mMockWindowManager, never())
+                .addView(eq(mMagnificationThumbnail.mThumbnailLayout), any());
+        verify(mMockWindowManager, never())
+                .removeView(eq(mMagnificationThumbnail.mThumbnailLayout));
+    }
+
+    @Test
+    public void whenHidden_setBoundsDoesNotShow() throws InterruptedException {
+        runOnMainSync(() -> mMagnificationThumbnail.setThumbNailBounds(
+                new Rect(),
+                /* scale=   */ 2f,
+                /* centerX= */ 5,
+                /* centerY= */ 10
+        ));
+        idle();
+
+        // Wait for the fade in/out animation
+        Thread.sleep(1100L);
+
+        verify(mMockWindowManager, never())
+                .addView(eq(mMagnificationThumbnail.mThumbnailLayout), any());
+        verify(mMockWindowManager, never())
+                .removeView(eq(mMagnificationThumbnail.mThumbnailLayout));
+    }
+
+    private static void idle() {
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
+    private static void runOnMainSync(Runnable runnable) {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 3d6e1af..48025ed 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2775,8 +2775,7 @@
         // Can't set message for admin in another uid.
         {
             mContext.binder.callingUid = DpmMockContext.CALLER_UID + 1;
-            assertExpectException(SecurityException.class,
-                    /* messageRegex= */ "is not owned by uid",
+            assertThrows(SecurityException.class,
                     () -> dpm.setShortSupportMessage(admin1, "Some text"));
             mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         }
diff --git a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
index 454d3f3..9ce80c4 100644
--- a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
@@ -19,6 +19,9 @@
 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
 import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION;
 import static android.os.PowerManager.LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN;
+import static android.os.PowerManager.LowPowerStandbyPortDescription.MATCH_PORT_LOCAL;
+import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_TCP;
+import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_UDP;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -47,9 +50,11 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.IPowerManager;
 import android.os.PowerManager;
 import android.os.PowerManager.LowPowerStandbyPolicy;
+import android.os.PowerManager.LowPowerStandbyPortDescription;
 import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -98,6 +103,10 @@
     private static final int USER_ID_2 = 10;
     private static final LowPowerStandbyPolicy EMPTY_POLICY = new LowPowerStandbyPolicy(
             "Test policy", Collections.emptySet(), 0, Collections.emptySet());
+    private static final LowPowerStandbyPortDescription PORT_DESC_1 =
+            new LowPowerStandbyPortDescription(PROTOCOL_UDP, MATCH_PORT_LOCAL, 5353);
+    private static final LowPowerStandbyPortDescription PORT_DESC_2 =
+            new LowPowerStandbyPortDescription(PROTOCOL_TCP, MATCH_PORT_LOCAL, 8008);
 
     private LowPowerStandbyController mController;
     private BroadcastInterceptingContext mContextSpy;
@@ -140,6 +149,7 @@
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
         when(mDeviceConfigWrapperMock.enableCustomPolicy()).thenReturn(true);
+        when(mDeviceConfigWrapperMock.enableStandbyPorts()).thenReturn(true);
         mResourcesSpy = spy(mContextSpy.getResources());
         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
         when(mResourcesSpy.getBoolean(
@@ -703,6 +713,81 @@
         verify(mPowerManagerInternalMock).setLowPowerStandbyAllowlist(new int[0]);
     }
 
+    @Test
+    public void testStandbyPorts_broadcastChangedIfPackageIsExempt() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(true);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG1));
+
+        Binder token = new Binder();
+        BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent(
+                PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED);
+        mController.acquireStandbyPorts(token, TEST_PKG1_APP_ID, List.of(PORT_DESC_1));
+        mTestLooper.dispatchAll();
+        assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull();
+
+        futureIntent = mContextSpy.nextBroadcastIntent(
+                PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED);
+        mController.releaseStandbyPorts(token);
+        mTestLooper.dispatchAll();
+        assertThat(futureIntent.get(1, TimeUnit.SECONDS)).isNotNull();
+    }
+
+    @Test
+    public void testStandbyPorts_noBroadcastChangedIfPackageIsNotExempt() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(true);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG1));
+
+        BroadcastInterceptingContext.FutureIntent futureIntent = mContextSpy.nextBroadcastIntent(
+                PowerManager.ACTION_LOW_POWER_STANDBY_PORTS_CHANGED);
+        mController.acquireStandbyPorts(new Binder(), TEST_PKG2_APP_ID, List.of(PORT_DESC_1));
+        mTestLooper.dispatchAll();
+        futureIntent.assertNotReceived();
+    }
+
+    @Test
+    public void testActiveStandbyPorts_emptyIfDisabled() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(false);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG1));
+
+        mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1));
+        assertThat(mController.getActiveStandbyPorts()).isEmpty();
+    }
+
+    @Test
+    public void testActiveStandbyPorts_emptyIfPackageNotExempt() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(true);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG2));
+
+        mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1));
+        assertThat(mController.getActiveStandbyPorts()).isEmpty();
+    }
+
+    @Test
+    public void testActiveStandbyPorts_activeIfPackageExempt() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(true);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG1));
+
+        mController.acquireStandbyPorts(new Binder(), TEST_PKG1_APP_ID, List.of(PORT_DESC_1));
+        mController.acquireStandbyPorts(new Binder(), TEST_PKG2_APP_ID, List.of(PORT_DESC_2));
+        assertThat(mController.getActiveStandbyPorts()).containsExactly(PORT_DESC_1);
+    }
+
+    @Test
+    public void testActiveStandbyPorts_removedAfterRelease() throws Exception {
+        mController.systemReady();
+        mController.setEnabled(true);
+        mController.setPolicy(policyWithExemptPackages(TEST_PKG1));
+        Binder token = new Binder();
+        mController.acquireStandbyPorts(token, TEST_PKG1_APP_ID, List.of(PORT_DESC_1));
+        mController.releaseStandbyPorts(token);
+        assertThat(mController.getActiveStandbyPorts()).isEmpty();
+    }
+
     private void setInteractive() throws Exception {
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
         mContextSpy.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
index 57f9f18..13c011a 100644
--- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.power;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -30,6 +32,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.hardware.thermal.TemperatureThreshold;
 import android.hardware.thermal.ThrottlingSeverity;
 import android.os.CoolingDevice;
@@ -55,7 +58,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -114,6 +119,7 @@
             skinThreshold.type = Temperature.TYPE_SKIN;
             skinThreshold.name = "skin1";
             skinThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
+            skinThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
             for (int i = 0; i < skinThreshold.hotThrottlingThresholds.length; ++i) {
                 // Sets NONE to 25.0f, SEVERE to 40.0f, and SHUTDOWN to 55.0f
                 skinThreshold.hotThrottlingThresholds[i] = 25.0f + 5.0f * i;
@@ -124,6 +130,7 @@
             cpuThreshold.type = Temperature.TYPE_CPU;
             cpuThreshold.name = "cpu";
             cpuThreshold.hotThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
+            cpuThreshold.coldThrottlingThresholds = new float[7 /*ThrottlingSeverity#len*/];
             for (int i = 0; i < cpuThreshold.hotThrottlingThresholds.length; ++i) {
                 if (i == ThrottlingSeverity.SEVERE) {
                     cpuThreshold.hotThrottlingThresholds[i] = 95.0f;
@@ -189,7 +196,8 @@
 
         @Override
         protected void dump(PrintWriter pw, String prefix) {
-            return;
+            pw.print(prefix);
+            pw.println("ThermalHAL AIDL 1  connected: yes");
         }
     }
 
@@ -496,4 +504,51 @@
             return watcher.mSamples.isEmpty();
         }
     }
+
+    @Test
+    public void testDump() {
+        when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+        final StringWriter out = new StringWriter();
+        PrintWriter pw = new PrintWriter(out);
+        mService.dumpInternal(new FileDescriptor(), pw, null);
+        final String dumpStr = out.toString();
+        assertThat(dumpStr).contains("IsStatusOverride: false");
+        assertThat(dumpStr).contains(
+                "ThermalEventListeners:\n"
+                        + "\tcallbacks: 2\n"
+                        + "\tkilled: false\n"
+                        + "\tbroadcasts count: -1");
+        assertThat(dumpStr).contains(
+                "ThermalStatusListeners:\n"
+                        + "\tcallbacks: 2\n"
+                        + "\tkilled: false\n"
+                        + "\tbroadcasts count: -1");
+        assertThat(dumpStr).contains("Thermal Status: 0");
+        assertThat(dumpStr).contains(
+                "Cached temperatures:\n"
+                + "\tTemperature{mValue=0.0, mType=4, mName=usbport, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=2, mName=batt, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=3, mName=skin1, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=3, mName=skin2, mStatus=0}"
+        );
+        assertThat(dumpStr).contains("HAL Ready: true\n"
+                + "HAL connection:\n"
+                + "\tThermalHAL AIDL 1  connected: yes");
+        assertThat(dumpStr).contains("Current temperatures from HAL:\n"
+                + "\tTemperature{mValue=0.0, mType=3, mName=skin1, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=3, mName=skin2, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=2, mName=batt, mStatus=0}\n"
+                + "\tTemperature{mValue=0.0, mType=4, mName=usbport, mStatus=0}\n");
+        assertThat(dumpStr).contains("Current cooling devices from HAL:\n"
+                + "\tCoolingDevice{mValue=0, mType=1, mName=cpu}\n"
+                + "\tCoolingDevice{mValue=0, mType=1, mName=gpu}\n");
+        assertThat(dumpStr).contains("Temperature static thresholds from HAL:\n"
+                + "\tTemperatureThreshold{mType=3, mName=skin1, mHotThrottlingThresholds=[25.0, "
+                + "30.0, 35.0, 40.0, 45.0, 50.0, 55.0], mColdThrottlingThresholds=[0.0, 0.0, 0.0,"
+                + " 0.0, 0.0, 0.0, 0.0]}\n"
+                + "\tTemperatureThreshold{mType=0, mName=cpu, mHotThrottlingThresholds=[NaN, NaN,"
+                + " NaN, 95.0, NaN, NaN, NaN], mColdThrottlingThresholds=[0.0, 0.0, 0.0, 0.0, 0"
+                + ".0, 0.0, 0.0]}");
+    }
 }
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 687696a..96ec2b8 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -48,6 +48,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_MUTABLE;
 import static android.app.PendingIntent.FLAG_ONE_SHOT;
@@ -73,6 +74,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
 import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.ALLOW_DISMISS_ONGOING;
+import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE;
+import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -82,6 +85,7 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNotSame;
 import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
@@ -111,6 +115,7 @@
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 
+import android.Manifest;
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -170,6 +175,8 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionCheckerManager;
+import android.permission.PermissionManager;
 import android.provider.DeviceConfig;
 import android.provider.MediaStore;
 import android.provider.Settings;
@@ -203,6 +210,7 @@
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag;
 import com.android.internal.config.sysui.TestableFlagResolver;
 import com.android.internal.logging.InstanceIdSequence;
 import com.android.internal.logging.InstanceIdSequenceFake;
@@ -320,6 +328,8 @@
     @Mock
     private NotificationManager mMockNm;
     @Mock
+    private PermissionManager mPermissionManager;
+    @Mock
     private DevicePolicyManagerInternal mDevicePolicyManager;
 
     @Mock
@@ -527,7 +537,7 @@
                 mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager,
                 mock(TelephonyManager.class),
                 mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
-                mTelecomManager, mLogger, mTestFlagResolver);
+                mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager);
         // Return first true for RoleObserver main-thread check
         when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
@@ -604,6 +614,9 @@
                 PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID));
         clearInvocations(mRankingHandler);
         when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
+
+        mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false);
+        mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false);
     }
 
     @After
@@ -10111,6 +10124,84 @@
         verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class));
     }
 
+    private void verifyStickyHun(Flag flag, int permissionState, boolean isSticky)
+            throws Exception {
+
+        mTestFlagResolver.setFlagOverride(flag, true);
+
+        when(mPermissionManager.checkPermissionForDataDelivery(
+                eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any()))
+                .thenReturn(permissionState);
+
+        Notification n = new Notification.Builder(mContext, "test")
+                .setFullScreenIntent(mock(PendingIntent.class), true)
+                .build();
+
+        mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+
+        final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
+
+        if (isSticky) {
+            assertNotSame(0, stickyFlag);
+        } else {
+            assertSame(0, stickyFlag);
+        }
+    }
+
+    @Test
+    public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+                /* isSticky= */ true);
+    }
+
+    @Test
+    public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+                /* isSticky= */ true);
+    }
+
+    @Test
+    public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+                /* isSticky= */ false);
+    }
+
+    @Test
+    public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+                /* isSticky= */ true);
+    }
+
+    @Test
+    public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+                /* isSticky= */ true);
+    }
+
+    @Test
+    public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun()
+            throws Exception {
+
+        verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
+                /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+                /* isSticky= */ true);
+    }
+
     @Test
     public void fixSystemNotification_withOnGoingFlag_shouldBeNonDismissible()
             throws Exception {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index a3977ba..b1a9f08 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -51,6 +51,7 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.permission.PermissionManager;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -169,7 +170,8 @@
                     mock(ActivityManagerInternal.class),
                     mock(MultiRateLimiter.class), mock(PermissionHelper.class),
                     mock(UsageStatsManagerInternal.class), mock (TelecomManager.class),
-                    mock(NotificationChannelLogger.class), new TestableFlagResolver());
+                    mock(NotificationChannelLogger.class), new TestableFlagResolver(),
+                    mock(PermissionManager.class));
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 7b19e1f..0a80abe 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.app.Activity.RESULT_CANCELED;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -43,6 +44,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Process.SYSTEM_UID;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
@@ -50,6 +52,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -77,6 +80,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.notNull;
@@ -111,6 +115,8 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.DeviceConfigStateHelper;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.am.PendingIntentRecord;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
 import com.android.server.wm.utils.MockTracker;
@@ -120,6 +126,8 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -880,6 +888,64 @@
                 false, false, false, false, false, false, false);
     }
 
+    /**
+     * This test ensures proper logging for BAL_ALLOW_PERMISSION.
+     */
+    @Test
+    public void testBackgroundActivityStartsAllowed_logging() {
+        doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
+        MockitoSession mockingSession = mockitoSession()
+                .mockStatic(ActivityTaskManagerService.class)
+                .mockStatic(FrameworkStatsLog.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+        doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
+                eq(START_ACTIVITIES_FROM_BACKGROUND),
+                anyInt(), anyInt()));
+        runAndVerifyBackgroundActivityStartsSubtest(
+                "allowed_notAborted", false,
+                UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
+                UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP,
+                false, true, false, false, false, false, false);
+        verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+                "",  // activity name
+                BackgroundActivityStartController.BAL_ALLOW_PERMISSION,
+                UNIMPORTANT_UID,
+                UNIMPORTANT_UID2));
+        mockingSession.finishMocking();
+    }
+
+    /**
+     * This test ensures proper logging for BAL_ALLOW_PENDING_INTENT.
+     */
+    @Test
+    public void testBackgroundActivityStartsAllowed_loggingPendingIntentAllowed() {
+        doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
+        MockitoSession mockingSession = mockitoSession()
+                .mockStatic(ActivityTaskManagerService.class)
+                .mockStatic(FrameworkStatsLog.class)
+                .mockStatic(PendingIntentRecord.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+        doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
+                eq(START_ACTIVITIES_FROM_BACKGROUND),
+                anyInt(), anyInt()));
+        doReturn(BackgroundStartPrivileges.allowBackgroundActivityStarts(null)).when(
+                () -> PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
+                anyObject(), anyInt()));
+        runAndVerifyBackgroundActivityStartsSubtest(
+                "allowed_notAborted", false,
+                UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
+                Process.SYSTEM_UID, true, PROCESS_STATE_BOUND_TOP,
+                false, true, false, false, false, false, false);
+        verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
+                DEFAULT_COMPONENT_PACKAGE_NAME + "/" + DEFAULT_COMPONENT_PACKAGE_NAME,
+                BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT,
+                UNIMPORTANT_UID,
+                Process.SYSTEM_UID));
+        mockingSession.finishMocking();
+    }
+
     private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
             int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
             int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index d8037f6..6f633d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -497,6 +497,7 @@
         doReturn(insets).when(mainWindow).getInsetsState();
         doReturn(attrs).when(mainWindow).getAttrs();
         doReturn(true).when(mainWindow).isDrawn();
+        doReturn(true).when(mainWindow).isOnScreen();
         doReturn(false).when(mainWindow).isLetterboxedForDisplayCutout();
         doReturn(true).when(mainWindow).areAppWindowBoundsLetterboxed();
         doReturn(true).when(mLetterboxConfiguration).isLetterboxActivityCornersRounded();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 3e555a3..c9f758c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -516,7 +516,7 @@
 
         spyOn(mActivity.mLetterboxUiController);
         doReturn(true).when(mActivity.mLetterboxUiController)
-                .isSurfaceReadyAndVisible(any());
+                .isSurfaceVisible(any());
 
         assertTrue(mActivity.mLetterboxUiController.shouldShowLetterboxUi(
                 mActivity.findMainWindow()));
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 819b0b2..66711df 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -18038,6 +18038,87 @@
     public static final int CELL_BROADCAST_RESULT_FAIL_ACTIVATION = 3;
 
     /**
+     * Callback mode type
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"EMERGENCY_CALLBACK_MODE_"}, value = {
+            EMERGENCY_CALLBACK_MODE_CALL,
+            EMERGENCY_CALLBACK_MODE_SMS})
+    public @interface EmergencyCallbackModeType {}
+
+    /**
+     * The callback mode is due to emergency call.
+     * @hide
+     */
+    public static final int EMERGENCY_CALLBACK_MODE_CALL = 1;
+
+    /**
+     * The callback mode is due to emergency SMS.
+     * @hide
+     */
+    public static final int EMERGENCY_CALLBACK_MODE_SMS = 2;
+
+    /**
+     * The reason for changing callback mode.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"STOP_REASON_"},
+            value = {
+                    STOP_REASON_UNKNOWN,
+                    STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED,
+                    STOP_REASON_NORMAL_SMS_SENT,
+                    STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED,
+                    STOP_REASON_EMERGENCY_SMS_SENT,
+                    STOP_REASON_TIMER_EXPIRED,
+                    STOP_REASON_USER_ACTION,
+            })
+    public @interface EmergencyCallbackModeStopReason {}
+
+    /**
+     * unknown reason.
+     * @hide
+     */
+    public static final int STOP_REASON_UNKNOWN = 0;
+
+    /**
+     * The call back mode is exited due to a new normal call is originated.
+     * @hide
+     */
+    public static final int STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED = 1;
+
+    /**
+     * The call back mode is exited due to a new normal SMS is originated.
+     * @hide
+     */
+    public static final int STOP_REASON_NORMAL_SMS_SENT = 2;
+
+    /**
+     * The call back mode is exited due to a new emergency call is originated.
+     * @hide
+     */
+    public static final int STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED = 3;
+
+    /**
+     * The call back mode is exited due to a new emergency SMS is originated.
+     * @hide
+     */
+    public static final int STOP_REASON_EMERGENCY_SMS_SENT = 4;
+
+    /**
+     * The call back mode is exited due to timer expiry.
+     * @hide
+     */
+    public static final int STOP_REASON_TIMER_EXPIRED = 5;
+
+    /**
+     * The call back mode is exited due to user action.
+     * @hide
+     */
+    public static final int STOP_REASON_USER_ACTION = 6;
+
+    /**
      * Set reception of cell broadcast messages with the list of the given ranges
      *
      * <p>The ranges set previously will be overridden by the new one. Empty list
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index ead49f0..e0c31ed 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -18,7 +18,6 @@
 
 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
 import android.telephony.satellite.stub.ISatelliteListener;
-import android.telephony.satellite.stub.ISatelliteModemStateConsumer;
 import android.telephony.satellite.stub.SatelliteDatagram;
 
 import com.android.internal.telephony.IBooleanConsumer;
@@ -36,6 +35,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -54,6 +54,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -64,15 +65,16 @@
     void setSatelliteListeningEnabled(in boolean enable, in IIntegerConsumer errorCallback);
 
     /**
-     * Enable or disable the satellite modem. If the satellite modem is enabled, this will also
-     * disable the cellular modem, and if the satellite modem is disabled, this will also re-enable
-     * the cellular modem.
+     * Request to enable or disable the satellite modem. If the satellite modem is enabled,
+     * this will also disable the cellular modem, and if the satellite modem is disabled,
+     * this will also re-enable the cellular modem.
      *
      * @param enable True to enable the satellite modem and false to disable.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -80,17 +82,19 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void setSatelliteEnabled(in boolean enabled, in IIntegerConsumer errorCallback);
+    void requestSatelliteEnabled(in boolean enabled, in IIntegerConsumer errorCallback);
 
     /**
      * Request to get whether the satellite modem is enabled.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite modem is enabled.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -104,11 +108,13 @@
      * Request to get whether the satellite service is supported on the device.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite service is supported on the device.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -123,11 +129,13 @@
      * Request to get the SatelliteCapabilities of the satellite service.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the SatelliteCapabilities of the satellite service.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -147,6 +155,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -164,6 +173,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -177,11 +187,13 @@
      * Request to get the maximum number of characters per MO text message on satellite.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the maximum number of characters per MO text message on satellite.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -203,6 +215,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -225,6 +238,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -240,13 +254,14 @@
     /**
      * Request to get whether this device is provisioned with a satellite provider.
      *
-     * @param token The token of the device/subscription to be deprovisioned.
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether this device is provisioned with a satellite provider.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -254,7 +269,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestIsSatelliteProvisioned(in String token, in IIntegerConsumer errorCallback,
+    void requestIsSatelliteProvisioned(in IIntegerConsumer errorCallback,
             in IBooleanConsumer callback);
 
     /**
@@ -266,6 +281,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -291,6 +307,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -313,11 +330,13 @@
      * ISatelliteListener#onSatelliteModemStateChanged.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the current satellite modem state.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -326,17 +345,19 @@
      *   SatelliteError:NO_RESOURCES
      */
     void requestSatelliteModemState(in IIntegerConsumer errorCallback,
-            in ISatelliteModemStateConsumer callback);
+            in IIntegerConsumer callback);
 
     /**
      * Request to get whether satellite communication is allowed for the current location.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether satellite communication is allowed for the current location.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -353,11 +374,13 @@
      * This will return 0 if the satellite is currently visible.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the time after which the satellite will be visible.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl
index 4514a71..6a110a9 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteError.aidl
@@ -32,60 +32,60 @@
     /**
      * Error received from the satellite server.
      */
-    SATELLITE_SERVER_ERROR = 2,
+    SERVER_ERROR = 2,
     /**
      * Error received from the vendor service. This generic error code should be used
      * only when the error cannot be mapped to other specific service error codes.
      */
-    SATELLITE_SERVICE_ERROR = 3,
+    SERVICE_ERROR = 3,
     /**
      * Error received from satellite modem. This generic error code should be used only when
      * the error cannot be mapped to other specific modem error codes.
      */
-    SATELLITE_MODEM_ERROR = 4,
+    MODEM_ERROR = 4,
     /**
      * Error received from the satellite network. This generic error code should be used only when
      * the error cannot be mapped to other specific network error codes.
      */
-    SATELLITE_NETWORK_ERROR = 5,
+    NETWORK_ERROR = 5,
     /**
      * Telephony is not in a valid state to receive requests from clients.
      */
-    SATELLITE_INVALID_TELEPHONY_STATE = 6,
+    INVALID_TELEPHONY_STATE = 6,
     /**
      * Satellite modem is not in a valid state to receive requests from clients.
      */
-    SATELLITE_INVALID_MODEM_STATE = 7,
+    INVALID_MODEM_STATE = 7,
     /**
      * Either vendor service, or modem, or Telephony framework has received a request with
      * invalid arguments from its clients.
      */
-    SATELLITE_INVALID_ARGUMENTS = 8,
+    INVALID_ARGUMENTS = 8,
     /**
      * Telephony framework failed to send a request or receive a response from the vendor service
      * or satellite modem due to internal error.
      */
-    SATELLITE_REQUEST_FAILED = 9,
+    REQUEST_FAILED = 9,
     /**
      * Radio did not start or is resetting.
      */
-    SATELLITE_RADIO_NOT_AVAILABLE = 10,
+    RADIO_NOT_AVAILABLE = 10,
     /**
      * The request is not supported by either the satellite modem or the network.
      */
-    SATELLITE_REQUEST_NOT_SUPPORTED = 11,
+    REQUEST_NOT_SUPPORTED = 11,
     /**
      * Satellite modem or network has no resources available to handle requests from clients.
      */
-    SATELLITE_NO_RESOURCES = 12,
+    NO_RESOURCES = 12,
     /**
      * Satellite service is not provisioned yet.
      */
-    SATELLITE_SERVICE_NOT_PROVISIONED = 13,
+    SERVICE_NOT_PROVISIONED = 13,
     /**
      * Satellite service provision is already in progress.
      */
-    SATELLITE_SERVICE_PROVISION_IN_PROGRESS = 14,
+    SERVICE_PROVISION_IN_PROGRESS = 14,
     /**
      * The ongoing request was aborted by either the satellite modem or the network.
      */
@@ -98,7 +98,7 @@
      * Satellite modem timeout to receive ACK or response from the satellite network after
      * sending a request to the network.
      */
-    SATELLITE_NETWORK_TIMEOUT = 17,
+    NETWORK_TIMEOUT = 17,
     /**
      * Satellite network is not reachable from the modem.
      */
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index f9c2ea3..4140939 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -130,11 +130,11 @@
         }
 
         @Override
-        public void setSatelliteEnabled(boolean enable, IIntegerConsumer errorCallback)
+        public void requestSatelliteEnabled(boolean enable, IIntegerConsumer errorCallback)
                 throws RemoteException {
             executeMethodAsync(
-                    () -> SatelliteImplBase.this.setSatelliteEnabled(enable, errorCallback),
-                    "setSatelliteEnabled");
+                    () -> SatelliteImplBase.this.requestSatelliteEnabled(enable, errorCallback),
+                    "requestSatelliteEnabled");
         }
 
         @Override
@@ -206,11 +206,11 @@
         }
 
         @Override
-        public void requestIsSatelliteProvisioned(String token, IIntegerConsumer errorCallback,
+        public void requestIsSatelliteProvisioned(IIntegerConsumer errorCallback,
                 IBooleanConsumer callback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .requestIsSatelliteProvisioned(token, errorCallback, callback),
+                            .requestIsSatelliteProvisioned(errorCallback, callback),
                     "requestIsSatelliteProvisioned");
         }
 
@@ -233,7 +233,7 @@
 
         @Override
         public void requestSatelliteModemState(IIntegerConsumer errorCallback,
-                ISatelliteModemStateConsumer callback) throws RemoteException {
+                IIntegerConsumer callback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
                             .requestSatelliteModemState(errorCallback, callback),
@@ -256,7 +256,7 @@
                 IIntegerConsumer callback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .requestTimeForNextSatelliteVisibility(errorCallback, errorCallback),
+                            .requestTimeForNextSatelliteVisibility(errorCallback, callback),
                     "requestTimeForNextSatelliteVisibility");
         }
 
@@ -282,6 +282,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -303,6 +304,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -316,15 +318,16 @@
     }
 
     /**
-     * Enable or disable the satellite modem. If the satellite modem is enabled, this will also
-     * disable the cellular modem, and if the satellite modem is disabled, this will also re-enable
-     * the cellular modem.
+     * Request to enable or disable the satellite modem. If the satellite modem is enabled,
+     * this will also disable the cellular modem, and if the satellite modem is disabled,
+     * this will also re-enable the cellular modem.
      *
      * @param enable True to enable the satellite modem and false to disable.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -332,7 +335,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void setSatelliteEnabled(boolean enable, @NonNull IIntegerConsumer errorCallback) {
+    public void requestSatelliteEnabled(boolean enable, @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
 
@@ -340,11 +343,13 @@
      * Request to get whether the satellite modem is enabled.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite modem is enabled.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -361,11 +366,13 @@
      * Request to get whether the satellite service is supported on the device.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether the satellite service is supported on the device.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -382,11 +389,13 @@
      * Request to get the SatelliteCapabilities of the satellite service.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the SatelliteCapabilities of the satellite service.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -408,6 +417,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -427,6 +437,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -442,11 +453,13 @@
      * Request to get the maximum number of characters per MO text message on satellite.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the maximum number of characters per MO text message on satellite.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -470,6 +483,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -495,6 +509,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -513,13 +528,14 @@
     /**
      * Request to get whether this device is provisioned with a satellite provider.
      *
-     * @param token The token of the device/subscription to be deprovisioned.
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether this device is provisioned with a satellite provider.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -527,8 +543,8 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void requestIsSatelliteProvisioned(@NonNull String token,
-            @NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
+    public void requestIsSatelliteProvisioned(@NonNull IIntegerConsumer errorCallback,
+            @NonNull IBooleanConsumer callback) {
         // stub implementation
     }
 
@@ -540,6 +556,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -567,6 +584,7 @@
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:NETWORK_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
@@ -591,11 +609,13 @@
      * ISatelliteListener#onSatelliteModemStateChanged.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the current satellite modem state.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -604,7 +624,7 @@
      *   SatelliteError:NO_RESOURCES
      */
     public void requestSatelliteModemState(@NonNull IIntegerConsumer errorCallback,
-            @NonNull ISatelliteModemStateConsumer callback) {
+            @NonNull IIntegerConsumer callback) {
         // stub implementation
     }
 
@@ -612,11 +632,13 @@
      * Request to get whether satellite communication is allowed for the current location.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 whether satellite communication is allowed for the current location.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
@@ -635,11 +657,13 @@
      * This will return 0 if the satellite is currently visible.
      *
      * @param errorCallback The callback to receive the error code result of the operation.
+     *                      This must only be sent when the result is not SatelliteError#ERROR_NONE.
      * @param callback If the result is SatelliteError#ERROR_NONE, the callback to receive
      *                 the time after which the satellite will be visible.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
+     *   SatelliteError:SERVICE_ERROR
      *   SatelliteError:MODEM_ERROR
      *   SatelliteError:INVALID_MODEM_STATE
      *   SatelliteError:INVALID_ARGUMENTS
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index 74b42d4..9593c8a 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -340,16 +340,18 @@
      * Send command to the implementation of {@link SharedConnectivityService} requesting
      * disconnection from the active Tether Network.
      *
+     * @param network {@link TetherNetwork} object representing the network the user has requested
+     *                to disconnect from.
      * @return Returns true if the service received the command. Does not guarantee that the
      *         disconnection was successful.
      */
-    public boolean disconnectTetherNetwork() {
+    public boolean disconnectTetherNetwork(@NonNull TetherNetwork network) {
         if (mService == null) {
             return false;
         }
 
         try {
-            mService.disconnectTetherNetwork();
+            mService.disconnectTetherNetwork(network);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception in disconnectTetherNetwork", e);
             return false;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
index 5d79405..52da596 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -27,7 +27,7 @@
     void registerCallback(in ISharedConnectivityCallback callback);
     void unregisterCallback(in ISharedConnectivityCallback callback);
     void connectTetherNetwork(in TetherNetwork network);
-    void disconnectTetherNetwork();
+    void disconnectTetherNetwork(in TetherNetwork network);
     void connectKnownNetwork(in KnownNetwork network);
     void forgetKnownNetwork(in KnownNetwork network);
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index a0b931f..13084f4 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -117,9 +117,9 @@
             }
 
             @Override
-            public void disconnectTetherNetwork() {
+            public void disconnectTetherNetwork(TetherNetwork network) {
                 checkPermissions();
-                mHandler.post(() -> onDisconnectTetherNetwork());
+                mHandler.post(() -> onDisconnectTetherNetwork(network));
             }
 
             @Override
@@ -323,8 +323,10 @@
      * Implementing application should implement this method.
      *
      * Implementation should initiate a disconnection from the active Tether Network.
+     *
+     * @param network Object identifying the Tether Network the user has requested to disconnect.
      */
-    public abstract void onDisconnectTetherNetwork();
+    public abstract void onDisconnectTetherNetwork(@NonNull TetherNetwork network);
 
     /**
      * Implementing application should implement this method.
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index 815a012..439d456 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -285,25 +285,28 @@
      */
     @Test
     public void disconnectTetherNetwork_serviceNotConnected_shouldFail() {
+        TetherNetwork network = buildTetherNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.disconnectTetherNetwork());
+        assertFalse(manager.disconnectTetherNetwork(network));
     }
 
     @Test
     public void disconnectTetherNetwork() throws RemoteException {
+        TetherNetwork network = buildTetherNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        manager.disconnectTetherNetwork();
-        verify(mService).disconnectTetherNetwork();
+        manager.disconnectTetherNetwork(network);
+        verify(mService).disconnectTetherNetwork(network);
     }
 
     @Test
     public void disconnectTetherNetwork_remoteException_shouldFail() throws RemoteException {
+        TetherNetwork network = buildTetherNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).disconnectTetherNetwork();
-        assertFalse(manager.disconnectTetherNetwork());
+        doThrow(new RemoteException()).when(mService).disconnectTetherNetwork(any());
+        assertFalse(manager.disconnectTetherNetwork(network));
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index e15be8b..fb8d7bf 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -56,7 +56,7 @@
             public void onConnectTetherNetwork(TetherNetwork network) {}
 
             @Override
-            public void onDisconnectTetherNetwork() {}
+            public void onDisconnectTetherNetwork(TetherNetwork network) {}
 
             @Override
             public void onConnectKnownNetwork(KnownNetwork network) {}